fix(build): switch to cjs output for es5.

System output does not work at the current versions of TS and
system.js. Will revisit after upgrading TS.

Removes unused traceur tooling.

Closes #3974
This commit is contained in:
Rado Kirov 2015-09-02 20:58:02 -07:00 committed by Rado Kirov
parent b025f94351
commit e9ad100b1f
39 changed files with 25 additions and 1243 deletions

View File

@ -1,5 +1,3 @@
require('../../tools/transpiler/index.js').init();
var Package = require('dgeni').Package;
var jsdocPackage = require('dgeni-packages/jsdoc');
var nunjucksPackage = require('dgeni-packages/nunjucks');

View File

@ -1,5 +1,3 @@
require('../../tools/transpiler/index.js').init();
var basePackage = require('dgeni-packages/base');
var Package = require('dgeni').Package;
var path = require('canonical-path');

View File

@ -20,7 +20,6 @@ var licenseWrap = require('./tools/build/licensewrap');
var watch = require('./tools/build/watch');
var transpile = require('./tools/build/transpile');
var pubget = require('./tools/build/pubget');
var linknodemodules = require('./tools/build/linknodemodules');
var pubbuild = require('./tools/build/pubbuild');

View File

@ -25,11 +25,12 @@ module.exports = function(config) {
'node_modules/reflect-metadata/Reflect.js',
'tools/build/file2modulename.js',
'test-main.js',
{pattern: 'modules/**/test/**/static_assets/**', included: false, watched: false}
{pattern: 'modules/**/test/**/static_assets/**', included: false, watched: false}
],
exclude: [
'dist/js/dev/es5/**/e2e_test/**',
'dist/js/dev/es5/rtts_assert/**',
'dist/angular1_router.js'
],
@ -40,11 +41,11 @@ module.exports = function(config) {
startConnect: false,
recordVideo: false,
recordScreenshots: false,
options: {
'selenium-version': '2.45.0',
'command-timeout': 600,
'idle-timeout': 600,
'max-duration': 5400
options: {
'selenium-version': '2.45.0',
'command-timeout': 600,
'idle-timeout': 600,
'max-duration': 5400
}
},
@ -62,5 +63,3 @@ module.exports = function(config) {
config.transports = ['xhr-polling'];
}
};

View File

@ -16,7 +16,12 @@ export function evalModule(moduleSource: string, moduleImports: string[][], args
var modName = sourceImport[0];
var modAlias = sourceImport[1];
importModuleNames.push(modName);
moduleSourceWithImports.push(`var ${modAlias} = require('${modName}');`);
// Note: After transpilation to commonJS and loading this file in a browser
// using SystemJS, the loader might get confused by the presence of require,
// and attempt to load "+ modName +.js" !?!
// A simple string concat manages to prevent that, but that is one compiler
// optimaztion away from breaking again. Proceed with caution!
moduleSourceWithImports.push(`var ${modAlias} = require` + `('${modName}');`);
});
moduleSourceWithImports.push(moduleSource);

View File

@ -93,26 +93,3 @@ export class MdInput {
ObservableWrapper.callNext(this.mdFocusChange, hasFocus);
}
}
/*
@Directive({
selector: 'md-input-container textarea',
events: ['mdChange', 'mdFocusChange'],
hostProperties: {
'yes': 'class.md-input'
},
hostListeners: {
'input': 'updateValue($event)',
'focus': 'setHasFocus(true)',
'blur': 'setHasFocus(false)'
}
})
export class MdTextarea extends MdInput {
constructor(
@Attribute('value') value: string,
@SkipSelf() @Host() container: MdInputContainer,
@Attribute('id') id: string) {
super(value, container, id);
}
}
*/

View File

