Skip to content

Commit 43850b5

Browse files
shickscopybara-github
authored andcommitted
Consolidate all of ReplaceToggles into a single optimization pass
PiperOrigin-RevId: 560882626
1 parent d186a48 commit 43850b5

File tree

5 files changed

+89
-159
lines changed

5 files changed

+89
-159
lines changed

src/com/google/javascript/jscomp/AbstractCompiler.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.google.common.base.Splitter;
2424
import com.google.common.base.Strings;
2525
import com.google.common.collect.ImmutableList;
26-
import com.google.common.collect.ImmutableMap;
2726
import com.google.common.collect.ImmutableSet;
2827
import com.google.errorprone.annotations.MustBeClosed;
2928
import com.google.errorprone.annotations.OverridingMethodsMustInvokeSuper;
@@ -713,15 +712,4 @@ public final LogFile createOrReopenIndexedLog(
713712
* rewriting has not occurred.
714713
*/
715714
abstract void mergeSyntheticCodeInput();
716-
717-
/**
718-
* Records the mapping of toggle names to ordinals, which is read from a bootstrap JS file by the
719-
* first (check) pass of {@link RewriteToggles}.
720-
*/
721-
void setToggleOrdinalMapping(@Nullable ImmutableMap<String, Integer> mapping) {}
722-
723-
/** Returns the recorded toggle-name-to-ordinal mapping. */
724-
@Nullable ImmutableMap<String, Integer> getToggleOrdinalMapping() {
725-
return null;
726-
}
727715
}

