Skip to content

Commit

Permalink
Fix Polymer pass from generating code outside goog.loadModule
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=263662505
  • Loading branch information
rishipal authored and lauraharker committed Aug 16, 2019
1 parent 406f482 commit 1e5bd8c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 10 deletions.
41 changes: 31 additions & 10 deletions src/com/google/javascript/jscomp/PolymerClassRewriter.java
Expand Up @@ -18,6 +18,7 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.javascript.jscomp.NodeUtil.isBundledGoogModuleCall;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
Expand Down Expand Up @@ -66,6 +67,15 @@ final class PolymerClassRewriter {
this.propertyRenamingEnabled = propertyRenamingEnabled;
}

static boolean isFunctionArgInGoogLoadModule(Node n) {
if (!n.isFunction()) {
return false;
}

Node parent = n.getParent();
return parent != null && isBundledGoogModuleCall(parent);
}

/**
* Rewrites a given call to Polymer({}) to a set of declarations and assignments which can be
* understood by the compiler.
Expand Down Expand Up @@ -141,16 +151,28 @@ void rewritePolymerCall(
// module scopes are well-supported. If this is not in a module or the global scope it is likely
// exported.
if (!isInGlobalOrModuleScope && !cls.target.isGetProp()) {
Node scriptOrModuleNode =
NodeUtil.getEnclosingNode(parent, node -> node.isScript() || node.isModuleBody());
if (scriptOrModuleNode.isModuleBody()
&& scriptOrModuleNode.getParent().getBooleanProp(Node.GOOG_MODULE)) {
Node enclosingNode =
NodeUtil.getEnclosingNode(
parent,
node ->
node.isScript() || node.isModuleBody() || isFunctionArgInGoogLoadModule(node));
if (enclosingNode.isModuleBody()
&& enclosingNode.getParent().getBooleanProp(Node.GOOG_MODULE)) {
// The goog.module('ns'); call must remain the first statement in the module.
Node insertionPoint = getInsertionPointForGoogModule(scriptOrModuleNode);
scriptOrModuleNode.addChildrenAfter(statements, insertionPoint);
} else {
scriptOrModuleNode.addChildrenToFront(statements);
compiler.reportChangeToChangeScope(NodeUtil.getEnclosingScript(scriptOrModuleNode));
Node insertionPoint = getInsertionPointForGoogModule(enclosingNode);
enclosingNode.addChildrenAfter(statements, insertionPoint);
} else if (enclosingNode.isScript()) {
enclosingNode.addChildrenToFront(statements);
compiler.reportChangeToChangeScope(NodeUtil.getEnclosingScript(enclosingNode));
} else if (enclosingNode.isFunction()) {
Node functionBlock = enclosingNode.getLastChild();
Node insertionPoint = getInsertionPointForGoogModule(functionBlock);
// Node insertionPoint will be null here if functionBlock does not contain a goog.module()
// Missing goog.module inside the loadModule's functionBlock is semantically incorrect
// That will cause the compiler to crash in closureRewriteModule pass.
if (insertionPoint != null) {
functionBlock.addChildrenAfter(statements, insertionPoint);
}
}
} else {
Node beforeRoot = exprRoot.getPrevious();
Expand Down Expand Up @@ -996,7 +1018,6 @@ private static boolean isParamLiteral(String param) {
}

private static Node getInsertionPointForGoogModule(Node moduleBody) {
checkArgument(moduleBody.isModuleBody(), moduleBody);
Node insertionPoint = moduleBody.getFirstChild(); // goog.module('ns');
Node next = insertionPoint.getNext();
while ((NodeUtil.isNameDeclaration(next)
Expand Down
21 changes: 21 additions & 0 deletions test/com/google/javascript/jscomp/PolymerClassRewriterTest.java
Expand Up @@ -79,6 +79,27 @@ public void setUp() throws Exception {

// TODO(jlklein): Add tests for non-global definitions, interface externs, read-only setters, etc.

@Test
public void testPolymerWriterGeneratesCodeInsideLoadModule() {
inGlobalScope = false;
test(
lines(
"goog.loadModule(function(exports) {",
" goog.module('ytu.app.ui.shared.YtuIcon');",
" YtuIcon = Polymer({is: 'ytu-icon' });",
" exports = YtuIcon;",
" return exports;",
"})"),
lines(
"goog.loadModule(function(exports) {",
" goog.module('ytu.app.ui.shared.YtuIcon');",
" var YtuIcon = function(){}",
" YtuIcon = Polymer(/** @lends {YtuIcon.prototype} */ {is:\"ytu-icon\"});",
" exports = YtuIcon;",
" return exports;",
"})"));
}

@Test
public void testVarTarget() {
test(
Expand Down

0 comments on commit 1e5bd8c

Please sign in to comment.