Skip to content

Commit 287fd41

Browse files
kevinoconnor7copybara-github
authored andcommitted
Declare global define aliases that J2clUtilGetDefineRewriterPass can read from
This will allow goog.defines declared in goog.modules to be consumable by J2CL's System.getProperty infrastructure. Since these reads are out-of-scope of the declaration, we need to provide some hook to link the two. To do this we define a global variable to serve as a well-known alias to the define. For the J2CL pass we can assume what the global variable is based on the define name, so we just simply replace the getProperty references with the appropriate global, if it exists. PiperOrigin-RevId: 719370016
1 parent 480bf0e commit 287fd41

File tree

4 files changed

+91
-5
lines changed

4 files changed

+91
-5
lines changed

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ private void rewriteUtilGetDefine(NodeTraversal t, Node callNode) {
6464
}
6565

6666
private Node getDefineReplacement(Node firstExpr, Node secondExpr) {
67-
if (defines.contains(firstExpr.getString())) {
68-
Node define = NodeUtil.newQName(compiler, firstExpr.getString());
67+
String defineName = firstExpr.getString();
68+
if (defines.contains(defineName)) {
69+
Node define = NodeUtil.newQName(compiler, ProcessDefines.getGlobalDefineAlias(defineName));
6970
Node defineStringValue = NodeUtil.newCallNode(IR.name("String"), define);
7071
return IR.comma(secondExpr, defineStringValue);
7172
} else {

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

+41-1
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,31 @@ private void overrideDefines() {
244244

245245
compiler.reportChangeToEnclosingScope(define.valueParent);
246246
}
247+
248+
// When requested, create a globally accessible alias for all define values. This will
249+
// provide a hook for passes like J2clUtilGetDefineRewriterPass to read them in out-of-scope
250+
// contexts.
251+
if (J2clSourceFileChecker.shouldRunJ2clPasses(compiler)) {
252+
String alias = getGlobalDefineAlias(define.defineName);
253+
if (!alias.equals(define.defineName)) {
254+
// If we had:
255+
// var x = goog.define('y', ...);
256+
// we'll add an additional statement:
257+
// var goog$defines$y = x;
258+
Node globalDefineName =
259+
NodeUtil.newName(
260+
compiler, getGlobalDefineAlias(define.defineName), define.valueParent);
261+
Node defineLhs =
262+
define.valueParent.isAssign()
263+
? define.valueParent.getFirstChild().cloneTree()
264+
: define.valueParent.cloneNode();
265+
checkState(defineLhs.isName() || defineLhs.isQualifiedName(), defineLhs);
266+
Node globalDefineVar =
267+
IR.var(globalDefineName, defineLhs).srcrefTreeIfMissing(define.valueParent);
268+
globalDefineVar.insertAfter(define.valueParent.getParent());
269+
compiler.reportChangeToEnclosingScope(define.valueParent.getParent());
270+
}
271+
}
247272
}
248273
}
249274

@@ -261,6 +286,17 @@ private void overrideDefines() {
261286
}
262287
}
263288

289+
static String getGlobalDefineAlias(String defineName) {
290+
// Known defines are already globally accessible and may not be present in code. Therefore we'll
291+
// reference them directly.
292+
// goog.LOCALE is a special case as it's not processed as a define, it is instead
293+
// late-substituted.
294+
if (KNOWN_DEFINES.contains(defineName) || defineName.equals("goog.LOCALE")) {
295+
return defineName;
296+
}
297+
return "jscomp$defines$" + defineName.replace('.', '$');
298+
}
299+
264300
/**
265301
* Returns the replacement value for a @define, if any.
266302
*
@@ -347,7 +383,11 @@ private void collectDefines(Node root) {
347383
}
348384
}
349385
}
350-
compiler.setDefineNames(defineByDefineName.keySet());
386+
compiler.setDefineNames(
387+
ImmutableSet.<String>builder()
388+
.addAll(KNOWN_DEFINES)
389+
.addAll(defineByDefineName.keySet())
390+
.build());
351391
}
352392

353393
private @Nullable Ref selectDefineDeclaration(Name name) {

test/com/google/javascript/jscomp/J2clUtilGetDefineRewriterPassTest.java

+18-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ public void testUtilGetDefine() {
5353
"var a = {};",
5454
"a.b = {}",
5555
"/** @define {boolean} */ a.b.c = true;",
56-
"('def', String(a.b.c));"));
56+
"var jscomp$defines$a$b$c = a.b.c;",
57+
"('def', String(jscomp$defines$a$b$c));"));
5758
test(
5859
lines(
5960
"var a = {};",
@@ -64,7 +65,22 @@ public void testUtilGetDefine() {
6465
"var a = {};",
6566
"a.b = {}",
6667
"/** @define {boolean} */ a.b.c = true;",
67-
"(null, String(a.b.c));"));
68+
"var jscomp$defines$a$b$c = a.b.c;",
69+
"(null, String(jscomp$defines$a$b$c));"));
70+
test(
71+
lines(
72+
"/** @define {boolean} */ var x = goog.define('x', 1);",
73+
"/** @define {boolean} */ var y = goog.define('y', x);",
74+
"nativebootstrap.Util.$getDefine('x');",
75+
"nativebootstrap.Util.$getDefine('y');"),
76+
lines(
77+
"/** @define {boolean} */ var x = 1;",
78+
"var jscomp$defines$x = x;",
79+
"/** @define {boolean} */ var y = x;",
80+
"var jscomp$defines$y = y;",
81+
"(null, String(jscomp$defines$x));",
82+
"(null, String(jscomp$defines$y));"));
83+
test(lines("nativebootstrap.Util.$getDefine('COMPILED');"), "(null, String(COMPILED));");
6884
}
6985

7086
@Test

test/com/google/javascript/jscomp/ProcessDefinesTest.java

+29
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public ProcessDefinesTest() {
4141
private ProcessDefines.Mode mode;
4242
private boolean recognizeClosureDefines = true;
4343

44+
private boolean enableJ2clPasses = false;
45+
4446
@Override
4547
@Before
4648
public void setUp() throws Exception {
@@ -55,6 +57,9 @@ public void setUp() throws Exception {
5557

5658
@Override
5759
protected CompilerPass getProcessor(Compiler compiler) {
60+
if (enableJ2clPasses) {
61+
J2clSourceFileChecker.markToRunJ2clPasses(compiler);
62+
}
5863
return new ProcessDefinesWithInjectedNamespace(compiler);
5964
}
6065

@@ -940,6 +945,30 @@ public void testClosureDefinesErrors_enabledByRecognizeClosureDefines() {
940945
testSame("var CLOSURE_DEFINES = {'FOO': a};");
941946
}
942947

948+
@Test
949+
public void testGenerateGlobalAliases() {
950+
enableJ2clPasses = true;
951+
952+
test(
953+
lines("var a = {};", "/** @define {number} */ a.b = goog.define('a.b', 1);"),
954+
lines("var a = {};", "/** @define {number} */ a.b = 1;", "var jscomp$defines$a$b = a.b;"));
955+
test(
956+
lines("var a = {};", "/** @define {number} */ a.b = goog.define('c.d', 1);"),
957+
lines("var a = {};", "/** @define {number} */ a.b = 1;", "var jscomp$defines$c$d = a.b;"));
958+
test(
959+
"/** @define {number} */ var a = goog.define('c.d', 1);",
960+
lines("/** @define {number} */ var a = 1;", "var jscomp$defines$c$d = a;"));
961+
test(
962+
lines(
963+
"/** @define {number} */ var a = goog.define('a', 1);",
964+
"/** @define {number} */ var b = goog.define('b', a);"),
965+
lines(
966+
"/** @define {number} */ var a = 1;",
967+
"var jscomp$defines$a = a;",
968+
"/** @define {number} */ var b = a;",
969+
"var jscomp$defines$b = b;"));
970+
}
971+
943972
private class ProcessDefinesWithInjectedNamespace implements CompilerPass {
944973
private final Compiler compiler;
945974

0 commit comments

Comments
 (0)