Skip to content

Commit

Permalink
start on babel module bundling and type inferrence
Browse files Browse the repository at this point in the history
  • Loading branch information
sebmck committed May 1, 2015
1 parent 5080534 commit aaf4cbf
Show file tree
Hide file tree
Showing 12 changed files with 213 additions and 98 deletions.
2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -28,6 +28,7 @@
},
"dependencies": {
"ast-types": "~0.7.0",
"bluebird": "^2.9.25",
"chalk": "^1.0.0",
"convert-source-map": "^1.1.0",
"core-js": "^0.9.0",
Expand All @@ -49,6 +50,7 @@
"regenerator": "^0.8.20",
"regexpu": "^1.1.2",
"repeating": "^1.1.2",
"resolve": "^1.1.6",
"shebang-regex": "^1.0.0",
"slash": "^1.0.0",
"source-map": "^0.4.0",
Expand Down
1 change: 1 addition & 0 deletions src/babel/api/node.js
Expand Up @@ -9,6 +9,7 @@ export { canCompile } from "../util";

export { default as options } from "../transformation/file/options";
export { default as Transformer } from "../transformation/transformer";
export { default as Pipeline } from "../transformation/transformer-pipeline";
export { default as traverse } from "../traversal";
export { default as buildExternalHelpers } from "../tools/build-external-helpers";
export { version } from "../../../package";
Expand Down
15 changes: 15 additions & 0 deletions src/babel/transformation/bundler/index.js
@@ -0,0 +1,15 @@
export default class Bundler {
constructor(opts) {
this.resolvers = [];
this.cache = {};
this.opts = opts;
}

addResolver(resolver) {
this.resolvers.push(resolver);
}

transform() {

}
}
25 changes: 25 additions & 0 deletions src/babel/transformation/bundler/resolvers/node.js
@@ -0,0 +1,25 @@
import { Promise } from "bluebird";
import resolve from "resolve";
import path from "path";
import fs from "fs";

export default function (request, parent) {
return new Promise(function (resolve, reject) {
resolve(request, { basedir: path.dirname(parent) }, function (err, res) {
if (err) {
resolve(null);
} else {
fs.readFile(res, "utf8", function (err) {
if (err) {
reject(err);
} else {
resolve({
filename: filename,
content: content
});
}
});
}
});
});
}
16 changes: 9 additions & 7 deletions src/babel/transformation/file/index.js
@@ -1,5 +1,6 @@
import convertSourceMap from "convert-source-map";
import * as optionParsers from "./option-parsers";
import moduleFormatters from "../modules";
import PluginManager from "./plugin-manager";
import shebangRegex from "shebang-regex";
import TraversalPath from "../../traversal/path";
Expand Down Expand Up @@ -38,7 +39,7 @@ function checkPath(stack, path) {
}

export default class File {
constructor(opts = {}) {
constructor(opts = {}, pipeline) {
this.dynamicImportTypes = {};
this.dynamicImportIds = {};
this.dynamicImports = [];
Expand All @@ -49,9 +50,10 @@ export default class File {
this.data = {};
this.uids = {};

this.log = new Logger(this, opts.filename || "unknown");
this.opts = this.normalizeOptions(opts);
this.ast = {};
this.pipeline = pipeline;
this.log = new Logger(this, opts.filename || "unknown");
this.opts = this.normalizeOptions(opts);
this.ast = {};

this.buildTransformers();
}
Expand Down Expand Up @@ -133,7 +135,7 @@ export default class File {
}

var optionParser = optionParsers[option.type];
if (optionParser) val = optionParser(key, val);
if (optionParser) val = optionParser(key, val, this.pipeline);

if (option.alias) {
opts[option.alias] = opts[option.alias] || val;
Expand Down Expand Up @@ -200,7 +202,7 @@ export default class File {
var stack = [];

// build internal transformers
each(transform.transformers, function (transformer, key) {
each(this.pipeline.transformers, function (transformer, key) {
var pass = transformers[key] = transformer.buildPass(file);

if (pass.canTransform()) {
Expand Down Expand Up @@ -235,7 +237,7 @@ export default class File {
}

getModuleFormatter(type: string) {
var ModuleFormatter = isFunction(type) ? type : transform.moduleFormatters[type];
var ModuleFormatter = isFunction(type) ? type : moduleFormatters[type];

if (!ModuleFormatter) {
var loc = util.resolveRelative(type);
Expand Down
7 changes: 3 additions & 4 deletions src/babel/transformation/file/option-parsers.js
@@ -1,14 +1,13 @@
import transform from "./../index";
import * as util from "../../util";

export function transformerList(key, val) {
export function transformerList(key, val, pipeline) {
val = util.arrayify(val);

if (val.indexOf("all") >= 0 || val.indexOf(true) >= 0) {
val = Object.keys(transform.transformers);
val = Object.keys(pipeline.transformers);
}

return transform._ensureTransformerNames(key, val);
return pipeline._ensureTransformerNames(key, val);
}

export function number(key, val) {
Expand Down
80 changes: 23 additions & 57 deletions src/babel/transformation/index.js
@@ -1,68 +1,34 @@
import normalizeAst from "../helpers/normalize-ast";
import Transformer from "./transformer";
import object from "../helpers/object";
import File from "./file";
import each from "lodash/collection/each";
import Pipeline from "./transformer-pipeline";

export default function transform(code: string, opts?: Object) {
var file = new File(opts);
return file.parse(code);
}
var pipeline = new Pipeline;

transform.fromAst = function (ast, code, opts) {
ast = normalizeAst(ast);
//

var file = new File(opts);
file.addCode(code);
file.transform(ast);
return file.generate();
};
import transformers from "./transformers";
pipeline.addTransformers(transformers);

transform._ensureTransformerNames = function (type: string, rawKeys: Array<string>) {
var keys = [];
//

for (var i = 0; i < rawKeys.length; i++) {
var key = rawKeys[i];
import deprecated from "./transformers/deprecated";
pipeline.addDeprecated(deprecated);

var deprecatedKey = transform.deprecatedTransformerMap[key];
var aliasKey = transform.aliasTransformerMap[key];
if (aliasKey) {
keys.push(aliasKey);
} else if (deprecatedKey) {
// deprecated key, remap it to the new one
console.error(`The transformer ${key} has been renamed to ${deprecatedKey}`);
rawKeys.push(deprecatedKey);
} else if (transform.transformers[key]) {
// valid key
keys.push(key);
} else if (transform.namespaces[key]) {
// namespace, append all transformers within this namespace
keys = keys.concat(transform.namespaces[key]);
} else {
// invalid key
throw new ReferenceError(`Unknown transformer ${key} specified in ${type}`);
}
}
//

return keys;
};
import aliases from "./transformers/aliases";
pipeline.addDeprecated(aliases);

transform.transformerNamespaces = object();
transform.transformers = object();
transform.namespaces = object();
//

transform.deprecatedTransformerMap = require("./transformers/deprecated");
transform.aliasTransformerMap = require("./transformers/aliases");
transform.moduleFormatters = require("./modules");
import * as filters from "./transformers/filters";
pipeline.addFilter(filters.internal);
pipeline.addFilter(filters.blacklist);
pipeline.addFilter(filters.whitelist);
pipeline.addFilter(filters.stage);
pipeline.addFilter(filters.optional);

import rawTransformers from "./transformers";
//

each(rawTransformers, function (transformer, key) {
var namespace = key.split(".")[0];

transform.namespaces[namespace] = transform.namespaces[namespace] || [];
transform.namespaces[namespace].push(key);
transform.transformerNamespaces[key] = namespace;

transform.transformers[key] = new Transformer(key, transformer);
});
var transform = pipeline.transform.bind(pipeline);
transform.fromAst = pipeline.transformFromAst.bind(pipeline);
transform.pipeline = pipeline;
export default transform;
25 changes: 1 addition & 24 deletions src/babel/transformation/transformer-pass.js
Expand Up @@ -17,30 +17,7 @@ export default class TransformerPass {
}

canTransform(): boolean {
var transformer = this.transformer;

var opts = this.file.opts;
var key = transformer.key;

// internal
if (key[0] === "_") return true;

// blacklist
var blacklist = opts.blacklist;
if (blacklist.length && includes(blacklist, key)) return false;

// whitelist
var whitelist = opts.whitelist;
if (whitelist) return includes(whitelist, key);

// stage
var stage = transformer.metadata.stage;
if (stage != null && stage >= opts.stage) return true;

// optional
if (transformer.metadata.optional && !includes(opts.optional, key)) return false;

return true;
return this.file.pipeline.canTransform(this.transformer, this.file.opts);
}

checkPath(path: TraversalPath): boolean {
Expand Down
105 changes: 105 additions & 0 deletions src/babel/transformation/transformer-pipeline.js
@@ -0,0 +1,105 @@
import Transformer from "./transformer";
import normalizeAst from "../helpers/normalize-ast";
import Bundler from "./bundler";
import assign from "lodash/object/assign";
import object from "../helpers/object";
import File from "./file";

export default class TransformerPipeline {
constructor() {
this.transformers = object();
this.namespaces = object();
this.deprecated = object();
this.aliases = object();
this.filters = [];
}

addTransformers(transformers) {
for (var key in transformers) {
this.addTransformer(key, transformers[key]);
}
return this;
}

addTransformer(key, transformer) {
if (this.transformers[key]) throw new Error(); // todo: error

var namespace = key.split(".")[0];
this.namespaces[namespace] = this.namespaces[namespace] || [];
this.namespaces[namespace].push(key);
this.namespaces[key] = namespace;

this.transformers[key] = new Transformer(key, transformer);
}

addAliases(names) {
assign(this.aliases, names);
return this;
}

addDeprecated(names) {
assign(this.deprecated, names);
return this;
}

addFilter(filter: Function) {
this.filters.push(filter);
return this;
}

canTransform(transformer, fileOpts) {
for (var filter of (this.filters: Array)) {
var result = filter(transformer, fileOpts);
if (result != null) return result;
}

return true;
}

transform(code: string, opts?: Object) {
var file = new File(opts, this);
return file.parse(code);
}

transformFromAst(ast, code, opts) {
ast = normalizeAst(ast);

var file = new File(opts, this);
file.addCode(code);
file.transform(ast);
return file.generate();
}

createBundler() {
return new Bundler(this);
}

_ensureTransformerNames(type: string, rawKeys: Array<string>) {
var keys = [];

for (var i = 0; i < rawKeys.length; i++) {
var key = rawKeys[i];

var deprecatedKey = this.deprecated[key];
var aliasKey = this.aliases[key];
if (aliasKey) {
keys.push(aliasKey);
} else if (deprecatedKey) {
// deprecated key, remap it to the new one
console.error(`The transformer ${key} has been renamed to ${deprecatedKey}`);
rawKeys.push(deprecatedKey);
} else if (this.transformers[key]) {
// valid key
keys.push(key);
} else if (this.namespaces[key]) {
// namespace, append all transformers within this namespace
keys = keys.concat(this.namespaces[key]);
} else {
// invalid key
throw new ReferenceError(`Unknown transformer ${key} specified in ${type}`);
}
}

return keys;
}
}
3 changes: 1 addition & 2 deletions src/babel/transformation/transformer.js
Expand Up @@ -15,7 +15,7 @@ import each from "lodash/collection/each";
*/

export default class Transformer {
constructor(transformerKey: string, transformer: Object, opts: Object) {
constructor(transformerKey: string, transformer: Object) {
transformer = assign({}, transformer);

var take = function (key) {
Expand All @@ -40,7 +40,6 @@ export default class Transformer {
//

this.handlers = this.normalize(transformer);
this.opts = this.opts || {};
this.key = transformerKey;

//
Expand Down

13 comments on commit aaf4cbf

@intuitivepixel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this commit ember s breaks with and endless ... (ember-cli v0.2.3 & node v0.12.0)

The transformer useStrict has been renamed to strict
The transformer useStrict has been renamed to strict
The transformer useStrict has been renamed to strict
The transformer useStrict has been renamed to strict
The transformer useStrict has been renamed to strict
The transformer useStrict has been renamed to strict
The transformer useStrict has been renamed to strict
The transformer useStrict has been renamed to strict
The transformer useStrict has been renamed to strict
The transformer useStrict has been renamed to strict
The transformer useStrict has been renamed to strict
...

@sebmck
Copy link
Contributor Author

@sebmck sebmck commented on aaf4cbf May 1, 2015 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@intuitivepixel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but ember s never comes up, it's just returns to the console prompt after endless of this messages...

@intuitivepixel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a workaround? This is breaking our CI process

@sebmck
Copy link
Contributor Author

@sebmck sebmck commented on aaf4cbf May 1, 2015 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sebmck
Copy link
Contributor Author

@sebmck sebmck commented on aaf4cbf May 1, 2015 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@intuitivepixel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't get me wrong, I don't want you to do anything you don't want to do :) It's just that all that are referencing this module use "^5.0.0" which get's this version and even if I stay on 5.0.0 it doesn't work

@intuitivepixel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was not happening yesterday that's my point, and i see you commited this 10h ago, so this fit's in the time range

@sebmck
Copy link
Contributor Author

@sebmck sebmck commented on aaf4cbf May 1, 2015 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@intuitivepixel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AMAZING!!! 👍 You made my day man :)

$ ember s
version: 0.2.3
Could not find watchman, falling back to NodeWatcher for file system events.
Visit http://www.ember-cli.com/#watchman for more info.
Livereload server on port 35729
Serving on http://localhost:4200/

Build successful - 36525ms.

Slowest Trees                                 | Total
----------------------------------------------+---------------------
Babel                                         | 13105ms
JSHint app- QUnit                             | 6868ms
Concat: Vendor                                | 4402ms
ES6: App Tree                                 | 4030ms
Babel                                         | 2119ms

Slowest Trees (cumulative)                    | Total (avg)
----------------------------------------------+---------------------
Babel (3)                                     | 15750ms (5250 ms)
JSHint app- QUnit (1)                         | 6868ms
Concat: Vendor (1)                            | 4402ms
ES6: App Tree (1)                             | 4030ms

and believe me this would have bitten more people, it's just that it was 10hours out only :)

@intuitivepixel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much again for the quick response

@sebmck
Copy link
Contributor Author

@sebmck sebmck commented on aaf4cbf May 1, 2015 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sebmck
Copy link
Contributor Author

@sebmck sebmck commented on aaf4cbf May 1, 2015 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.