Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ampproject/rollup-plugin-closure-compiler

Package Overview
Dependencies
Maintainers
3
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ampproject/rollup-plugin-closure-compiler - npm Package Compare versions

Comparing version 0.4.3 to 0.5.0-alpha.1

dist/index.mjs

600

dist/index.js
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var path = require('path');
var tempWrite = require('temp-write');
var MagicString = _interopDefault(require('magic-string'));
var googleClosureCompiler = require('google-closure-compiler');

@@ -23,13 +27,5 @@ var fs = require('fs');

*/
// @see https://github.com/estree/estree/blob/master/es2015.md#exports
const EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration';
const EXPORT_SPECIFIER = 'ExportSpecifier';
const EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration';
const EXPORT_ALL_DECLARATION = 'ExportAllDeclaration';
const ALL_EXPORT_TYPES = [
EXPORT_NAMED_DECLARATION,
EXPORT_SPECIFIER,
EXPORT_DEFAULT_DECLARATION,
EXPORT_ALL_DECLARATION,
];
// @see https://github.com/estree/estree/blob/master/es2015.md#imports
const IMPORT_DECLARATION = 'ImportDeclaration';
const ALL_IMPORT_DECLARATIONS = [IMPORT_DECLARATION];
var ExportClosureMapping;

@@ -40,9 +36,12 @@ (function (ExportClosureMapping) {

ExportClosureMapping[ExportClosureMapping["NAMED_DEFAULT_FUNCTION"] = 2] = "NAMED_DEFAULT_FUNCTION";
ExportClosureMapping[ExportClosureMapping["NAMED_DEFAULT_CLASS"] = 3] = "NAMED_DEFAULT_CLASS";
ExportClosureMapping[ExportClosureMapping["NAMED_CONSTANT"] = 4] = "NAMED_CONSTANT";
ExportClosureMapping[ExportClosureMapping["DEFAULT"] = 5] = "DEFAULT";
ExportClosureMapping[ExportClosureMapping["DEFAULT_FUNCTION"] = 3] = "DEFAULT_FUNCTION";
ExportClosureMapping[ExportClosureMapping["NAMED_DEFAULT_CLASS"] = 4] = "NAMED_DEFAULT_CLASS";
ExportClosureMapping[ExportClosureMapping["DEFAULT_CLASS"] = 5] = "DEFAULT_CLASS";
ExportClosureMapping[ExportClosureMapping["NAMED_CONSTANT"] = 6] = "NAMED_CONSTANT";
ExportClosureMapping[ExportClosureMapping["DEFAULT"] = 7] = "DEFAULT";
})(ExportClosureMapping || (ExportClosureMapping = {}));
class Transform {
constructor(context) {
constructor(context, inputOptions) {
this.context = context;
this.inputOptions = inputOptions;
}

@@ -65,2 +64,18 @@ extern(options) {

}
isEntryPoint(id) {
const inputs = (input) => {
if (typeof this.inputOptions.input === 'string') {
return [this.inputOptions.input];
}
else if (typeof this.inputOptions.input === 'object') {
return Object.values(this.inputOptions.input);
}
else {
return this.inputOptions.input;
}
};
return inputs(this.inputOptions.input)
.map(input => path.resolve(input))
.includes(id);
}
}

@@ -121,13 +136,13 @@

const exportSpecifierName = (exportSpecifier) => exportSpecifier.exported.name;
function functionDeclarationName(context, declaration) {
const camelcase = (input) => input
.replace(/^[_.\- ]+/, '')
.toLowerCase()
.replace(/[_.\- ]+(\w|$)/g, (m, p1) => p1.toUpperCase());
function functionDeclarationName(context, id, declaration) {
// For the Declaration passed, there can be a function declaration.
if (declaration.declaration && declaration.declaration.type === 'FunctionDeclaration') {
const functionDeclaration = declaration.declaration;
if (functionDeclaration === null ||
functionDeclaration.id === null ||
functionDeclaration.id.name === null) {
context.error(`Plugin requires exports to be named, 'export function Foo(){}' not 'export function(){}'`);
}
else {
// This function declaration is the export name we need to know.
if (functionDeclaration !== null &&
functionDeclaration.id !== null &&
functionDeclaration.id.name !== null) {
return functionDeclaration.id.name;

@@ -138,12 +153,9 @@ }

}
function classDeclarationName(context, declaration) {
function classDeclarationName(context, id, declaration) {
// For the Declaration passed, there can be a function declaration.
if (declaration.declaration && declaration.declaration.type === 'ClassDeclaration') {
const classDeclaration = declaration.declaration;
if (classDeclaration === null ||
classDeclaration.id === null ||
classDeclaration.id.name === null) {
context.error(`Plugin requires exports to be named, 'export class Foo(){}' not 'export class(){}'`);
}
else {
if (classDeclaration !== null &&
classDeclaration.id !== null &&
classDeclaration.id.name !== null) {
// This class declaration is the export name we need to know.

@@ -155,5 +167,8 @@ return classDeclaration.id.name;

}
function NamedDeclaration(context, declaration) {
const functionName = functionDeclarationName(context, declaration);
const className = classDeclarationName(context, declaration);
function NamedDeclaration(context, id, declaration) {
const functionName = functionDeclarationName(context, id, declaration);
const className = classDeclarationName(context, id, declaration);
// console.log(functionName, className);
// TODO(KB): This logic isn't great. If something has a named declaration, lets instead use the AST to find out what it is.
// var Foo=function(){}export{Foo as default} => default export function
if (functionName !== null) {

@@ -170,2 +185,3 @@ return {

else if (declaration.specifiers) {
// console.log(declaration.specifiers);
const exportMap = {};

@@ -179,7 +195,7 @@ declaration.specifiers.forEach(exportSpecifier => {

}
function DefaultDeclaration(context, declaration) {
function DefaultDeclaration(context, id, declaration) {
if (declaration.declaration) {
switch (declaration.declaration.type) {
case 'FunctionDeclaration':
const functionName = functionDeclarationName(context, declaration);
const functionName = functionDeclarationName(context, id, declaration);
if (functionName !== null) {

@@ -190,3 +206,11 @@ return {

}
break;
else {
// When Rollup encounters a default export that is unnamed,
// it uses camelCase(filename) of the id to name the function.
// THIS IS NOT INTUITIVE!
const functionName = camelcase(path.basename(id, '.js'));
return {
[functionName]: ExportClosureMapping.DEFAULT_FUNCTION,
};
}
case 'Identifier':

@@ -200,3 +224,3 @@ if (declaration.declaration.name) {

case 'ClassDeclaration':
const className = classDeclarationName(context, declaration);
const className = classDeclarationName(context, id, declaration);
if (className !== null) {

@@ -207,3 +231,11 @@ return {

}
break;
else {
// When Rollup encounters a default export that is unnamed,
// it uses camelCase(filename) of the id to name the class.
// THIS IS NOT INTUITIVE!
const className = camelcase(path.basename(id, '.js'));
return {
[className]: ExportClosureMapping.DEFAULT_CLASS,
};
}
}

@@ -213,2 +245,17 @@ }

}
function literalName(context, id, literal) {
// Literal can either be a SimpleLiteral, or RegExpLiteral
if ('regex' in literal) {
// This is a RegExpLiteral
context.warn('Rollup Plugin Closure Compiler found a Regex Literal Named Import. `import foo from "*/.hbs"`');
return '';
}
const literalValue = literal.value;
return typeof literalValue === 'string' ? literalValue : '';
}
// export function ImportDeclaration(
// context: PluginContext,
// id: string,
// declaration: ImportDeclaration,
// ):

@@ -246,3 +293,3 @@ /**

*/
const defaults = (options, transformers) => {
const defaults = (options, providedExterns, transformers) => {
// Defaults for Rollup Projects are slightly different than Closure Compiler defaults.

@@ -256,8 +303,11 @@ // - Users of Rollup tend to transpile their code before handing it to a minifier,

const externs = transformers
? transformers.map(transform => tempWrite.sync(transform.extern(options)))
: '';
? transformers.map(transform => tempWrite.sync(transform.extern(options))).concat(providedExterns)
: providedExterns.length > 0
? providedExterns
: '';
return {
language_out: 'NO_TRANSPILE',
assume_function_wrapper: isESMFormat(options.format) ? true : false,
assume_function_wrapper: isESMFormat(options.format),
warning_level: 'QUIET',
module_resolution: 'NODE',
externs,

@@ -277,11 +327,17 @@ };

const mapFile = tempWrite.sync('');
return [
{
...defaults(outputOptions, transforms),
...compileOptions,
js: tempWrite.sync(code),
create_source_map: mapFile,
},
mapFile,
];
const externs = (compileOptions) => {
if ('externs' in compileOptions) {
switch (typeof compileOptions.externs) {
case 'boolean':
return [];
case 'string':
return [compileOptions.externs];
default:
return compileOptions.externs;
}
}
return [];
};
const options = Object.assign({}, defaults(outputOptions, externs(compileOptions), transforms), compileOptions, { js: tempWrite.sync(code), create_source_map: mapFile });
return [options, mapFile];
}

@@ -304,8 +360,3 @@

*/
const HEADER$1 = `/**
* @fileoverview Externs built via derived configuration from Rollup or input code.
* This extern contains top level exported members.
* @externs
*/
`;
const walk = require('acorn/dist/walk');
/**

@@ -322,48 +373,35 @@ * This Transform will apply only if the Rollup configuration is for 'esm' output.

super(...arguments);
this.exported = {};
this.originalExports = {};
}
extern(options$$1) {
let content = HEADER$1;
if (isESMFormat(options$$1.format)) {
Object.keys(this.exported).forEach(key => {
content += `window['${key}'] = ${key};\n`;
});
}
return content;
}
/**
* Before Closure Compiler is given a chance to look at the code, we need to
* find and store all export statements with their correct type
* @param code source to parse, and modify
* @param code source to parse
* @param id Rollup id reference to the source
* @return Promise containing the modified source
*/
async deriveFromInputSource(code, id) {
const program = this.context.parse(code, {});
const exportNodes = program.body.filter(node => ALL_EXPORT_TYPES.includes(node.type));
exportNodes.forEach((node) => {
switch (node.type) {
case EXPORT_NAMED_DECLARATION:
const namedDeclarationValues = NamedDeclaration(this.context, node);
if (this.isEntryPoint(id)) {
const context = this.context;
let originalExports = {};
const program = context.parse(code, { ranges: true });
walk.simple(program, {
ExportNamedDeclaration(node) {
const namedDeclarationValues = NamedDeclaration(context, id, node);
if (namedDeclarationValues !== null) {
this.exported = { ...this.exported, ...namedDeclarationValues };
originalExports = Object.assign({}, originalExports, namedDeclarationValues);
}
break;
case EXPORT_DEFAULT_DECLARATION:
// TODO(KB): This case is not fully supported – only named default exports.
// `export default Foo(){};`, or `export default Foo;`, not `export default function(){};`
const defaultDeclarationValue = DefaultDeclaration(this.context, node);
},
ExportDefaultDeclaration(node) {
const defaultDeclarationValue = DefaultDeclaration(context, id, node);
if (defaultDeclarationValue !== null) {
this.exported = { ...this.exported, ...defaultDeclarationValue };
originalExports = Object.assign({}, originalExports, defaultDeclarationValue);
}
break;
case EXPORT_ALL_DECLARATION:
},
ExportAllDeclaration(node) {
// TODO(KB): This case `export * from "./import"` is not currently supported.
this.context.error(new Error(`Rollup Plugin Closure Compiler does not support export all syntax.`));
break;
default:
this.context.error(new Error(`Rollup Plugin Closure Compiler found unsupported module declaration type, ${node.type}`));
break;
}
});
context.error(new Error(`Rollup Plugin Closure Compiler does not support export all syntax.`));
},
});
this.originalExports = originalExports;
}
return void 0;

@@ -383,7 +421,12 @@ }

else if (isESMFormat(this.outputOptions.format)) {
Object.keys(this.exported).forEach(key => {
code += `\nwindow['${key}'] = ${key}`;
const source = new MagicString(code);
// Window scoped references for each key are required to ensure Closure Compilre retains the code.
Object.keys(this.originalExports).forEach(key => {
source.append(`\nwindow['${key}'] = ${key}`);
});
return {
code: source.toString(),
map: source.generateMap(),
};
}
// TODO(KB): Sourcemaps fail :(
return {

@@ -405,50 +448,185 @@ code,

else if (isESMFormat(this.outputOptions.format)) {
const exportedConstants = [];
Object.keys(this.exported).forEach(key => {
switch (this.exported[key]) {
case ExportClosureMapping.NAMED_FUNCTION:
code = code.replace(`window.${key}=function`, `export function ${key}`);
break;
case ExportClosureMapping.NAMED_CLASS:
const namedClassMatch = new RegExp(`window.${key}=(\\w+);`).exec(code);
if (namedClassMatch && namedClassMatch.length > 0) {
// Remove the declaration on window scope, i.e. `window.Exported=a;`
code = code.replace(namedClassMatch[0], '');
// Store a new export constant to output at the end. `a as Exported`
exportedConstants.push(`${namedClassMatch[1]} as ${key}`);
}
break;
case ExportClosureMapping.NAMED_DEFAULT_FUNCTION:
code = code.replace(`window.${key}=function`, `export default function ${key}`);
break;
case ExportClosureMapping.NAMED_DEFAULT_CLASS:
const namedDefaultClassMatch = new RegExp(`window.${key}=(\\w+);`).exec(code);
if (namedDefaultClassMatch && namedDefaultClassMatch.length > 0) {
// Remove the declaration on window scope, i.e. `window.ExportedTwo=a;`
// Replace it with an export statement `export default a;`
code = code.replace(namedDefaultClassMatch[0], `export default ${namedDefaultClassMatch[1]};`);
}
break;
case ExportClosureMapping.NAMED_CONSTANT:
// Remove the declaration on the window scope, i.e. `window.ExportedThree=value`
// Replace it with a const declaration, i.e `const ExportedThree=value`
code = code.replace(`window.${key}=`, `const ${key}=`);
// Store a new export constant to output at the end, i.e `ExportedThree`
exportedConstants.push(key);
break;
default:
this.context.warn('Rollup Plugin Closure Compiler could not restore all exports statements.');
break;
}
const source = new MagicString(code);
const program = this.context.parse(code, { ranges: true });
const collectedExportsToAppend = [];
const originalExports = this.originalExports;
const originalExportIdentifiers = Object.keys(originalExports);
source.trimEnd();
walk.ancestor(program, {
// We inserted window scoped assignments for all the export statements during `preCompilation`
// window['exportName'] = exportName;
// Now we need to find where Closure Compiler moved them, and restore the exports of their name.
// ASTExporer Link: https://astexplorer.net/#/gist/94f185d06a4105d64828f1b8480bddc8/0fc5885ae5343f964d0cdd33c7d392a70cf5fcaf
Identifier(node, ancestors) {
if (node.name === 'window') {
ancestors.forEach((ancestor) => {
if (ancestor.type === 'ExpressionStatement' &&
ancestor.expression.type === 'AssignmentExpression' &&
ancestor.expression.left.type === 'MemberExpression' &&
ancestor.expression.left.object.type === 'Identifier' &&
ancestor.expression.left.object.name === 'window' &&
ancestor.expression.left.property.type === 'Identifier' &&
originalExportIdentifiers.includes(ancestor.expression.left.property.name)) {
const exportName = ancestor.expression.left.property.name;
switch (originalExports[exportName]) {
case ExportClosureMapping.DEFAULT_FUNCTION:
case ExportClosureMapping.NAMED_DEFAULT_FUNCTION:
if (ancestor.expression.left.range) {
source.overwrite(ancestor.expression.left.range[0], ancestor.expression.left.range[1] + ancestor.expression.operator.length, `export default `);
}
break;
case ExportClosureMapping.NAMED_FUNCTION:
if (ancestor.expression.right.type === 'FunctionExpression' &&
ancestor.expression.right.params.length > 0) {
const firstParameter = ancestor.expression.right.params[0];
if (ancestor.expression.range && firstParameter.range) {
source.overwrite(ancestor.expression.range[0], firstParameter.range[0] - 1, `export function ${ancestor.expression.left.property.name}`);
}
}
break;
case ExportClosureMapping.DEFAULT_CLASS:
case ExportClosureMapping.NAMED_DEFAULT_CLASS:
if (ancestor.expression.right.type === 'Identifier') {
const mangledName = ancestor.expression.right.name;
walk.simple(program, {
ClassDeclaration(node) {
if (node.id &&
node.id.name === mangledName &&
node.range &&
node.body.range &&
ancestor.range) {
if (node.superClass && node.superClass.type === 'Identifier') {
source.overwrite(node.range[0], node.body.range[0], `export default class extends ${node.superClass.name}`);
}
else {
source.overwrite(node.range[0], node.body.range[0], `export default class`);
}
source.remove(ancestor.range[0], ancestor.range[1]);
}
},
});
}
break;
case ExportClosureMapping.NAMED_CONSTANT:
if (ancestor.expression.left.object.range) {
source.overwrite(ancestor.expression.left.object.range[0], ancestor.expression.left.object.range[1] + 1, 'var ');
}
collectedExportsToAppend.push(ancestor.expression.left.property.name);
break;
default:
if (ancestor.range) {
source.remove(ancestor.range[0], ancestor.range[1]);
}
if (ancestor.expression.right.type === 'Identifier') {
collectedExportsToAppend.push(`${ancestor.expression.right.name} as ${ancestor.expression.left.property.name}`);
}
break;
}
}
});
}
},
});
if (exportedConstants.length > 0) {
// Remove the newline at the end since we are going to append exports.
if (code.endsWith('\n')) {
code = code.substr(0, code.lastIndexOf('\n'));
}
// Append the exports that were gathered, i.e `export {a as Exported, ExportedThree};`
code += `export {${exportedConstants.join(',')}};`;
if (collectedExportsToAppend.length > 0) {
source.append(`export {${collectedExportsToAppend.join(',')}};`);
}
// Object.keys(exportedConstants).forEach(exportedConstant => {
// let range: [number, number] | undefined = undefined;
// if ((range = exportedConstants[exportedConstant].range)) {
// switch(this.exported[exportedConstant]) {
// case ExportClosureMapping.NAMED_FUNCTION:
// // replace(`window.${key}=function`, `export function ${key}`, code, source);
// source.overwrite(range[0], range[1], `export function ${exportedConstant}`);
// break;
// case ExportClosureMapping.NAMED_CLASS:
// break;
// case ExportClosureMapping.DEFAULT_FUNCTION:
// break;
// case ExportClosureMapping.NAMED_DEFAULT_FUNCTION:
// break;
// case ExportClosureMapping.DEFAULT_CLASS:
// break;
// case ExportClosureMapping.NAMED_DEFAULT_CLASS:
// break;
// case ExportClosureMapping.NAMED_CONSTANT:
// break;
// default:
// this.context.warn(
// 'Rollup Plugin Closure Compiler could not restore all exports statements.',
// );
// break;
// }
// range && source.overwrite(range[0], range[1], 'new text');
// }
// });
// console.log('exportedConstants', exportedConstants);
// Object.keys(this.exported).forEach(key => {
// switch (this.exported[key]) {
// case ExportClosureMapping.NAMED_FUNCTION:
// replace(`window.${key}=function`, `export function ${key}`, code, source);
// break;
// case ExportClosureMapping.NAMED_CLASS:
// const namedClassMatch = new RegExp(`window.${key}=(\\w+);`).exec(code);
// if (namedClassMatch && namedClassMatch.length > 0) {
// // Remove the declaration on window scope, i.e. `window.Exported=a;`
// replace(namedClassMatch[0], '', code, source);
// // Store a new export constant to output at the end. `a as Exported`
// exportedConstants.push(`${namedClassMatch[1]} as ${key}`);
// }
// break;
// case ExportClosureMapping.DEFAULT_FUNCTION:
// replace(`window.${key}=function`, `export default function`, code, source);
// break;
// case ExportClosureMapping.NAMED_DEFAULT_FUNCTION:
// replace(`window.${key}=function`, `export default function ${key}`, code, source);
// break;
// case ExportClosureMapping.DEFAULT_CLASS:
// const defaultClassMatch = new RegExp(`window.${key}=(\\w+);`).exec(code);
// if (defaultClassMatch && defaultClassMatch.length > 0) {
// // Remove the declaration on window scope, i.e. `window.ExportedTwo=a;`
// // Replace it with an export statement `export default a;`
// replace(`class ${defaultClassMatch[1]}`, `export default class`, code, source);
// replace(defaultClassMatch[0], '', code, source);
// }
// break;
// case ExportClosureMapping.NAMED_DEFAULT_CLASS:
// const namedDefaultClassMatch = new RegExp(`window.${key}=(\\w+);`).exec(code);
// if (namedDefaultClassMatch && namedDefaultClassMatch.length > 0) {
// // Remove the declaration on window scope, i.e. `window.ExportedTwo=a;`
// // Replace it with an export statement `export default a;`
// replace(
// namedDefaultClassMatch[0],
// `export default ${namedDefaultClassMatch[1]};`,
// code,
// source,
// );
// }
// break;
// case ExportClosureMapping.NAMED_CONSTANT:
// // Remove the declaration on the window scope, i.e. `window.ExportedThree=value`
// // Replace it with a const declaration, i.e `const ExportedThree=value`
// replace(`window.${key}=`, `const ${key}=`, code, source);
// // Store a new export constant to output at the end, i.e `ExportedThree`
// exportedConstants.push(key);
// break;
// default:
// this.context.warn(
// 'Rollup Plugin Closure Compiler could not restore all exports statements.',
// );
// break;
// }
// });
// if (exportedConstants.length > 0) {
// // Remove the newline at the end since we are going to append exports.
// if (code.endsWith('\n')) {
// source.trimLines();
// }
// // Append the exports that were gathered, i.e `export {a as Exported, ExportedThree};`
// source.append(`export {${exportedConstants.join(',')}};`);
// }
return {
code: source.toString(),
map: source.generateMap(),
};
}
// TODO(KB): Sourcemaps fail :(
return {

@@ -475,2 +653,98 @@ code,

*/
// TODO(KB): Need to generate externs for external members if we do not have an extern passed in.
// Otherwise, advanced mode compilation will fail.
// Likely this means moving scanning for external imports from `preCompilation` to the `derive` phase.
// const HEADER = `/**
// * @fileoverview Externs built via derived configuration from Rollup or input code.
// * This extern contains the external import names, to prevent compilation failures.
// * @externs
// */
// `;
class ImportTransform extends Transform {
constructor() {
super(...arguments);
this.importedExternalsSyntax = {};
}
/**
* Rollup allows configuration for 'external' imports.
* These are items that will not be bundled with the resulting code, but instead are expected
* to already be available via `import` or other means.
* @param source parsed from import statements, this is the source of a particular import statement.
* @param parent parent id requesting the import.
* @return Promise<boolean> if the import is listed in the external list.
*/
async isExternalImport(source, parent) {
if (this.inputOptions.external === undefined) {
return false;
}
if (Array.isArray(this.inputOptions.external)) {
return this.inputOptions.external.includes(source);
}
if (typeof this.inputOptions.external === 'function') {
const configDrivenExternal = await this.inputOptions.external(source, parent, true);
return configDrivenExternal !== undefined && configDrivenExternal === true;
}
return false;
}
/**
* Before Closure Compiler modifies the source, we need to ensure external imports have been removed
* since Closure will error out when it encounters them.
* @param code source to parse, and modify
* @param id Rollup id reference to the source
* @return modified input source with external imports removed.
*/
async preCompilation(code, id) {
const source = new MagicString(code);
const program = this.context.parse(code, { ranges: true });
const importNodes = program.body.filter(node => ALL_IMPORT_DECLARATIONS.includes(node.type));
for (const node of importNodes) {
switch (node.type) {
case IMPORT_DECLARATION:
const name = literalName(this.context, id, node.source);
if (await this.isExternalImport(name, id)) {
const range = node.range ? [node.range[0], node.range[1]] : [0, 0];
this.importedExternalsSyntax[name] = code.slice(range[0], range[1]);
source.remove(range[0], range[1]);
}
break;
default:
break;
}
}
return {
code: source.toString(),
map: source.generateMap(),
};
}
/**
* After Closure Compiler has modified the source, we need to re-add the external imports
* @param code source post Closure Compiler Compilation
* @param id Rollup identifier for the source
* @return Promise containing the repaired source
*/
async postCompilation(code, id) {
const source = new MagicString(code);
Object.values(this.importedExternalsSyntax).forEach(importedExternalSyntax => source.prepend(importedExternalSyntax));
return {
code: source.toString(),
map: source.generateMap(),
};
}
}
/**
* Copyright 2018 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const STRICT_MODE_DECLARATION = `'use strict';`;

@@ -491,5 +765,10 @@ const STRICT_MODE_DECLARATION_LENGTH = STRICT_MODE_DECLARATION.length;

else if (isESMFormat(this.outputOptions.format) && code.startsWith(STRICT_MODE_DECLARATION)) {
const source = new MagicString(code);
// This will only remove the top level 'use strict' directive since we cannot
// be certain source does not contain strings with the intended content.
code = code.slice(STRICT_MODE_DECLARATION_LENGTH, code.length);
source.remove(0, STRICT_MODE_DECLARATION_LENGTH);
return {
code: source.toString(),
map: source.generateMap(),
};
}

@@ -517,11 +796,31 @@ return {

*/
/**
* Copyright 2018 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Instantiate transform class instances for the plugin invocation.
* @param context Plugin context to bind for each transform instance.
* @param options Rollup input options
* @param id Rollup's id entry for this source.
* @return Instantiated transform class instances for the given entry point.
*/
const createTransforms = (context) => {
return [new IifeTransform(context), new ExportTransform(context), new StrictTransform(context)];
const createTransforms = (context, options) => {
return [
new IifeTransform(context, options),
new StrictTransform(context, options),
new ExportTransform(context, options),
new ImportTransform(context, options),
];
};

@@ -554,4 +853,2 @@ /**

async function postCompilation(code, transforms) {
// Following successful Closure Compiler compilation, each transform needs an opportunity
// to clean up work is performed in preCompilation via postCompilation.
for (const transform of transforms) {

@@ -568,6 +865,7 @@ const result = await transform.postCompilation(code, 'none');

* @param code source code to derive information from, pre Closure Compiler minification.
* @param id Rollup identifier for this input source.
* @param transforms Transforms to execute.
*/
async function deriveFromInputSource(code, transforms) {
await Promise.all(transforms.map(transform => transform.deriveFromInputSource(code, 'none'))).then(_ => void 0);
async function deriveFromInputSource(code, id, transforms) {
await Promise.all(transforms.map(transform => transform.deriveFromInputSource(code, id))).then(_ => void 0);
}

@@ -633,3 +931,3 @@

*/
const transformChunk = async (transforms, requestedCompileOptions, sourceCode, outputOptions) => {
const transformChunk = async (transforms, requestedCompileOptions = {}, sourceCode, outputOptions) => {
const code = await preCompilation(sourceCode, outputOptions, transforms);

@@ -644,9 +942,11 @@ const [compileOptions, mapFile] = options(requestedCompileOptions, outputOptions, code, transforms);

function closureCompiler(requestedCompileOptions = {}) {
let inputOptions;
let transforms;
return {
name: 'closure-compiler',
options: options$$1 => (inputOptions = options$$1),
load() {
transforms = transforms || createTransforms(this);
transforms = transforms || createTransforms(this, inputOptions);
},
transform: async (code) => deriveFromInputSource(code, transforms),
transform: async (code, id) => deriveFromInputSource(code, id, transforms),
transformChunk: async (code, outputOptions, chunk) => await transformChunk(transforms, requestedCompileOptions, code, outputOptions),

@@ -653,0 +953,0 @@ };

{
"name": "@ampproject/rollup-plugin-closure-compiler",
"version": "0.4.3",
"version": "0.5.0-alpha.1",
"description": "Rollup + Google Closure Compiler",

@@ -21,3 +21,3 @@ "main": "dist/index.js",

"pretest": "rimraf dist transpile && tsc -p tsconfig.test.json & wait",
"test": "ava test/**/*.js",
"test": "ava -v test/**/*.js",
"build": "rimraf dist transpile && tsc -p tsconfig.json & wait",

@@ -28,20 +28,26 @@ "postbuild": "rollup --config rollup.config.js",

"dependencies": {
"google-closure-compiler": "^20180610.0.2",
"temp-write": "^3.4.0"
"google-closure-compiler": "20180610.0.2",
"magic-string": "0.25.0",
"temp-write": "3.4.0"
},
"devDependencies": {
"@types/estree": "^0.0.39",
"@types/google-closure-compiler": "^0.0.18",
"@types/temp-write": "^3.3.0",
"@types/acorn": "4.0.3",
"@types/estree": "0.0.39",
"@types/google-closure-compiler": "0.0.18",
"@types/temp-write": "3.3.0",
"acorn": "5.7.1",
"ava": "1.0.0-beta.6",
"builtins": "2.0.0",
"husky": "1.0.0-rc.13",
"lint-staged": "^7.2.0",
"prettier": "^1.13.5",
"rimraf": "^2.6.2",
"rollup": "^0.62.0",
"rollup-plugin-commonjs": "^9.1.3",
"rollup-plugin-node-builtins": "^2.1.2",
"tslint": "^5.10.0",
"typescript": "^2.9.2"
"lint-staged": "7.2.0",
"prettier": "1.13.7",
"rimraf": "2.6.2",
"rollup": "0.62.0",
"tslint": "5.10.0",
"typescript": "2.9.2"
},
"files": [
"dist/index.js",
"dist/index.mjs"
],
"lint-staged": {

@@ -48,0 +54,0 @@ "*.ts": [

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc