Skip to content

Commit

Permalink
Move goog.exportSymbol handling from checks to optimizations phase
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 716236673
  • Loading branch information
lauraharker authored and copybara-github committed Jan 16, 2025
1 parent b3bc455 commit 04ba2c5
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 32 deletions.
14 changes: 10 additions & 4 deletions src/com/google/javascript/jscomp/DefaultPassConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -1445,7 +1445,6 @@ public void process(Node externs, Node root) {
final ProcessClosurePrimitives pass = new ProcessClosurePrimitives(compiler);
return (Node externs, Node root) -> {
pass.process(externs, root);
compiler.addExportedNames(pass.getExportedVariableNames());
};
})
.build();
Expand All @@ -1455,9 +1454,16 @@ public void process(Node externs, Node root) {
PassFactory.builder()
.setName("closureProvidesRequires")
.setInternalFactory(
(compiler) ->
new ProcessClosureProvidesAndRequires(
compiler, options.shouldPreservesGoogProvidesAndRequires()))
(compiler) -> {
preprocessorSymbolTableFactory.maybeInitialize(compiler);
final ProcessClosureProvidesAndRequires pass =
new ProcessClosureProvidesAndRequires(
compiler, options.shouldPreservesGoogProvidesAndRequires());
return (Node externs, Node root) -> {
pass.process(externs, root);
compiler.addExportedNames(pass.getExportedVariableNames());
};
})
.build();

/** Process AngularJS-specific annotations. */
Expand Down
19 changes: 0 additions & 19 deletions src/com/google/javascript/jscomp/ProcessClosurePrimitives.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ class ProcessClosurePrimitives extends AbstractPostOrderCallback implements Comp

private final Set<String> knownClosureSubclasses = new LinkedHashSet<>();

private final Set<String> exportedVariables = new LinkedHashSet<>();

private final ImmutableMap<String, ModuleMetadata> closureModules;

ProcessClosurePrimitives(AbstractCompiler compiler) {
Expand All @@ -140,10 +138,6 @@ class ProcessClosurePrimitives extends AbstractPostOrderCallback implements Comp
.getModulesByGoogNamespace();
}

Set<String> getExportedVariableNames() {
return exportedVariables;
}

