Skip to content

Commit

Permalink
Roll forward of Rework interop between closure files and ES6 modules.
Browse files Browse the repository at this point in the history
- Fix goog.require and goog: import in ES6 modules for non-legacy goog.modules.
- Add support for a new path based goog.require to require ES6 modules from goog modules.
- ES6 modules can call "goog.module.declareNamespace('namespace')" to declare a non-legacy goog.module-like namespace. This is for backwards compatibility so users can update their goog.modules to ES6 modules in place. Note this migration path doesn't work for default exports (there is no analogy for "exports = x" in ES6 modules) or for legacy modules (goog.module.declareNamespace does not declare a legacy namespace and we won't add support for it). Library and deps generation support for this will be added in a future change.

NEW: Whitelist polymer for the new mixed module type error. Polymer is generating files with goog.provide and es6 imports because there is no good interop story yet. These files are 100% side effect based, thus nothing should ever reference them, and rewriting doesn't matter.

Automated g4 rollback of changelist 191366556.

*** Reason for rollback ***

Roll forward, whitelisting polymer.

*** Original change description ***

Automated g4 rollback of changelist 191347644.

*** Reason for rollback ***

Tap failures (polymer emits mixed modules).

*** Original change description ***

Rework interop between closure files and ES6 modules.

- Fix goog.require and goog: import in ES6 modules for non-legacy goog.modules.
- Add support for a new path based goog.require to require ES6 modules from goog modules.
- ES6 modules can call "goog.module.declareNamespace('namespace')" to declare a non-legacy goog.module-like namespac...

***

Public: Rework interop between closure files and ES6 modules.

- Fix goog.require and goog: import in ES6 modules for non-legacy goog.modules.
- Add support for a new path based goog.require to require ES6 modules from goog modules.
- ES6 modules can call "goog.module.declareNamespace('namespace')" to declare a non-legacy goog.module-like namespace. This is for backwards compatibility so users can update their goog.modules to ES6 modules in place. Note this migration path doesn't work for default exports (there is no analogy for "exports = x" in ES6 modules) or for legacy modules (goog.module.declareNamespace does not declare a legacy namespace and we won't add support for it). Library and deps generation support for this will be added in a future change.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=191905296
  • Loading branch information
