Skip to content

Commit

Permalink
fix(infrastructure): Harden closure declaration source rewriting
Browse files Browse the repository at this point in the history
- Ensure that all JS src files are recursively picked up when sending
  `--js` flag to closure compiler
- Ensure `export ... from ...` statements are covered when rewriting
  declaration sources.
  • Loading branch information
traviskaufman committed Jun 15, 2017
1 parent 184897b commit f5c974c
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 18 deletions.
3 changes: 1 addition & 2 deletions scripts/closure-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ function log() {

CLOSURE_TMP=.closure-tmp
CLOSURE_PKGDIR=$CLOSURE_TMP/packages
JS_SRCS=$CLOSURE_PKGDIR/**/*.js
CLOSURIZED_PKGS=$(node -e "console.log(require('./package.json').closureWhitelist.join(' '))")

if [ -z "$CLOSURIZED_PKGS" ]; then
Expand Down Expand Up @@ -56,7 +55,7 @@ for pkg in $CLOSURIZED_PKGS; do
CMD="java -jar node_modules/google-closure-compiler/compiler.jar \
--externs closure_externs.js \
--compilation_level ADVANCED \
--js $JS_SRCS \
--js $(find $CLOSURE_PKGDIR -type f -name "*.js") \
--language_out ECMASCRIPT5_STRICT \
--dependency_mode STRICT \
--module_resolution LEGACY \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
* - https://github.com/google/closure-compiler/issues/2386
*
* Note that for third-party modules, they must be defined in closure_externs.js. See that file for more info.
* Also note that this works on `export .... from ...` as well.
*/

const assert = require('assert');
Expand Down Expand Up @@ -94,8 +95,10 @@ function transform(srcFile, rootDir) {
});

traverse(ast, {
'ImportDeclaration'({node}) {
rewriteImportDeclaration(node, srcFile, rootDir);
'ImportDeclaration|ExportNamedDeclaration'({node}) {
if (node.source) {
rewriteDeclarationSource(node, srcFile, rootDir);
}
},
});

Expand All @@ -113,38 +116,39 @@ function transform(srcFile, rootDir) {
console.log(`[rewrite] ${srcFile}`);
}

function rewriteImportDeclaration(node, srcFile, rootDir) {
let importSource = node.source.value;
const pathParts = importSource.split('/');
function rewriteDeclarationSource(node, srcFile, rootDir) {
let source = node.source.value;
const pathParts = source.split('/');
const isMDCImport = pathParts[0] === '@material';
if (isMDCImport) {
const modName = pathParts[1]; // @material/<modName>
const atMaterialReplacementPath = `${rootDir}/mdc-${modName}`;
const rewrittenImportSource = [atMaterialReplacementPath].concat(pathParts.slice(2)).join('/');
importSource = rewrittenImportSource;
const rewrittenSource = [atMaterialReplacementPath].concat(pathParts.slice(2)).join('/');
source = rewrittenSource;
}

patchNodeForImportSource(importSource, srcFile, node);
patchNodeForDeclarationSource(source, srcFile, rootDir, node);
}

function patchNodeForImportSource(importSource, srcFile, node) {
let resolvedImportSource = importSource;
function patchNodeForDeclarationSource(source, srcFile, rootDir, node) {
let resolvedSource = source;
// See: https://nodejs.org/api/modules.html#modules_all_together (step 3)
const wouldLoadAsFileOrDir = ['./', '/', '../'].some((s) => importSource.indexOf(s) === 0);
const wouldLoadAsFileOrDir = ['./', '/', '../'].some((s) => source.indexOf(s) === 0);
const isThirdPartyModule = !wouldLoadAsFileOrDir;
if (isThirdPartyModule) {
assert(importSource.indexOf('@material') < 0, '@material/* import sources should have already been rewritten');
assert(source.indexOf('@material') < 0, '@material/* import sources should have already been rewritten');
patchDefaultImportIfNeeded(node);
resolvedImportSource = `goog:mdc.thirdparty.${camelCase(importSource)}`;
resolvedSource = `goog:mdc.thirdparty.${camelCase(source)}`;
} else {
const needsClosureModuleRootResolution = path.isAbsolute(importSource);
const normPath = path.normalize(path.dirname(srcFile), source);
const needsClosureModuleRootResolution = path.isAbsolute(source) || fs.statSync(normPath).isDirectory();
if (needsClosureModuleRootResolution) {
resolvedImportSource = path.relative(rootDir, resolve.sync(importSource, {
resolvedSource = path.relative(rootDir, resolve.sync(source, {
basedir: path.dirname(srcFile),
}));
}
}
node.source = t.stringLiteral(resolvedImportSource);
node.source = t.stringLiteral(resolvedSource);
}

function patchDefaultImportIfNeeded(node) {
Expand Down

0 comments on commit f5c974c

Please sign in to comment.