@ -1,6 +1,6 @@
// tree benchmark in React
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
import React from './react.min';
import * as React from './react.min';
var TreeComponent = React.createClass({
displayName: 'TreeComponent',

View File

@ -1,2 +1,2 @@
declare var React: any;
export default React;
export var createElement: Function;
export var render: Function;

View File

@ -34,15 +34,10 @@ describe('sourcemaps', function() {
var originalPosition = decoder.originalPositionFor({line: errorLine, column: errorColumn});
var finalMapData = fs.readFileSync('dist/js/prod/es6/examples/src/sourcemap/index.js.map');
var finalDecoder = new sourceMap.SourceMapConsumer(JSON.parse(finalMapData));
var finalPosition = finalDecoder.originalPositionFor(originalPosition);
var sourceCodeLines =
fs.readFileSync('modules/examples/src/sourcemap/index.ts', {encoding: 'UTF-8'})
.split('\n');
expect(sourceCodeLines[finalPosition.line - 1])
expect(sourceCodeLines[originalPosition.line - 1])
.toMatch(/throw new BaseException\(\'Sourcemap test\'\)/);
});
});

View File

@ -1,56 +0,0 @@
/// <reference path="../../typings/fs-extra/fs-extra.d.ts" />
/// <reference path="../../typings/node/node.d.ts" />
import fs = require('fs');
import fse = require('fs-extra');
import path = require('path');
import {wrapDiffingPlugin, DiffingBroccoliPlugin, DiffResult} from '../diffing-broccoli-plugin';
let traceur = require('../../../../tools/transpiler');
let xtend = require('xtend');
class DiffingTraceurCompiler implements DiffingBroccoliPlugin {
constructor(public inputPath: string, public cachePath: string, public options) {}
static includeExtensions = ['.js', '.cjs'];
rebuild(treeDiff: DiffResult) {
treeDiff.addedPaths.concat(treeDiff.changedPaths)
.forEach((changedFilePath) => {
var traceurOpts = xtend({filename: changedFilePath}, this.options.traceurOptions);
var fsOpts = {encoding: 'utf-8'};
var absoluteInputFilePath = path.join(this.inputPath, changedFilePath);
var sourcecode = fs.readFileSync(absoluteInputFilePath, fsOpts);
var result = traceur.compile(traceurOpts, changedFilePath, sourcecode);
// TODO: we should fix the sourceMappingURL written by Traceur instead of overriding
// (but we might switch to typescript first)
var mapFilepath =
changedFilePath.replace(/\.\w+$/, '') + this.options.destSourceMapExtension;
result.js = result.js + '\n//# sourceMappingURL=./' + path.basename(mapFilepath);
var destFilepath = changedFilePath.replace(/\.\w+$/, this.options.destExtension);
var destFile = path.join(this.cachePath, destFilepath);
fse.mkdirsSync(path.dirname(destFile));
fs.writeFileSync(destFile, result.js, fsOpts);
var destMap = path.join(this.cachePath, mapFilepath);
result.sourceMap.file = destFilepath;
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
});
treeDiff.removedPaths.forEach((removedFilePath) => {
var destFilepath = removedFilePath.replace(/\.\w+$/, this.options.destExtension);
var absoluteOuputFilePath = path.join(this.cachePath, destFilepath);
fs.unlinkSync(absoluteOuputFilePath);
});
}
}
let transpileWithTraceur = wrapDiffingPlugin(DiffingTraceurCompiler);
let TRACEUR_RUNTIME_PATH = traceur.RUNTIME_PATH;
export {transpileWithTraceur as default, TRACEUR_RUNTIME_PATH};

View File

@ -2,16 +2,16 @@
var Funnel = require('broccoli-funnel');
var htmlReplace = require('../html-replace');
var jsReplace = require("../js-replace");
var jsReplace = require('../js-replace');
var path = require('path');
var stew = require('broccoli-stew');
var traceur = require('traceur');
import compileWithTypescript from '../broccoli-typescript';
import destCopy from '../broccoli-dest-copy';
import flatten from '../broccoli-flatten';
import mergeTrees from '../broccoli-merge-trees';
import replace from '../broccoli-replace';
import {default as transpileWithTraceur, TRACEUR_RUNTIME_PATH} from '../traceur/index';
var projectRootDir = path.normalize(path.join(__dirname, '..', '..', '..', '..'));
@ -83,13 +83,10 @@ module.exports = function makeBrowserTree(options, destinationPath) {
],
destDir: '/'
});
var es5ModulesTree = new Funnel('modules', {
include: ['**/**'],
exclude: [
'**/*.cjs',
'benchmarks/e2e_test/**'
],
exclude: ['**/*.cjs', 'angular1_router/**', 'benchmarks/e2e_test/**'],
destDir: '/'
});
@ -117,7 +114,7 @@ module.exports = function makeBrowserTree(options, destinationPath) {
sourceRoot: '.',
target: 'ES6'
});
// Use TypeScript to transpile the *.ts files to ES5
var es5Tree = compileWithTypescript(es5ModulesTree, {
allowNonTsExtensions: false,
@ -125,7 +122,7 @@ module.exports = function makeBrowserTree(options, destinationPath) {
emitDecoratorMetadata: true,
experimentalDecorators: true,
mapRoot: '', // force sourcemaps to use relative path
module: 'System',
module: 'CommonJS',
noEmitOnError: false,
rootDir: '.',
sourceMap: true,
@ -133,7 +130,7 @@ module.exports = function makeBrowserTree(options, destinationPath) {
target: 'ES5'
});
// Now we add a few more files to the es6 tree that Traceur should not see
// Now we add a few more files to the es6 tree that the es5 tree should not see
['angular2', 'rtts_assert'].forEach(function(destDir) {
var extras = new Funnel('tools/build', {files: ['es5build.js'], destDir: destDir});
es6Tree = mergeTrees([es6Tree, extras]);
@ -147,7 +144,7 @@ module.exports = function makeBrowserTree(options, destinationPath) {
'node_modules/rx/dist/rx.js',
'node_modules/base64-js/lib/b64.js',
'node_modules/reflect-metadata/Reflect.js',
path.relative(projectRootDir, TRACEUR_RUNTIME_PATH)
path.relative(projectRootDir, traceur.RUNTIME_PATH)
]
}));

View File

@ -1,16 +0,0 @@
var util = require('./util');
var gulpTraceur = require('../transpiler/gulp-traceur');
var file2moduleName = require('./file2modulename');
module.exports = function(gulp, plugins, config) {
return function() {
return gulp.src(config.src)
.pipe(plugins.rename({extname: '.'+config.outputExt}))
.pipe(util.insertSrcFolder(plugins, config.srcFolderInsertion))
.pipe(gulpTraceur(
config.options,
file2moduleName)
)
.pipe(gulp.dest(config.dest));
};
};

View File

@ -1,62 +0,0 @@
'use strict';
var through = require('through2');
var compiler = require('./index');
var path = require('path');
module.exports = gulpTraceur;
gulpTraceur.RUNTIME_PATH = compiler.RUNTIME_PATH;
gulpTraceur.sourcesChanged = compiler.sourcesChanged;
function gulpTraceur(options, resolveModuleName) {
options = options || {};
return through.obj(function (file, enc, done) {
if (file.isNull()) {
done();
return;
}
if (file.isStream()) {
throw new Error('gulp-traceur: Streaming not supported');
}
try {
var originalFilePath = file.history[0];
var moduleName = resolveModuleName ? resolveModuleName(file.relative) : null;
var result = compiler.compile(options, {
inputPath: originalFilePath,
outputPath: file.relative,
moduleName: moduleName
}, file.contents.toString());
var transpiledContent = result.js;
var sourceMap = result.sourceMap;
if (sourceMap) {
sourceMap.file = file.relative;
var sourceMapFile = cloneFile(file, {
path: file.path.replace(/\.\w+$/, '.map'),
contents: JSON.stringify(sourceMap)
});
transpiledContent += '\n//# sourceMappingURL=./' + path.basename(sourceMapFile.path);
this.push(sourceMapFile);
}
this.push(cloneFile(file, {contents: transpiledContent}));
done();
} catch (errors) {
if (errors.join) {
throw new Error('gulp-traceur:\n ' + errors.join('\n '));
} else {
console.error('Error when transpiling:\n ' + originalFilePath);
throw errors;
}
}
});
};
function cloneFile(file, override) {
var File = file.constructor;
return new File({path: override.path || file.path, cwd: override.cwd || file.cwd, contents: new Buffer(override.contents || file.contents), base: override.base || file.base});
}

View File

@ -1,243 +0,0 @@
// Entry point for Node.
var fs = require('fs');
var glob = require('glob');
var path = require('path');
var traceur = require('traceur');
var assert = require('assert');
exports.RUNTIME_PATH = traceur.RUNTIME_PATH;
var TRACEUR_PATH = traceur.RUNTIME_PATH.replace('traceur-runtime.js', 'traceur.js');
var SELF_SOURCE_REGEX = /transpiler\/src/;
var SELF_COMPILE_OPTIONS = {
modules: 'register',
memberVariables: false,
moduleName: true,
script: false // parse as a module
};
var needsReload = true;
var oldSystemGet = System.get;
var currentOptions;
exports.reloadSources = function() {
needsReload = true;
};
exports.compile = function compile(options, paths, source, reloadTraceur) {
if (needsReload) {
reloadCompiler(reloadTraceur);
needsReload = false;
}
var inputPath, outputPath, moduleName;
if (typeof paths === 'string') {
inputPath = outputPath = paths;
} else {
inputPath = paths.inputPath;
outputPath = paths.inputPath;
moduleName = paths.moduleName;
}
outputPath = outputPath || inputPath;
moduleName = moduleName || inputPath;
moduleName = moduleName.replace(/\.\w*$/, '');
var CompilerCls = System.get('transpiler/src/compiler').Compiler;
var compiler = new CompilerCls(options, moduleName);
currentOptions = options;
var result = {
js: compiler.compile(source, inputPath, outputPath),
sourceMap: null
};
currentOptions = null;
var sourceMapString = compiler.getSourceMap();
if (sourceMapString) {
result.sourceMap = JSON.parse(sourceMapString);
}
if (options.outputLanguage === 'es6' && source.indexOf('$traceurRuntime') === -1) {
assert(result.js.indexOf('$traceurRuntime') === -1,
'Transpile to ES6 must not add references to $traceurRuntime, '
+ inputPath + ' is transpiled to:\n' + result.js);
}
return result;
};
exports.init = function() {
if (needsReload) {
reloadCompiler();
needsReload = false;
}
}
// Transpile and evaluate the code in `src`.
// Use existing traceur to compile our sources.
function reloadCompiler(reloadTraceur) {
if (reloadTraceur) {
loadModule(TRACEUR_PATH, false);
}
glob.sync(__dirname + '/src/**/*.js').forEach(function(fileName) {
loadModule(fileName, true);
});
// Traceur modules are register with the ".js" extension but we don't want
// to add it to all the import statements.
System.get = function get(normalizedName) {
var m = oldSystemGet.call(this, normalizedName);
if (!m && normalizedName.indexOf('traceur') == 0) {
m = oldSystemGet.call(this, normalizedName + '.js');
}
return m;
};
useRttsAssertModuleForConvertingTypesToExpressions();
supportSuperCallsInEs6Patch();
convertTypesToExpressionsInEs6Patch();
disableGetterSetterAssertionPatch();
patchCommonJSModuleTransformerToSupportExportStar();
}
function loadModule(filepath, transpile) {
var data = fs.readFileSync(filepath, 'utf8');
if (!data) {
throw new Error('Failed to import ' + filepath);
}
if (transpile) {
var moduleName = path.normalize(filepath)
.replace(__dirname, 'transpiler')
.replace(/\\/g, '/')
.replace(/\.\w*$/, '');
data = traceur.compile(data, SELF_COMPILE_OPTIONS, moduleName);
}
('global', eval)(data);
}
function extend(source, props) {
var res = {};
for (var prop in source) {
res[prop] = source[prop];
}
for (var prop in props) {
res[prop] = props[prop];
}
return res;
}
// TODO(tbosch): remove when traceur is fixed.
// see https://github.com/google/traceur-compiler/issues/1700
function supportSuperCallsInEs6Patch() {
var traceurVersion = System.map['traceur'];
var ParseTreeMapWriter = System.get(traceurVersion+'/src/outputgeneration/ParseTreeMapWriter').ParseTreeMapWriter;
var _enterBranch = ParseTreeMapWriter.prototype.enterBranch;
ParseTreeMapWriter.prototype.enterBranch = function(location) {
if (!location.start) {
// This would throw...
return;
}
return _enterBranch.apply(this, arguments);
}
}
// TODO(tbosch): Remove when traceur is fixed.
// see https://github.com/google/traceur-compiler/issues/1699
function convertTypesToExpressionsInEs6Patch() {
var traceurVersion = System.map['traceur'];
var TypeToExpressionTransformer = System.get(traceurVersion+'/src/codegeneration/TypeToExpressionTransformer').TypeToExpressionTransformer;
var PureES6Transformer = System.get(traceurVersion+'/src/codegeneration/PureES6Transformer').PureES6Transformer;
var UniqueIdentifierGenerator = System.get(traceurVersion+'/src/codegeneration/UniqueIdentifierGenerator').UniqueIdentifierGenerator;
var _transform = PureES6Transformer.prototype.transform;
PureES6Transformer.prototype.transform = function() {
if (!this._patched) {
this._patched = true;
var self = this;
this.treeTransformers_.splice(0,0, function(tree) {
return new TypeToExpressionTransformer(new UniqueIdentifierGenerator(), self.reporter_, self.options_).transformAny(tree);
});
}
return _transform.apply(this, arguments);
};
}
// TODO(tbosch): Disable getter/setters for assertions until traceur has a flag
// that allows to disable them while keeping assertions and member fields enabled.
// see https://github.com/google/traceur-compiler/issues/1625
// Why:
// - traceur uses field names based on numbers, which can lead to collisions when creating a subclass in a separate compiler run.
// - this rename of fields makes debugging via the repl harder (e.g. via DevTools console)
// - this rename can break JSON conversion of instances
function disableGetterSetterAssertionPatch() {
var traceurVersion = System.map['traceur'];
var MemberVariableTransformer = System.get(traceurVersion+'/src/codegeneration/MemberVariableTransformer').MemberVariableTransformer;
var AnonBlock = System.get(traceurVersion+'/src/syntax/trees/ParseTrees.js').AnonBlock;
MemberVariableTransformer.prototype.transformPropertyVariableDeclaration = function(tree) {
return new AnonBlock(tree.location, []);
}
}
// TODO(tbosch): Get all types from `assert` module and not from `$traceurRuntime`.
// With this a transpile to ES6 does no more include the `$traceurRuntime`.
// see https://github.com/google/traceur-compiler/issues/1706
function useRttsAssertModuleForConvertingTypesToExpressions() {
var traceurVersion = System.map['traceur'];
var original = System.get(traceurVersion+'/src/codegeneration/TypeToExpressionTransformer').TypeToExpressionTransformer;
var patch = System.get('transpiler/src/patch/TypeToExpressionTransformer').TypeToExpressionTransformer;
for (var prop in patch.prototype) {
original.prototype[prop] = patch.prototype[prop];
}
original.prototype.getOptions = function() { return currentOptions; };
var TypeAssertionTransformer = System.get(traceurVersion+'/src/codegeneration/TypeAssertionTransformer').TypeAssertionTransformer;
var createIdentifierExpression = System.get(traceurVersion+'/src/codegeneration/ParseTreeFactory').createIdentifierExpression;
var parseExpression = System.get(traceurVersion+'/src/codegeneration/PlaceholderParser.js').parseExpression;
TypeAssertionTransformer.prototype.transformBindingElementParameter_ = function(element, typeAnnotation) {
// Copied from https://github.com/google/traceur-compiler/commits/master/src/codegeneration/TypeAssertionTransformer.js
if (!element.binding.isPattern()) {
if (typeAnnotation) {
this.paramTypes_.atLeastOneParameterTyped = true;
} else {
// PATCH start
var typeModule = currentOptions.outputLanguage === 'es6' ? 'assert' : '$traceurRuntime';
typeAnnotation = parseExpression([typeModule + ".type.any"]);
// PATCH end
}
this.paramTypes_.arguments.push(
createIdentifierExpression(element.binding.identifierToken),
typeAnnotation);
return;
}
// 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 +0,0 @@
export function main() {}

View File

@ -1,78 +0,0 @@
import {describe, it, expect, iit} from 'angular2/test_lib';
import {readFirstAnnotation} from './fixtures/annotations';
import {CONST} from 'angular2/src/core/facade/lang';
class Inject {}
class Bar {}
class Provide {
token;
@CONST()
constructor(token) {
this.token = token;
}
}
class AnnotateMe {
maybe;
@CONST()
constructor({maybe = 'default'} = {}) {
this.maybe = maybe;
}
}
@Provide('Foo')
class Foo {
@Inject
constructor() {}
}
@Provide(Foo)
function baz() {}
@AnnotateMe()
class A {}
@AnnotateMe({maybe: 'yes'})
class B {}
@AnnotateMe({maybe: {'a': 'b'}})
class SomeClassWithMapInAnnotation {}
@AnnotateMe({maybe: [23]})
class SomeClassWithListInAnnotation {}
@AnnotateMe({maybe: new Provide(0)})
class SomeClassWithConstObject {}
function annotatedParams(@Inject(Foo) f, @Inject(Bar) b) {}
export function main() {
describe('annotations', function() {
it('should work', function() {
// Assert `Foo` class has `Provide` annotation.
var clazz = readFirstAnnotation(Foo);
expect(clazz instanceof Provide).toBe(true);
});
it('should work with named arguments', function() {
expect(readFirstAnnotation(A).maybe).toBe('default');
expect(readFirstAnnotation(B).maybe).toBe('yes');
});
it('should work with maps in named arguments', () => {
expect(readFirstAnnotation(SomeClassWithMapInAnnotation).maybe).toEqual({'a': 'b'});
});
it('should work with lists in named arguments', () => {
expect(readFirstAnnotation(SomeClassWithListInAnnotation).maybe).toEqual([23]);
});
it('should work with new instances in named arguments', () => {
expect(readFirstAnnotation(SomeClassWithConstObject).maybe).toEqual(new Provide(0));
});
});
}

View File

@ -1,63 +0,0 @@
import {describe, it, expect, iit} from 'angular2/test_lib';
var inc = x => x + 1;
var objLiteral = val => ({'key': val});
var max = (a, b) => {
if (a > b) {
return a;
} else {
return b;
}
};
var namedFn = function({fn}) {
return fn();
}
class LexicalThis {
zero;
constructor() {
this.zero = 0;
}
getZero() {
return (() => this.zero)();
}
}
export function main() {
describe('arrow functions', function() {
it('should support implicit return', function() {
expect(inc(0)).toBe(1);
});
it('should support implicit return in named arguments', function() {
expect(namedFn({fn: () => 1})).toBe(1);
});
it('should support object literal', function() {
var o = objLiteral('val');
expect(o['key']).toBe('val');
});
it('should support complex body', function() {
expect(max(0, 1)).toBe(1);
expect(max(1, 0)).toBe(1);
});
it('should support complex body in named arguments', function() {
expect(namedFn({fn: () => {
return 1;
}})).toBe(1);
});
it('should support lexical this', function() {
var lthis = new LexicalThis();
expect(lthis.getZero()).toBe(0);
});
});
}

View File

@ -1,3 +0,0 @@
export var Bar1 = 'BAR1';
export var Bar2 = 'BAR2';
export function Bar3() {}

View File

@ -1 +0,0 @@
export var Baz = 'BAZ';

View File

@ -1,108 +0,0 @@
import {ddescribe, describe, it, expect} from 'angular2/test_lib';
import {CONST} from './fixtures/annotations';
class Foo {
a;
b;
constructor(a, b) {
this.a = a;
this.b = b;
}
sum() {
return this.a + this.b;
}
}
class SubFoo extends Foo {
c;
constructor(a, b) {
super(a, b);
this.c = 3;
}
}
class ConstClass {}
class Const {
a;
@CONST
constructor(a:number) {
this.a = a;
}
}
class SubConst extends Const {
b;
@CONST
constructor(a:number, b:number) {
super(a);
this.b = b;
}
}
class HasGetters {
get getter():string {
return 'getter';
}
static get staticGetter():string {
return 'getter';
}
}
class WithFields {
name: string;
static id: number;
}
export function main() {
describe('classes', function() {
it('should work', function() {
var foo = new Foo(2, 3);
expect(foo.a).toBe(2);
expect(foo.b).toBe(3);
expect(foo.sum()).toBe(5);
});
it('@CONST should be transpiled to a const constructor', function() {
var subConst = new SubConst(1, 2);
expect(subConst.a).toBe(1);
expect(subConst.b).toBe(2);
});
describe('inheritance', function() {
it('should support super call', function () {
var subFoo = new SubFoo(1, 2);
expect(subFoo.a).toBe(1);
expect(subFoo.b).toBe(2);
expect(subFoo.c).toBe(3);
});
});
describe("getters", function () {
it("should call instance getters", function () {
var obj = new HasGetters();
expect(obj.getter).toEqual('getter');
});
it("should call static getters", function () {
expect(HasGetters.staticGetter).toEqual('getter');
});
});
describe('fields', function() {
it('should work', function() {
var obj = new WithFields();
obj.name = 'Vojta';
WithFields.id = 12;
});
});
});
}

View File

@ -1,5 +0,0 @@
import {foo} from './cycle_spec';
export function cycle() {
return foo;
}

View File

@ -1,13 +0,0 @@
import {describe, it, expect} from 'angular2/test_lib';
import {cycle} from './cycle';
export function main() {
describe('cycle', function() {
it('should work', function() {
expect(cycle()).toBe(true);
});
});
}
export var foo = true;

View File

@ -1,22 +0,0 @@
import {describe, it, expect} from 'angular2/test_lib';
function same(a, b) {
return a === b;
}
function notSame(a, b) {
if ((a !== a) && (b !== b)) return true;
return a !== b;
}
export function main() {
describe('equals', function() {
it('should work', function() {
var obj = {};
expect(same({}, {}) == false).toBe(true);
expect(same(obj, obj) == true).toBe(true);
expect(notSame({}, {}) == true).toBe(true);
expect(notSame(obj, obj) == false).toBe(true);
});
});
}

View File

@ -1,2 +0,0 @@
export * from './foo';
export {Bar1, Bar2} from './bar';

View File

@ -1,7 +0,0 @@
import 'dart:mirrors';
// TODO: this api does not yet return an array as we don't have
// a nice array wrapper for Dart
readFirstAnnotation(clazz) {
return reflectClass(clazz).metadata.first.reflectee;
}

View File

@ -1,5 +0,0 @@
// TODO: this api does not yet return an array as we don't have
// a nice array wrapper for Dart
export function readFirstAnnotation(clazz) {
return clazz.annotations[0];
}

View File

@ -1,16 +0,0 @@
import 'dart:collection';
class MapWrapper {
}
/**
* Generic iterable class to test for-of. Provides iteration of the given list.
*/
class IterableList extends IterableBase {
List values;
IterableList(values) {
this.values = values;
}
Iterator get iterator => values.iterator;
}

View File

@ -1,18 +0,0 @@
export class MapWrapper {
}
/**
* Generic iterable class to test for-of. Provides iteration of the given array.
*/
export class IterableList {
constructor(values) {
this.values = values;
}
*[Symbol.iterator]() {
for (var value of this.values) {
yield value;
}
}
}

View File

@ -1,2 +0,0 @@
export var Foo = 'FOO';
export var Bar = 'BAR';

View File

@ -1,69 +0,0 @@
import {describe, ddescribe, it, iit, expect} from 'angular2/test_lib';
function sum(a, b) {
return a + b;
}
class ConstructorWithNamedParams {
sum;
constructor(a, {b=1, c=2}) {
this.sum = a + b + c;
}
}
export function main() {
describe('functions', function() {
it('should work', function() {
expect(sum(1, 2)).toBe(3);
});
describe("named parameters", function() {
it('should pass named params as named params by using identifier keys', function() {
function f(a, {b, c}) {return a + b + c;}
expect(f(1, {b: 2, c: 3})).toBe(6);
});
it('should pass named params as a map by using quoted keys', function() {
function f(m) {return m["a"] + m["b"];}
expect(f({"a": 1, "b": 2})).toBe(3);
});
it('should compile initializers', function() {
function f({a=1, b=2}) {return a + b;}
expect(f({a:10})).toBe(12);
});
it("should call function with named params without passing any" +
"params by providing an empty object initializer", function() {
function f({a=1, b=2}={}) {return a + b;}
expect(f({a: 10})).toBe(12);
expect(f()).toBe(3);
});
it("should support new expressions", function () {
var obj = new ConstructorWithNamedParams(100, {b:10});
expect(obj.sum).toEqual(112);
});
});
describe("optional params", function () {
it("should work", function () {
function optional(a=1,b=2){return a + b;}
expect(optional()).toEqual(3);
expect(optional(10)).toEqual(12);
expect(optional(10, 20)).toEqual(30);
});
it("should support a mix of optional and mandatory params", function () {
function optional(a,b=2){return a + b;}
expect(optional(1)).toEqual(3);
expect(optional(10)).toEqual(12);
});
});
});
}

View File

@ -1,11 +0,0 @@
import {describe, it, expect} from 'angular2/test_lib';
class Foo {}
export function main() {
describe('instanceof', function() {
it('should work', function() {
expect(new Foo() instanceof Foo);
});
});
}

View File

@ -1,26 +0,0 @@
import {ddescribe, describe, it, iit, expect} from 'angular2/test_lib';
import {IMPLEMENTS} from './fixtures/annotations';
class Interface1 {
one(){}
}
class Interface2 {
two(){}
}
@IMPLEMENTS(Interface1, Interface2)
class SomeClass {
one(){}
two(){}
}
export function main() {
describe('interfaces', function() {
it('should work', function () {
var s = new SomeClass();
expect(s).toImplement(Interface1);
expect(s).toImplement(Interface2);
});
});
}

View File

@ -1,14 +0,0 @@
import {describe, it, expect} from 'angular2/test_lib';
export function main() {
describe('lang', function() {
it('string interpolation', function() {
expect(`${123}-'${456}"`).toEqual('123-\'456"');
});
it('multiline string', function () {
expect(`1'
2"`).toEqual('1\'\n2"');
});
});
}

View File

@ -1,6 +0,0 @@
import {Baz} from './baz';
import {Bar1} from './bar';
export {Baz} from './baz';
var localVar = true;

View File

@ -1,94 +0,0 @@
import {describe, xdescribe, it, expect} from 'angular2/test_lib';
class A {}
class B {}
function sum(a: number, b: number): number {
return a + b;
}
function not(a: boolean): boolean {
return !a;
}
function generics(a: A<B>) {
}
function namedObjectType({a,b}:{a:A,b:B<C>}) {
}
class Bar {
constructor({
selector,
implementsTypes
})
{
}
}
class Foo {
a;
b;
constructor(a: number, b: number) {
this.a = a;
this.b = b;
}
sum(): number {
return this.a + this.b;
}
typedVariables() {
var foo:string = 'foo';
}
}
class WithFields {
name: string;
static id: number;
untyped;
static staticUntyped;
}
export function main() {
describe('types', function() {
it('should work', function() {
// TODO(vojta): test this better.
var f = new Foo(1, 2);
assert(f.sum() == 3);
assert(f instanceof Foo);
f.typedVariables();
});
xdescribe('class fields', function() {
it('should fail when setting wrong type value', function() {
var wf = new WithFields();
expect(function() {
wf.name = true;
}).toThrowError(
// TODO(vojta): Better error, it's not first argument, it's setting a field.
'Invalid arguments given!\n' +
' - 1st argument has to be an instance of string, got true'
);
});
});
xdescribe('static class fields', function() {
it('should fail when setting wrong type value', function() {
expect(function() {
WithFields.id = true;
}).toThrowError(
// TODO(vojta): Better error, it's not first argument, it's setting a field.
'Invalid arguments given!\n' +
' - 1st argument has to be an instance of number, got true'
);
});
});
});
}

View File

@ -1,36 +0,0 @@
import {Compiler as TraceurCompiler} from 'traceur/src/Compiler';
import {CollectingErrorReporter} from 'traceur/src/util/CollectingErrorReporter';
import {Parser} from './parser';
import {SourceFile} from 'traceur/src/syntax/SourceFile';
import {Options} from 'traceur/src/Options';
export class Compiler extends TraceurCompiler {
constructor(options, sourceRoot) {
super(options, sourceRoot);
this.moduleName_ = sourceRoot;
}
// Copy of the original method to use our custom Parser
parse(content, sourceName) {
if (!content) {
throw new Error('Compiler: no content to compile.');
} else if (!sourceName) {
throw new Error('Compiler: no source name for content.');
}
this.sourceMapGenerator_ = null;
var traceurOptions = new Options();
// Here we mutate the global/module options object to be used in parsing.
traceurOptions.setFromObject(this.options_);
var errorReporter = new CollectingErrorReporter();
sourceName = this.sourceName(sourceName);
var sourceFile = new SourceFile(sourceName, content);
var parser = new Parser(sourceFile, errorReporter, this.options_);
var tree =
this.options_.script ? parser.parseScript() : parser.parseModule();
this.throwIfErrors(errorReporter);
return tree;
}
}

View File

@ -1,23 +0,0 @@
import {Parser as TraceurParser} from 'traceur/src/syntax/Parser';
import {SyntaxErrorReporter} from 'traceur/src/util/SyntaxErrorReporter';
import {TypeName, ImportSpecifier, ImportedBinding, BindingIdentifier} from 'traceur/src/syntax/trees/ParseTrees';
import {PERIOD, IMPORT, STAR, AS, FROM, CLOSE_ANGLE, OPEN_ANGLE, COMMA, OPEN_CURLY, CLOSE_CURLY, COLON} from 'traceur/src/syntax/TokenType';
export class Parser extends TraceurParser {
constructor(file, errorReporter = new SyntaxErrorReporter(), options) {
super(file, errorReporter, options);
}
// TODO: add support for object type literals to traceur!
parseObjectType_() {
this.eat_(OPEN_CURLY);
do {
var identifier = this.eatId_();
this.eat_(COLON);
var type = this.parseNamedOrPredefinedType_();
var typeParameters = this.parseTypeParametersOpt_();
// TODO(misko): save the type information
} while (this.eatIf_(COMMA));
this.eat_(CLOSE_CURLY);
}
}

View File

@ -1,51 +0,0 @@
// Based on https://github.com/google/traceur-compiler/blob/master/src/codegeneration/TypeToExpressionTransformer.js
// Copyright 2012 Traceur Authors.
// Licensed under the Apache License, Version 2.0 (the 'License');
//
// Modifications:
// - use `assert` import, instead of `$traceurRuntime....` so
// that a transpilation to ES6 does not contain any traceur references.
import {ParseTreeTransformer} from 'traceur/src/codegeneration/ParseTreeTransformer.js';
import {
ArgumentList,
IdentifierExpression,
MemberExpression
} from 'traceur/src/syntax/trees/ParseTrees.js';
import {
parseExpression
} from 'traceur/src/codegeneration/PlaceholderParser.js';
export class TypeToExpressionTransformer extends ParseTreeTransformer {
// Not used. Just required to call super() by traceur.
constructor(idGenerator, reporter, options) {
super(idGenerator, reporter);
}
typeModule() {
return parseExpression([this.getOptions().outputLanguage === 'es6' ? 'assert' : '$traceurRuntime']);
}
transformTypeName(tree) {
if (tree.moduleName) {
var operand = this.transformAny(tree.moduleName);
return new MemberExpression(tree.location, operand, tree.name);
}
return new IdentifierExpression(tree.location, tree.name);
}
transformPredefinedType(tree) {
return parseExpression `${this.typeModule()}.type.${tree.typeToken})`;
}
transformTypeReference(tree) {
var typeName = this.transformAny(tree.typeName);
var args = this.transformAny(tree.args);
var argumentList = new ArgumentList(tree.location, [typeName, ...args]);
return parseExpression `${this.typeModule()}.genericType(${argumentList})`;
}
transformTypeArguments(tree) {
return this.transformList(tree.args);
}
}

View File

@ -1,135 +0,0 @@
var compiler = require('../index');
var temp = require('temp');
var fs = require('fs');
temp.track();
var DEFAULT_OPTIONS = {
sourceMaps: false,
annotations: true, // parse annotations
types: true, // parse types
script: false, // parse as a module
memberVariables: true // parse class fields
};
describe('transpile to es6', function() {
var options;
beforeEach(function() {
options = merge(DEFAULT_OPTIONS, {outputLanguage: 'es6', typeAssertions: 'true'});
});
it('should preserve generic type information', function() {
var result = compiler.compile(options, "test.js",
"function f(a:List<string>){}");
expect(result.js).toBe('function f(a) {\n'+
' assert.argumentTypes(a, assert.genericType(List, assert.type.string));\n'+
'}\n'+
'Object.defineProperty(f, "parameters", {get: function() {\n'+
' return [[assert.genericType(List, assert.type.string)]];\n'+
' }});\n');
});
it('should allow super() calls when transpiling to ES6 with source maps', function() {
options = merge(options, {sourceMaps: true});
var result = compiler.compile(options, "test.js",
"class Base {}\n" +
"class Test extends Base {" +
" constructor() { super(); }" +
"}");
expect(result.js).toBe("class Base {}\n" +
"class Test extends Base {\n" +
" constructor() {\n"+
" super();\n"+
" }\n"+
"}\n"+
"//# sourceMappingURL=test.js.map\n");
});
it('should convert types to expressions', function() {
var result = compiler.compile(options, "test.js",
"function f(a:string) {}");
expect(result.js).toBe('function f(a) {\n'+
' assert.argumentTypes(a, assert.type.string);\n'+
'}\n' +
'Object.defineProperty(f, "parameters", {get: function() {\n' +
' return [[assert.type.string]];\n' +
' }});\n');
});
it('should not convert type properties to getter/setters', function() {
var result = compiler.compile(options, "test.js",
"class Test {" +
" constructor() { this.a = 1; }" +
"}");
expect(result.js).toBe("class Test {\n" +
" constructor() {\n"+
" this.a = 1;\n"+
" }\n"+
"}\n");
});
it('should remove class field declarations', function() {
var result = compiler.compile(options, "test.js",
"class Test {" +
" a:number = 1;" +
"}");
expect(result.js).toBe("class Test {}\n");
});
it('should convert types to expressions on "assert" module', function() {
var result = compiler.compile(options, "test.js",
"function f(a:string, b) { return a+b; }");
expect(result.js).toBe('function f(a, b) {\n'+
' assert.argumentTypes(a, assert.type.string, b, assert.type.any);\n'+
' return a + b;\n'+
'}\n'+
'Object.defineProperty(f, "parameters", {get: function() {\n'+
' return [[assert.type.string], []];\n'+
' }});\n');
});
});
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 tempPath = temp.path({prefix: "ng2transpiler", suffix: ''});
var fd = fs.openSync(tempPath, 'w+');
fs.writeSync(fd, transpiledCode);
fs.closeSync(fd);
return tempPath.replace(/\\/g, '/');
}
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 = {};
for (var prop in a) {
result[prop] = a[prop];
}
for (var prop in b) {
result[prop] = b[prop];
}
return result;
}