@Override
public void process(Node externs, Node root) {
// Replace and validate other Closure primitives
Expand Down Expand Up @@ -244,24 +238,11 @@ private void checkGoogFunctions(NodeTraversal t, Node call) {
// when we see a provides/requires, and don't worry about
// reporting the change when we actually do the replacement.
String methodName = callee.getString();
Node arg = callee.getNext();
switch (methodName) {
case "inherits":
// Note: inherits is allowed in local scope
processInheritsCall(call);
break;
case "exportSymbol":
// Note: exportSymbol is allowed in local scope
if (arg.isStringLit()) {
String argString = arg.getString();
int dot = argString.indexOf('.');
if (dot == -1) {
exportedVariables.add(argString);
} else {
exportedVariables.add(argString.substring(0, dot));
}
}
break;
case "addDependency":
if (validateUnaliasablePrimitiveCall(t, call, methodName)) {
processAddDependency(call);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class ProcessClosureProvidesAndRequires implements CompilerPass {
// Use a LinkedHashMap because the goog.provides must be processed in a deterministic order.
private final Map<String, ProvidedName> providedNames = new LinkedHashMap<>();

private final Set<String> exportedVariables = new LinkedHashSet<>();

// If this is true, rewriting will not remove any goog.provide or goog.require calls
private final boolean preserveGoogProvidesAndRequires;
private final List<Node> requiresToBeRemoved = new ArrayList<>();
Expand All @@ -85,6 +87,10 @@ public void process(Node externs, Node root) {
rewriteProvidesAndRequires(externs, root);
}

Set<String> getExportedVariableNames() {
return exportedVariables;
}

/** Collects all `goog.provide`s in the given namespace and warns on invalid code */
Map<String, ProvidedName> collectProvidedNames(Node externs, Node root) {
if (this.providedNames.isEmpty()) {
Expand Down Expand Up @@ -152,6 +158,19 @@ public void visit(NodeTraversal t, Node n, Node parent) {
// when we see a provides/requires, and don't worry about
// reporting the change when we actually do the replacement.
switch (left.getString()) {
case "exportSymbol":
// Note: exportSymbol is allowed in local scope
Node arg = n.getSecondChild();
if (arg.isStringLit()) {
String argString = arg.getString();
int dot = argString.indexOf('.');
if (dot == -1) {
exportedVariables.add(argString);
} else {
exportedVariables.add(argString.substring(0, dot));
}
}
break;
case "require":
case "requireType":
if (isValidPrimitiveCall(t, n)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private static final String lines(String... lines) {
" * @template T",
" */",
"goog.define = function(name, defaultValue) {};",
"goog.exportSymbol = function() {};",
"goog.exportSymbol = function(publicName, symbol) {};",
"goog.inherits = function(childCtor, parentCtor) {",
" childCtor.superClass_ = parentCtor.prototype;",
"};",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public ProcessClosureProvidesAndRequiresTest() {
}

private boolean preserveGoogProvidesAndRequires;
private ProcessClosureProvidesAndRequires lastProcessor;

private ProcessClosureProvidesAndRequires createClosureProcessor(Compiler compiler) {
return new ProcessClosureProvidesAndRequires(compiler, preserveGoogProvidesAndRequires);
Expand All @@ -53,14 +54,15 @@ public void setUp() throws Exception {
enableTypeCheck();
enableCreateModuleMap(); // necessary for the typechecker
replaceTypesWithColors();
lastProcessor = null;
}

@Override
protected CompilerPass getProcessor(Compiler compiler) {
return (Node externs, Node root) -> {
verifyCollectProvidedNamesDoesntChangeAst(externs, root, compiler);
ProcessClosureProvidesAndRequires processor = createClosureProcessor(compiler);
processor.rewriteProvidesAndRequires(externs, root);
lastProcessor = createClosureProcessor(compiler);
lastProcessor.rewriteProvidesAndRequires(externs, root);
};
}

Expand Down Expand Up @@ -938,6 +940,20 @@ public void testEsModule_ignored() {
assertThat(providedNameMap.keySet()).containsExactly("goog");
}

@Test
public void testGoogExportSymbolRecording() {
testSame(
"""
goog.exportSymbol('a', 0);
goog.exportSymbol('foo.bar.baz', 1);
goog.exportSymbol(notAStringLiteral, 2);
function f() {
goog.exportSymbol('b', 3);
}
""");
assertThat(lastProcessor.getExportedVariableNames()).containsExactly("a", "foo", "b");
}

private Map<String, ProvidedName> getProvidedNameCollection(String js) {
Compiler compiler = createCompiler();
ProcessClosureProvidesAndRequires processor = createClosureProcessor(compiler);
Expand Down
3 changes: 2 additions & 1 deletion test/com/google/javascript/jscomp/RenameVarsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1186,7 +1186,8 @@ public void process(Node externs, Node root) {
new GatherModuleMetadata(
compiler, /* processCommonJsModules= */ false, ResolutionMode.BROWSER)
.process(externs, root);
ProcessClosurePrimitives closurePass = new ProcessClosurePrimitives(compiler);
ProcessClosureProvidesAndRequires closurePass =
new ProcessClosureProvidesAndRequires(compiler, true);
closurePass.process(externs, root);
renameVars =
new RenameVars(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,13 +382,11 @@ public void exportSymbol_preventsVariableRenamingCollision() throws IOException
Compiler compiler = compileTypedAstShards(options);

assertCompiledCodeEquals(
// TODO - b/389980981: don't reuse the name 'a' in variable renaming 'a' because it's also
// used in the goog.exportSymbol call.
compiler,
lines(
"var a;", //
"var b;",
"a.exportSymbol('a', b);"));
"var b;", //
"var c;",
"b.exportSymbol('a', c);"));
}

@Test
Expand Down

0 comments on commit 04ba2c5

Please sign in to comment.