johnplaisted authored and lauraharker committed Apr 7, 2018
1 parent 90e2102 commit 562a178
Show file tree
Hide file tree
Showing 15 changed files with 1,426 additions and 204 deletions.
Expand Up @@ -314,10 +314,11 @@ private void visitScriptNode(NodeTraversal t) {
private boolean isMissingRequire(String namespace, Node node) { private boolean isMissingRequire(String namespace, Node node) {
if (namespace.startsWith("goog.global.") if (namespace.startsWith("goog.global.")
// Most functions in base.js are goog.someName, but // Most functions in base.js are goog.someName, but
// goog.module.{get,declareLegacyNamespace} are the exceptions, so just check for them // goog.module.{get,declareLegacyNamespace,declareNamespace} are the exceptions, so just
// explicitly. // check for them explicitly.
|| namespace.equals("goog.module.get") || namespace.equals("goog.module.get")
|| namespace.equals("goog.module.declareLegacyNamespace")) { || namespace.equals("goog.module.declareLegacyNamespace")
|| namespace.equals("goog.module.declareNamespace")) {
return false; return false;
} }


Expand Down
16 changes: 11 additions & 5 deletions src/com/google/javascript/jscomp/ClosureCheckModule.java
Expand Up @@ -67,10 +67,11 @@ public final class ClosureCheckModule extends AbstractModuleCallback
"JSC_GOOG_MODULE_USES_THROW", "JSC_GOOG_MODULE_USES_THROW",
"The body of a goog.module cannot use 'throw'."); "The body of a goog.module cannot use 'throw'.");


static final DiagnosticType GOOG_MODULE_USES_GOOG_MODULE_GET = DiagnosticType.error( static final DiagnosticType MODULE_USES_GOOG_MODULE_GET =
"JSC_GOOG_MODULE_USES_GOOG_MODULE_GET", DiagnosticType.error(
"It's illegal to use a 'goog.module.get' at the module top-level." "JSC_MODULE_USES_GOOG_MODULE_GET",
+ " Did you mean to use goog.require instead?"); "It's illegal to use a 'goog.module.get' at the module top-level."
+ " Did you mean to use goog.require instead?");


static final DiagnosticType DUPLICATE_NAME_SHORT_REQUIRE = static final DiagnosticType DUPLICATE_NAME_SHORT_REQUIRE =
DiagnosticType.error( DiagnosticType.error(
Expand Down Expand Up @@ -159,6 +160,11 @@ public final class ClosureCheckModule extends AbstractModuleCallback
"JSC_REQUIRE_NOT_AT_TOP_LEVEL", "JSC_REQUIRE_NOT_AT_TOP_LEVEL",
"goog.require() must be called at file scope."); "goog.require() must be called at file scope.");


static final DiagnosticType DECLARE_LEGACY_NAMESPACE_OUTSIDE_GOOG_MODULE =
DiagnosticType.error(
"JSC_DECLARE_LEGACY_NAMESPACE_OUTSIDE_GOOG_MODULE",
"goog.module.declareLegacyNamespace can only be called in goog.modules.");

private final AbstractCompiler compiler; private final AbstractCompiler compiler;


private static class ModuleInfo { private static class ModuleInfo {
Expand Down Expand Up @@ -242,7 +248,7 @@ public void visit(NodeTraversal t, Node n, Node parent) {
|| callee.matchesQualifiedName("goog.forwardDeclare")) { || callee.matchesQualifiedName("goog.forwardDeclare")) {
checkRequireCall(t, n, parent); checkRequireCall(t, n, parent);
} else if (callee.matchesQualifiedName("goog.module.get") && t.inModuleHoistScope()) { } else if (callee.matchesQualifiedName("goog.module.get") && t.inModuleHoistScope()) {
t.report(n, GOOG_MODULE_USES_GOOG_MODULE_GET); t.report(n, MODULE_USES_GOOG_MODULE_GET);
} }
break; break;
case ASSIGN: { case ASSIGN: {
Expand Down
6 changes: 5 additions & 1 deletion src/com/google/javascript/jscomp/ClosureRewriteModule.java
Expand Up @@ -331,7 +331,7 @@ public ScriptDescription removeFirstChildScript() {
if (!this.isModule || this.declareLegacyNamespace) { if (!this.isModule || this.declareLegacyNamespace) {
return null; return null;
} }
return MODULE_EXPORTS_PREFIX + this.legacyNamespace.replace('.', '$'); return getBinaryModuleNamespace(legacyNamespace);
} }


@Nullable @Nullable
Expand All @@ -343,6 +343,10 @@ String getExportedNamespace() {
} }
} }


static String getBinaryModuleNamespace(String legacyNamespace) {
return MODULE_EXPORTS_PREFIX + legacyNamespace.replace('.', '$');
}

private class ScriptPreprocessor extends NodeTraversal.AbstractPreOrderCallback { private class ScriptPreprocessor extends NodeTraversal.AbstractPreOrderCallback {
@Override @Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) { public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
Expand Down
8 changes: 8 additions & 0 deletions src/com/google/javascript/jscomp/CompilerInput.java
Expand Up @@ -394,6 +394,14 @@ void visitSubtree(Node n, Node parent) {
default: default:
return; return;
} }
} else if (parent.isGetProp()
&& parent.matchesQualifiedName("goog.module.declareNamespace")
&& parent.getParent().isCall()) {
Node argument = parent.getParent().getSecondChild();
if (!argument.isString()) {
return;
}
provides.add(argument.getString());
} }
break; break;


Expand Down

0 comments on commit 562a178

Please sign in to comment.