angular/tools/broccoli/trees/browser_tree.ts
Victor Berchet e8a6c95e2a feat(VmTurnZone): Rework the implementation to minimize change detection runs
Before this PR there were only 2 zones: root zone = outer zone > inner
zone.
This PR creates the outer zone as a fork of the root zone: root > outer
> inner.

By doing this it is possible to detected microtasks scheduling in the
outer zone and run the change detection less often (no more than one
time per VM turn).

The PR also introduce a Promise monkey patch for the JS implementation.
It makes Promises aware of microtasks and again allow running the change
detection only once per turn.
2015-05-12 21:03:24 +02:00

164 lines
6.2 KiB
TypeScript

'use strict';
var Funnel = require('broccoli-funnel');
var flatten = require('broccoli-flatten');
var htmlReplace = require('../html-replace');
var mergeTrees = require('broccoli-merge-trees');
var path = require('path');
var replace = require('broccoli-replace');
var stew = require('broccoli-stew');
var ts2dart = require('../broccoli-ts2dart');
import compileWithTypescript from '../broccoli-typescript';
import destCopy from '../broccoli-dest-copy';
import {default as transpileWithTraceur, TRACEUR_RUNTIME_PATH} from '../traceur/index';
var projectRootDir = path.normalize(path.join(__dirname, '..', '..', '..', '..'));
module.exports = function makeBrowserTree(options, destinationPath) {
var modulesTree = new Funnel(
'modules',
{include: ['**/**'], exclude: ['**/*.cjs', 'benchmarks/e2e_test/**'], destDir: '/'});
// Use Traceur to transpile *.js sources to ES6
var traceurTree = transpileWithTraceur(modulesTree, {
destExtension: '.es6',
destSourceMapExtension: '.map',
traceurOptions: {
sourceMaps: true,
annotations: true, // parse annotations
types: true, // parse types
script: false, // parse as a module
memberVariables: true, // parse class fields
modules: 'instantiate',
// typeAssertionModule: 'rtts_assert/rtts_assert',
// typeAssertions: options.typeAssertions,
outputLanguage: 'es6'
}
});
// Use TypeScript to transpile the *.ts files to ES6
// We don't care about errors: we let the TypeScript compilation to ES5
// in node_tree.ts do the type-checking.
var typescriptTree = compileWithTypescript(modulesTree, {
allowNonTsExtensions: false,
declaration: true,
emitDecoratorMetadata: true,
mapRoot: '', // force sourcemaps to use relative path
noEmitOnError: false, // temporarily ignore errors, we type-check only via cjs build
rootDir: '.',
sourceMap: true,
sourceRoot: '.',
target: 'ES6'
});
typescriptTree = stew.rename(typescriptTree, '.js', '.es6');
var es6Tree = mergeTrees([traceurTree, typescriptTree]);
// TODO(iminar): tree differ seems to have issues with trees created by mergeTrees, investigate!
// ENOENT error is thrown while doing fs.readdirSync on inputRoot
// in the meantime, we just do noop mv to create a new tree
es6Tree = stew.mv(es6Tree, '');
// Call Traceur again to lower the ES6 build tree to ES5
var es5Tree = transpileWithTraceur(es6Tree, {
destExtension: '.js',
destSourceMapExtension: '.js.map',
traceurOptions: {modules: 'instantiate', sourceMaps: true}
});
// Now we add a few more files to the es6 tree that Traceur should not see
['angular2', 'rtts_assert'].forEach(function(destDir) {
var extras = new Funnel('tools/build', {files: ['es5build.js'], destDir: destDir});
es6Tree = mergeTrees([es6Tree, extras]);
});
var vendorScriptsTree = flatten(new Funnel('.', {
files: [
'zone/es6-promise.js',
'zone/zone.js',
'zone/long-stack-trace-zone.js',
'node_modules/es6-module-loader/dist/es6-module-loader-sans-promises.src.js',
'node_modules/systemjs/dist/system.src.js',
'node_modules/systemjs/lib/extension-register.js',
'node_modules/systemjs/lib/extension-cjs.js',
'node_modules/rx/dist/rx.js',
'node_modules/reflect-metadata/Reflect.js',
'tools/build/snippets/runtime_paths.js',
path.relative(projectRootDir, TRACEUR_RUNTIME_PATH)
]
}));
var vendorScripts_benchmark =
new Funnel('tools/build/snippets', {files: ['url_params_to_form.js'], destDir: '/'});
var vendorScripts_benchmarks_external =
new Funnel('node_modules/angular', {files: ['angular.js'], destDir: '/'});
var servingTrees = [];
function copyVendorScriptsTo(destDir) {
servingTrees.push(new Funnel(vendorScriptsTree, {srcDir: '/', destDir: destDir}));
if (destDir.indexOf('benchmarks') > -1) {
servingTrees.push(new Funnel(vendorScripts_benchmark, {srcDir: '/', destDir: destDir}));
}
if (destDir.indexOf('benchmarks_external') > -1) {
servingTrees.push(
new Funnel(vendorScripts_benchmarks_external, {srcDir: '/', destDir: destDir}));
}
}
function writeScriptsForPath(relativePath, result) {
copyVendorScriptsTo(path.dirname(relativePath));
return result.replace('@@FILENAME_NO_EXT', relativePath.replace(/\.\w+$/, ''));
}
var htmlTree = new Funnel(modulesTree, {include: ['*/src/**/*.html'], destDir: '/'});
htmlTree = replace(htmlTree, {
files: ['examples*/**'],
patterns: [{match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS')}],
replaceWithPath: writeScriptsForPath
});
htmlTree = replace(htmlTree, {
files: ['benchmarks/**'],
patterns: [{match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS_benchmarks')}],
replaceWithPath: writeScriptsForPath
});
htmlTree = replace(htmlTree, {
files: ['benchmarks_external/**'],
patterns: [{match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS_benchmarks_external')}],
replaceWithPath: writeScriptsForPath
});
// Copy all vendor scripts into all examples and benchmarks
['benchmarks/src', 'benchmarks_external/src', 'examples/src/benchpress'].forEach(
copyVendorScriptsTo);
var scripts = mergeTrees(servingTrees, {overwrite: true});
var css = new Funnel(modulesTree, {include: ["**/*.css"]});
var polymerFiles = new Funnel('.', {
files: [
'bower_components/polymer/lib/polymer.html',
'tools/build/snippets/url_params_to_form.js'
]
});
var polymer = stew.mv(flatten(polymerFiles), 'benchmarks_external/src/tree/polymer');
var reactFiles = new Funnel('.', {files: ['node_modules/react/dist/react.min.js']});
var react = stew.mv(flatten(reactFiles), 'benchmarks_external/src/tree/react');
htmlTree = mergeTrees([htmlTree, scripts, polymer, css, react]);
es5Tree = mergeTrees([es5Tree, htmlTree]);
var mergedTree = mergeTrees([stew.mv(es6Tree, '/es6'), stew.mv(es5Tree, '/es5')]);
// TODO(iminar): tree differ seems to have issues with trees created by mergeTrees, investigate!
// ENOENT error is thrown while doing fs.readdirSync on inputRoot
// in the meantime, we just do noop mv to create a new tree
mergedTree = stew.mv(mergedTree, '');
return destCopy(mergedTree, destinationPath);
};