fix(build): support transpile to commonjs

This commit is contained in:
Tobias Bosch 2015-02-11 11:40:29 -08:00
parent fc1b791a7a
commit 013e1faf27
44 changed files with 189 additions and 112 deletions

View File

@ -56,7 +56,7 @@ to the preprocessor and run the tests without exiting karma
### Performance tests
1. `gulp build.cjs` (builds benchpress and tests into `dist/cjs` folder)
1. `gulp build.js.cjs` (builds benchpress and tests into `dist/js/cjs` folder)
2. `gulp serve.js.prod serve.js.dart2js` (runs local webserver)
3. `protractor protractor-perf-js.conf.js`: JS performance tests
4. `protractor protractor-perf-dart2js.conf.js`: Dart2JS performance tests

View File

@ -9,6 +9,7 @@ var deps = require('./tools/build/deps');
var transpile = require('./tools/build/transpile');
var html = require('./tools/build/html');
var pubspec = require('./tools/build/pubspec');
var linknodemodules = require('./tools/build/linknodemodules');
var pubbuild = require('./tools/build/pubbuild');
var dartanalyzer = require('./tools/build/dartanalyzer');
var jsserve = require('./tools/build/jsserve');
@ -32,18 +33,6 @@ var _COMPILER_CONFIG_JS_DEFAULT = {
modules: 'instantiate'
};
var CJS_COMPILER_OPTIONS = {
sourceMaps: true,
annotations: false, // parse annotations
types: false, // parse types
// TODO(tbosch): Right now, traceur generates imports that
// rely on absolute paths. This is why we are not using this...
script: true, // parse as a script
memberVariables: false, // parse class fields
typeAssertions: false,
modules: null // not needed
};
var _HTLM_DEFAULT_SCRIPTS_JS = [
{src: '/deps/traceur-runtime.js', mimeType: 'text/javascript'},
{src: '/rtts_assert/rtts_assert.js', mimeType: 'text/javascript'},
@ -76,14 +65,10 @@ var CONFIG = {
es6: 'dist/js/prod/es6',
es5: 'dist/js/prod/es5'
},
cjs: 'dist/js/cjs',
dart2js: 'dist/js/dart2js'
},
dart: 'dist/dart',
cjs: {
all: 'dist/cjs',
tools: 'dist/cjs/tools',
e2eTest: 'dist/cjs/e2e_test'
},
docs: 'dist/docs'
},
srcFolderInsertion: {
@ -119,20 +104,12 @@ var CONFIG = {
},
transpile: {
src: {
js: ['modules/**/*.js', 'modules/**/*.es6', '!modules/**/e2e_test/**'],
dart: ['modules/**/*.js', '!modules/**/e2e_test/**'],
cjs: {
tools: ['tools/**/*.es6', '!tools/transpiler/**'],
e2eTest: ['modules/**/e2e_test/**/*.es6']
}
js: ['modules/**/*.js', 'modules/**/*.es6'],
dart: ['modules/**/*.js'],
},
copy: {
js: ['modules/**/*.es5', '!modules/**/e2e_test/**'],
js: ['modules/**/*.es5'],
dart: ['modules/**/*.dart', '!modules/**/e2e_test/**'],
cjs: {
tools: ['tools/**/*.es5', '!tools/transpiler/**'],
e2eTest: ['modules/**/e2e_test/**/*.es5']
}
},
options: {
js: {
@ -144,6 +121,11 @@ var CONFIG = {
prod: merge(true, _COMPILER_CONFIG_JS_DEFAULT, {
typeAssertions: false,
outputLanguage: 'es6'
}),
cjs: merge(true, _COMPILER_CONFIG_JS_DEFAULT, {
typeAssertionModule: 'rtts_assert/rtts_assert',
typeAssertions: true,
modules: 'commonjs'
})
},
dart: {
@ -153,8 +135,7 @@ var CONFIG = {
script: false, // parse as a module
memberVariables: true, // parse class fields
outputLanguage: 'dart'
},
cjs: CJS_COMPILER_OPTIONS
}
}
},
copy: {
@ -214,10 +195,6 @@ gulp.task('build/clean.dart', clean(gulp, gulpPlugins, {
path: CONFIG.dest.dart
}));
gulp.task('build/clean.cjs', clean(gulp, gulpPlugins, {
path: CONFIG.dest.cjs.all
}));
gulp.task('build/clean.docs', clean(gulp, gulpPlugins, {
path: CONFIG.dest.docs
}));
@ -294,6 +271,15 @@ gulp.task('build/transpile.js.prod', function(done) {
);
});
gulp.task('build/transpile.js.cjs', transpile(gulp, gulpPlugins, {
src: CONFIG.transpile.src.js.concat(['tools/benchp*/**/*.es6']),
copy: CONFIG.transpile.copy.js,
dest: CONFIG.dest.js.cjs,
outputExt: 'js',
options: CONFIG.transpile.options.js.cjs,
srcFolderInsertion: CONFIG.srcFolderInsertion.js
}));
gulp.task('build/transpile.dart', transpile(gulp, gulpPlugins, {
src: CONFIG.transpile.src.dart,
copy: CONFIG.transpile.copy.dart,
@ -303,24 +289,6 @@ gulp.task('build/transpile.dart', transpile(gulp, gulpPlugins, {
srcFolderInsertion: CONFIG.srcFolderInsertion.dart
}));
gulp.task('build/transpile/tools.cjs', transpile(gulp, gulpPlugins, {
src: CONFIG.transpile.src.cjs.tools,
copy: CONFIG.transpile.copy.cjs.tools,
dest: CONFIG.dest.cjs.tools,
outputExt: 'js',
options: CONFIG.transpile.options.cjs,
srcFolderInsertion: CONFIG.srcFolderInsertion.js
}));
gulp.task('build/transpile/e2eTest.cjs', transpile(gulp, gulpPlugins, {
src: CONFIG.transpile.src.cjs.e2eTest,
copy: CONFIG.transpile.copy.cjs.e2eTest,
dest: CONFIG.dest.cjs.e2eTest,
outputExt: 'js',
options: CONFIG.transpile.options.cjs,
srcFolderInsertion: CONFIG.srcFolderInsertion.js
}));
// ------------
// html
@ -394,6 +362,13 @@ gulp.task('build/pubspec.dart', pubspec(gulp, gulpPlugins, {
command: DART_SDK.PUB
}));
// ------------
// linknodemodules
gulp.task('build/linknodemodules.js.cjs', linknodemodules(gulp, gulpPlugins, {
dir: CONFIG.dest.js.cjs
}));
// ------------
// dartanalyzer
@ -571,15 +546,16 @@ gulp.task('build.js.prod', function(done) {
);
});
gulp.task('build.cjs', function(done) {
gulp.task('build.js.cjs', function(done) {
runSequence(
['build/transpile/tools.cjs', 'build/transpile/e2eTest.cjs'],
'build/transpile.js.cjs',
'build/linknodemodules.js.cjs',
done
);
);;
});
gulp.task('build.js', ['build.js.dev', 'build.js.prod']);
gulp.task('build.js', ['build.js.dev', 'build.js.prod', 'build.js.cjs']);
gulp.task('clean', ['build/clean.js', 'build/clean.dart', 'build/clean.cjs', 'build/clean.docs']);
gulp.task('clean', ['build/clean.js', 'build/clean.dart', 'build/clean.docs']);
gulp.task('build', ['build.js', 'build.dart', 'build.cjs']);
gulp.task('build', ['build.js', 'build.dart']);

View File

@ -1,4 +1,4 @@
var benchpress = require('../../../tools/benchpress/index.js');
var benchpress = require('benchpress/index.js');
var webdriver = require('protractor/node_modules/selenium-webdriver');
module.exports = {

View File

@ -1,4 +1,4 @@
var benchpress = require('../../../tools/benchpress/index.js');
var benchpress = require('benchpress/index.js');
module.exports = {
verifyNoBrowserErrors: benchpress.verifyNoBrowserErrors,

View File

@ -1,5 +1,5 @@
import {List, ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {normalizeBlank, isPresent} from 'angular2/src/facade/lang';
import {normalizeBlank, isPresent, global} from 'angular2/src/facade/lang';
export class VmTurnZone {
_outerZone;
@ -17,7 +17,7 @@ export class VmTurnZone {
this._onTurnDone = null;
this._onErrorHandler = null;
this._outerZone = window.zone;
this._outerZone = global.zone;
this._innerZone = this._createInnerZone(this._outerZone, enableLongStackTrace);
}

View File

@ -1,6 +1,7 @@
import {int} from 'angular2/src/facade/lang';
import {int, global} from 'angular2/src/facade/lang';
import {List} from 'angular2/src/facade/collection';
export var Promise = window.Promise;
export var Promise = global.Promise;
export class PromiseWrapper {
static resolve(obj):Promise {
@ -37,7 +38,7 @@ export class PromiseWrapper {
}
static setTimeout(fn:Function, millis:int) {
window.setTimeout(fn, millis);
global.setTimeout(fn, millis);
}
static isPromise(maybePromise):boolean {

View File

@ -1,8 +1,8 @@
import {int, isJsObject} from 'angular2/src/facade/lang';
import {int, isJsObject, global} from 'angular2/src/facade/lang';
export var List = window.Array;
export var Map = window.Map;
export var Set = window.Set;
export var List = global.Array;
export var Map = global.Map;
export var Set = global.Set;
export class MapWrapper {
static create():Map { return new Map(); }

View File

@ -1,3 +1,5 @@
import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
export var window = frames.window;
export var DocumentFragment = window.DocumentFragment;
export var Node = window.Node;
@ -10,8 +12,6 @@ export var document = window.document;
export var location = window.location;
export var gc = window.gc ? () => window.gc() : () => null;
import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
export class DOM {
static query(selector) {
return document.querySelector(selector);

View File

@ -1,6 +1,6 @@
library angular.core.facade.lang;
export 'dart:core' show Type, RegExp;
export 'dart:core' show Type, RegExp, print;
import 'dart:math' as math;
class Math {

View File

@ -1,7 +1,10 @@
export {proxy} from 'rtts_assert/rtts_assert';
var _global = typeof window === 'undefined' ? global : window;
export {_global as global};
export var Type = Function;
export var Math = window.Math;
export var Math = _global.Math;
var assertionsEnabled_ = typeof assert !== 'undefined';
@ -9,14 +12,14 @@ var int;
// global assert support, as Dart has it...
// TODO: `assert` calls need to be removed in production code!
if (assertionsEnabled_) {
window.assert = assert;
_global.assert = assert;
// `int` is not a valid JS type
int = assert.define('int', function(value) {
return typeof value === 'number' && value%1 === 0;
});
} else {
int = {};
window.assert = function() {};
_global.assert = function() {};
}
export {int};
@ -173,8 +176,8 @@ var RegExp;
if (assertionsEnabled_) {
RegExp = assert.define('RegExp', function(obj) {
assert(obj).is(assert.structure({
single: window.RegExp,
multiple: window.RegExp
single: _global.RegExp,
multiple: _global.RegExp
}));
});
} else {
@ -185,8 +188,8 @@ export class RegExpWrapper {
static create(regExpStr, flags:string = ''):RegExp {
flags = flags.replace(/g/g, '');
return {
multiple: new window.RegExp(regExpStr, flags + 'g'),
single: new window.RegExp(regExpStr, flags)
multiple: new _global.RegExp(regExpStr, flags + 'g'),
single: new _global.RegExp(regExpStr, flags)
};
}
static firstMatch(regExp, input) {

View File

@ -1 +1,3 @@
export var Math = window.Math;
import {global} from 'angular2/src/facade/lang';
export var Math = global.Math;

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng2 change detection benchmark', function () {

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng2 change detection benchmark', function () {

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng2 compiler benchmark', function () {

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng2 compiler benchmark', function () {

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng2 di benchmark', function () {

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng2 di benchmark', function () {

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng2 element injector benchmark', function () {

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng2 element injector benchmark', function () {

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng2 naive infinite scroll benchmark', function () {

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng2 naive infinite scroll benchmark', function () {

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng2 selector benchmark', function () {

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng2 selector benchmark', function () {

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng2 tree benchmark', function () {

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng2 tree benchmark', function () {

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng1.x compiler benchmark', function () {

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng1.x compiler benchmark', function () {

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng1.x largetable benchmark', function () {
var URL = 'benchmarks_external/src/largetable/largetable_benchmark.html';

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng1.x largetable benchmark', function () {
var URL = 'benchmarks_external/src/largetable/largetable_benchmark.html';

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng-dart1.x naive infinite scroll benchmark', function () {

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng-dart1.x naive infinite scroll benchmark', function () {

View File

@ -1,4 +1,4 @@
var perfUtil = require('../../angular2/e2e_test/perf_util');
var perfUtil = require('angular2/e2e_test/perf_util');
describe('ng1.x tree benchmark', function () {

View File

@ -1,4 +1,4 @@
var testUtil = require('../../angular2/e2e_test/test_util');
var testUtil = require('angular2/e2e_test/test_util');
describe('ng1.x tree benchmark', function () {

View File

@ -1,4 +1,4 @@
var benchpress = require('../../../../tools/benchpress/index.js');
var benchpress = require('benchpress/index.js');
describe('hello world', function () {
afterEach(benchpress.verifyNoBrowserErrors);

View File

@ -32,6 +32,7 @@
"node-uuid": "1.4.x"
},
"devDependencies": {
"temp": "^0.8.1",
"angular": "1.3.5",
"bower": "^1.3.12",
"canonical-path": "0.0.2",

View File

@ -2,5 +2,5 @@ var config = exports.config = require('./protractor-e2e-shared.js').config;
config.baseUrl = 'http://localhost:8002/';
// TODO: remove this line when largetable dart has been added
config.exclude = config.exclude || [];
config.exclude.push('dist/cjs/e2e_test/benchmarks_external/e2e_test/largetable_spec.js');
config.exclude.push('dist/js/cjs/benchmarks_external/e2e_test/largetable_spec.js');

View File

@ -3,4 +3,4 @@ config.baseUrl = 'http://localhost:8001/';
// TODO: remove exclusion when JS verison of scrolling benchmark is available
config.exclude = config.exclude || [];
config.exclude.push('dist/cjs/e2e_test/benchmarks_external/e2e_test/naive_infinite_scroll_spec.js');
config.exclude.push('dist/js/cjs/benchmarks_external/e2e_test/naive_infinite_scroll_spec.js');

View File

@ -1,2 +1,3 @@
var config = exports.config = require('./protractor-shared.js').config;
config.specs = ['dist/cjs/**/*_spec.js'];
config.specs = ['dist/js/cjs/**/e2e_test/**/*_spec.js'];
config.exclude = ['dist/js/cjs/**/node_modules/**'];

View File

@ -3,4 +3,4 @@ config.baseUrl = 'http://localhost:8002/';
config.params.lang = 'dart';
// TODO: remove this line when largetable dart has been added
config.exclude = config.exclude || [];
config.exclude.push('dist/cjs/e2e_test/benchmarks_external/e2e_test/largetable_perf.js');
config.exclude.push('dist/js/cjs/benchmarks_external/e2e_test/largetable_perf.js');

View File

@ -4,4 +4,4 @@ config.params.lang = 'js';
// TODO: remove exclusion when JS verison of scrolling benchmark is available
config.exclude = config.exclude || [];
config.exclude.push('dist/cjs/e2e_test/benchmarks_external/e2e_test/naive_infinite_scroll_perf.js');
config.exclude.push('dist/js/cjs/benchmarks_external/e2e_test/naive_infinite_scroll_perf.js');

View File

@ -14,7 +14,9 @@ if (process.env.CLOUD_SECRET_PATH) {
};
}
config.specs = ['dist/cjs/**/*_perf.js'];
config.specs = ['dist/js/cjs/**/e2e_test/**/*_perf.js'];
config.exclude = ['dist/js/cjs/**/node_modules/**'];
config.jasmineNodeOpts.defaultTimeoutInterval = 80000;
var runId = nodeUuid.v1();
@ -32,8 +34,8 @@ config.params = {
// forces a gc after every run
forceGc: false,
reporters: [
require('./dist/cjs/tools/benchpress/src/console_reporter.js'),
cloudReporterConfig ? require('./dist/cjs/tools/benchpress/src/cloud_reporter.js') : null,
require('./dist/js/cjs/benchpress/src/console_reporter.js'),
cloudReporterConfig ? require('./dist/js/cjs/benchpress/src/cloud_reporter.js') : null,
],
cloudReporter: cloudReporterConfig,
scaling: [{

View File

@ -0,0 +1,32 @@
var fs = require('fs');
var path = require('path');
module.exports = function(gulp, plugins, config) {
return function() {
var nodeModulesDir = path.join(config.dir, 'node_modules');
if (!fs.existsSync(nodeModulesDir)) {
fs.mkdirSync(nodeModulesDir);
}
getSubdirs(config.dir).forEach(function(relativeFolder) {
if (relativeFolder === 'node_modules') {
return;
}
var sourceDir = path.join('..', relativeFolder);
var linkDir = path.join(nodeModulesDir, relativeFolder);
if (!fs.existsSync(linkDir)) {
console.log('creating link', linkDir, sourceDir);
fs.symlinkSync(sourceDir, linkDir, 'dir');
}
});
};
};
function getSubdirs(rootDir) {
return fs.readdirSync(rootDir).filter(function(file) {
if (file[0] === '.') {
return false;
}
var dirPath = path.join(rootDir, file);
return fs.statSync(dirPath).isDirectory();
});
}

View File

@ -87,6 +87,7 @@ function reloadCompiler() {
convertTypesToExpressionsInEs6Patch();
removeNonStaticFieldDeclarationsInEs6Patch();
disableGetterSetterAssertionPatch();
patchCommonJSModuleTransformerToSupportExportStar();
}
function loadModule(filepath, transpile) {
@ -221,3 +222,29 @@ function useRttsAssertModuleForConvertingTypesToExpressions() {
// NYI
}
}
// TODO(tbosch): patch exports for CommonJS to support `export * from ...`
// see https://github.com/google/traceur-compiler/issues/1042
function patchCommonJSModuleTransformerToSupportExportStar() {
var traceurVersion = System.map['traceur'];
var CommonJsModuleTransformer = System.get(traceurVersion+'/src/codegeneration/CommonJsModuleTransformer').CommonJsModuleTransformer;
var parseStatement = System.get(traceurVersion+'/src/codegeneration/PlaceholderParser.js').parseStatement;
var prependStatements = System.get(traceurVersion+"/src/codegeneration/PrependStatements.js").prependStatements;
var _wrapModule = CommonJsModuleTransformer.prototype.wrapModule;
CommonJsModuleTransformer.prototype.wrapModule = function(statements) {
if (this.hasStarExports()) {
var last = statements[statements.length - 1];
statements = statements.slice(0, -1);
var exportObject = last.expression;
if (exportObject.propertyNameAndValues) {
throw new Error('Don\'t support export * with named exports right now...');
}
statements.push(parseStatement(['module.exports = ', ';'], exportObject));
return statements;
} else {
return _wrapModule.apply(this, arguments);
}
}
}

View File

@ -1,4 +1,8 @@
var compiler = require('../index');
var temp = require('temp');
var fs = require('fs');
temp.track();
var DEFAULT_OPTIONS = {
sourceMaps: false,
@ -157,6 +161,34 @@ describe('transpile to es6', function() {
});
describe('transpile to cjs', function() {
var options;
beforeEach(function() {
options = merge(DEFAULT_OPTIONS, {modules: 'commonjs'});
});
function compileAndWrite(input) {
var transpiledCode = compiler.compile(options, "test.js", input).js;
var tempFile = temp.openSync('ng2transpiler');
fs.writeSync(tempFile.fd, transpiledCode);
return tempFile.path;
}
it('should transpile export *', function() {
var file1 = compileAndWrite('export var a = 1');
var file2 = compileAndWrite('export * from "' + file1 + '"');
expect(require(file2).a).toBe(1);
});
it('should transpile export {name}', function() {
var file1 = compileAndWrite('export var a = 1');
var file2 = compileAndWrite('export {a} from "' + file1 + '"');
expect(require(file2).a).toBe(1);
});
});
function merge(a, b) {
var result = {};