src/com/google/javascript/jscomp/Compiler.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,6 @@ public SourceFile loadSource(String filename) {
290290

291291
private final Timeline<Node> changeTimeline = new Timeline<>();
292292

293-
private @Nullable ImmutableMap<String, Integer> toggleOrdinalMapping = null;
294-
295293
/**
296294
* When mapping symbols from a source map, we must repeatedly combine the path of the original
297295
* file with the path from the source map to compute the SourceFile of the underlying code. When
@@ -4327,14 +4325,4 @@ private static Node checkNotModule(Node script, String msg, Object... args) {
43274325
checkState(!script.getFirstChild().isModuleBody(), msg, args);
43284326
return script;
43294327
}
4330-
4331-
@Override
4332-
void setToggleOrdinalMapping(@Nullable ImmutableMap<String, Integer> mapping) {
4333-
this.toggleOrdinalMapping = mapping;
4334-
}
4335-
4336-
@Override
4337-
@Nullable ImmutableMap<String, Integer> getToggleOrdinalMapping() {
4338-
return toggleOrdinalMapping;
4339-
}
43404328
}

src/com/google/javascript/jscomp/DefaultPassConfig.java

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,6 @@ protected PassListBuilder getChecks() {
351351

352352
if (options.closurePass) {
353353
checks.maybeAdd(closurePrimitives);
354-
checks.maybeAdd(replaceTogglesCheck);
355354
}
356355

357356
// It's important that the PolymerPass run *after* the ClosurePrimitives and ChromePass rewrites
@@ -2053,23 +2052,12 @@ public void process(Node externs, Node jsRoot) {
20532052
.setInternalFactory(ConstParamCheck::new)
20542053
.build();
20552054

2056-
private final PassFactory replaceTogglesCheck = createReplaceToggles(true);
2057-
private final PassFactory replaceToggles = createReplaceToggles(false);
2058-
20592055
/** Replaces goog.toggle calls with toggle lookups. */
2060-
private final PassFactory createReplaceToggles(boolean check) {
2061-
return PassFactory.builder()
2062-
.setName("replaceToggles" + (check ? "Check" : ""))
2063-
.setInternalFactory(
2064-
(compiler) ->
2065-
new CompilerPass() {
2066-
@Override
2067-
public void process(Node externs, Node root) {
2068-
new ReplaceToggles(compiler, check).process(externs, root);
2069-
}
2070-
})
2071-
.build();
2072-
}
2056+
private final PassFactory replaceToggles =
2057+
PassFactory.builder()
2058+
.setName("replaceToggles")
2059+
.setInternalFactory(ReplaceToggles::new)
2060+
.build();
20732061

20742062
/** Generates unique ids. */
20752063
private final PassFactory replaceIdGenerators =

src/com/google/javascript/jscomp/ReplaceToggles.java

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package com.google.javascript.jscomp;
1818

19-
import com.google.common.annotations.VisibleForTesting;
2019
import com.google.common.collect.ImmutableMap;
2120
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
2221
import com.google.javascript.rhino.Node;
@@ -26,13 +25,21 @@
2625
import java.util.LinkedHashMap;
2726
import java.util.Map;
2827
import java.util.Set;
28+
import org.jspecify.nullness.Nullable;
2929

3030
/**
3131
* Replaces calls to id generators with ids.
3232
*
3333
* <p>Use this to get unique and short ids.
3434
*/
3535
class ReplaceToggles implements CompilerPass {
36+
37+
// NOTE: These diagnostics are only checked in Stage 2 (optimization), since none of this
38+
// code should ever be hand-written: the `CLOSURE_TOGGLE_ORDINALS` bootstrap and the calls to
39+
// `goog.readToggleInternalDoNotCallDirectly` are all generated automatically by the build
40+
// system, so it's unexpected that anyone should ever run into these diagnostics when doing
41+
// ordinary development.
42+
3643
static final DiagnosticType INVALID_TOGGLE_PARAMETER =
3744
DiagnosticType.error(
3845
"JSC_INVALID_TOGGLE_PARAMETER",
@@ -53,18 +60,17 @@ class ReplaceToggles implements CompilerPass {
5360
// NOTE: These values are chosen as negative integers because actual toggle ordinals must always
5461
// be non-negative (at least zero). Any negative integers would do to distinguish them from real
5562
// toggle ordinals, but -1 and -2 are the simplest.
56-
@VisibleForTesting static final int TRUE_VALUE = -2;
57-
58-
@VisibleForTesting static final int FALSE_VALUE = -1;
63+
private static final int TRUE_VALUE = -2;
64+
private static final int FALSE_VALUE = -1;
5965

6066
private final AbstractCompiler compiler;
6167
private final AstFactory astFactory;
62-
private final boolean check;
6368

64-
ReplaceToggles(AbstractCompiler compiler, boolean check) {
69+
private @Nullable ImmutableMap<String, Integer> ordinalMapping = null;
70+
71+
ReplaceToggles(AbstractCompiler compiler) {
6572
this.compiler = compiler;
6673
this.astFactory = compiler.createAstFactory();
67-
this.check = check;
6874
}
6975

7076
@Override
@@ -80,20 +86,21 @@ private class Traversal extends AbstractPostOrderCallback {
8086

8187
@Override
8288
public void visit(NodeTraversal t, Node n, Node parent) {
83-
// Look for `var CLOSURE_TOGGLE_ORDINALS = {...};`. Note that we only do this in check mode.
84-
// It's not our responsibility to delete the unused variable in optimized mode - if all
85-
// the calls to readToggle are deleted, then the bootstrap will be unused and deleted, too.
86-
if (check
87-
&& NodeUtil.isNameDeclaration(n)
88-
&& n.getFirstChild().matchesName(ORDINAL_VAR_NAME)) {
89+
// Look for `var CLOSURE_TOGGLE_ORDINALS = {...};`, record the mapping, and then delete the
90+
// declaration from the AST since we should no longer need it (and the optimizer won't
91+
// delete it in case the global assignment was an intended side effect).
92+
if (NodeUtil.isNameDeclaration(n) && n.getFirstChild().matchesName(ORDINAL_VAR_NAME)) {
8993
Node rhs = n.getFirstFirstChild();
9094

9195
if (rhs == null && n.getToken() == Token.VAR) {
92-
// An empty var is a type definition, which is OK.
96+
// An empty var is fine; it should get deleted later.
9397
return;
9498
} else if (!rhs.isObjectLit()) {
9599
compiler.report(JSError.make(n, INVALID_ORDINAL_MAPPING, "not an object literal"));
96100
return;
101+
} else if (ordinalMapping != null) {
102+
compiler.report(JSError.make(n, INVALID_ORDINAL_MAPPING, "multiple initialized copies"));
103+
return;
97104
}
98105

99106
Map<String, Integer> mapping = new LinkedHashMap<>();
@@ -126,10 +133,10 @@ public void visit(NodeTraversal t, Node n, Node parent) {
126133
mapping.put(key, intValue);
127134
ordinals.add(intValue);
128135
}
129-
compiler.setToggleOrdinalMapping(ImmutableMap.copyOf(mapping));
136+
ReplaceToggles.this.ordinalMapping = ImmutableMap.copyOf(mapping);
130137

131138
// NOTE: We do not support a simple assignment without `var` since reassignment or later
132-
// augmentation is not allowed.
139+
// augmentation (i.e. `CLOSURE_TOGGLE_ORDINALS['foo'] = true`) is not allowed.
133140
return;
134141
}
135142

@@ -147,15 +154,11 @@ public void visit(NodeTraversal t, Node n, Node parent) {
147154
return;
148155
}
149156

150-
ImmutableMap<String, Integer> toggles = compiler.getToggleOrdinalMapping();
151-
if (check) {
152-
if (toggles != null && !toggles.containsKey(arg.getString())) {
153-
compiler.report(JSError.make(n, UNKNOWN_TOGGLE));
154-
}
155-
return;
157+
if (ordinalMapping != null && !ordinalMapping.containsKey(arg.getString())) {
158+
compiler.report(JSError.make(n, UNKNOWN_TOGGLE));
156159
}
157160

158-
Integer ordinal = toggles != null ? toggles.get(arg.getString()) : null;
161+
Integer ordinal = ordinalMapping != null ? ordinalMapping.get(arg.getString()) : null;
159162
if (ordinal == null || ordinal < 0) {
160163
// No ordinals given: hard-code `true` if explicitly set as true, or `false` otherwise.
161164
n.replaceWith(

0 commit comments

Comments
 (0)