From 98a4d54212e90540f9b64f9daf647fa0968997e1 Mon Sep 17 00:00:00 2001 From: Arthur Verschaeve Date: Sat, 18 Jul 2015 10:59:20 +0200 Subject: [PATCH 1/6] Add `make test-cov` to `contributing.md` Ref #1851 --- CONTRIBUTING.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1e6e5c1909..36b8c53a42 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,6 +72,12 @@ Use the `TEST_GREP` variable to run a subset of tests by name: $ TEST_GREP=transformation make test ``` +To test the code coverage, use: + +```sh +$ make test-cov +``` + #### Internals Please see [`/doc`](/doc) for internals documentation relevant to developing babel. From eed750206c24ed8dc2c5c934abc9d7ec4a728c57 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Tue, 30 Jun 2015 01:22:06 -0500 Subject: [PATCH 2/6] Convert template objects to singletons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create file-scoped template objects that are instantiated once and reused between different tagged template evaluations. This is a closer match to the spec behavior which demands reuse, but does not match the spec exactly with respect to scoping as it’s possible to have similar template objects defined in different file scopes within the same program. For now we are not able to cleanly handle this case as it would require a registry or similar lookup mechanism that is consistent across different combinations of builds and optimizers. This has a 40x increase in six-speed throughput. Partial fix for #971 --- .../babel/src/transformation/file/index.js | 24 +++++++++++++++++++ .../transformers/es6/template-literals.js | 4 +++- packages/babel/src/traversal/scope/index.js | 5 ++-- .../es6.template-literals/tag-loose/actual.js | 2 ++ .../tag-loose/expected.js | 4 +++- .../es6.template-literals/tag/expected.js | 8 ++++++- 6 files changed, 42 insertions(+), 5 deletions(-) diff --git a/packages/babel/src/transformation/file/index.js b/packages/babel/src/transformation/file/index.js index 6505704cb3..7a81feb583 100644 --- a/packages/babel/src/transformation/file/index.js +++ b/packages/babel/src/transformation/file/index.js @@ -407,6 +407,30 @@ export default class File { return uid; } + addTemplateObject(helperName: string, strings: Array, raw: Array): Object { + // Generate a unique name based on the string literals so we dedupe + // identical strings used in the program. + var stringIds = raw.elements.map(function(string) { + return string.value; + }); + var name = `${helperName}_${raw.elements.length}_${stringIds.join(",")}`; + + var declar = this.declarations[name]; + if (declar) return declar; + + var uid = this.declarations[name] = this.scope.generateUidIdentifier(name); + + var helperId = this.addHelper(helperName); + var init = t.callExpression(helperId, [strings, raw]); + init._compact = true; + this.scope.push({ + id: uid, + init: init, + _blockHoist: 1.9 // This ensures that we don't fail if not using function expression helpers + }); + return uid; + } + /** * [Please add a description.] */ diff --git a/packages/babel/src/transformation/transformers/es6/template-literals.js b/packages/babel/src/transformation/transformers/es6/template-literals.js index 83f35c5e89..b561f64757 100644 --- a/packages/babel/src/transformation/transformers/es6/template-literals.js +++ b/packages/babel/src/transformation/transformers/es6/template-literals.js @@ -64,7 +64,9 @@ export var visitor = { var templateName = "tagged-template-literal"; if (file.isLoose("es6.templateLiterals")) templateName += "-loose"; - args.push(t.callExpression(file.addHelper(templateName), [strings, raw])); + + var templateObject = file.addTemplateObject(templateName, strings, raw); + args.push(templateObject); args = args.concat(quasi.expressions); diff --git a/packages/babel/src/traversal/scope/index.js b/packages/babel/src/traversal/scope/index.js index 7ef81af584..e588276c68 100644 --- a/packages/babel/src/traversal/scope/index.js +++ b/packages/babel/src/traversal/scope/index.js @@ -829,14 +829,15 @@ export default class Scope { var unique = opts.unique; var kind = opts.kind || "var"; + var blockHoist = opts._blockHoist || 2; - var dataKey = `declaration:${kind}`; + var dataKey = `declaration:${kind}:${blockHoist}`; var declar = !unique && path.getData(dataKey); if (!declar) { declar = t.variableDeclaration(kind, []); declar._generated = true; - declar._blockHoist = 2; + declar._blockHoist = blockHoist; this.hub.file.attachAuxiliaryComment(declar); diff --git a/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/actual.js b/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/actual.js index 7fe1864736..cfa5638dbd 100644 --- a/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/actual.js +++ b/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/actual.js @@ -1 +1,3 @@ var foo = bar`wow\na${ 42 }b ${_.foobar()}`; +var bar = bar`wow\nab${ 42 } ${_.foobar()}`; +var bar = bar`wow\naB${ 42 } ${_.foobar()}`; diff --git a/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/expected.js b/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/expected.js index a2264017ba..3665e56ad2 100644 --- a/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/expected.js +++ b/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/expected.js @@ -1,5 +1,7 @@ "use strict"; +var _taggedTemplateLiteralLoose_3_wowNaB = _taggedTemplateLiteralLoose(["wow\na", "b ", ""], ["wow\\na", "b ", ""]); + function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; } -var foo = bar(_taggedTemplateLiteralLoose(["wow\na", "b ", ""], ["wow\\na", "b ", ""]), 42, _.foobar()); \ No newline at end of file +var foo = bar(_taggedTemplateLiteralLoose_3_wowNaB, 42, _.foobar()); \ No newline at end of file diff --git a/packages/babel/test/fixtures/transformation/es6.template-literals/tag/expected.js b/packages/babel/test/fixtures/transformation/es6.template-literals/tag/expected.js index db7bc65355..1a4289dd50 100644 --- a/packages/babel/test/fixtures/transformation/es6.template-literals/tag/expected.js +++ b/packages/babel/test/fixtures/transformation/es6.template-literals/tag/expected.js @@ -1,5 +1,11 @@ "use strict"; +var _taggedTemplateLiteral_3_wowNaB = _taggedTemplateLiteral(["wow\na", "b ", ""], ["wow\\na", "b ", ""]), + _taggedTemplateLiteral_3_wowNab = _taggedTemplateLiteral(["wow\nab", " ", ""], ["wow\\nab", " ", ""]), + _taggedTemplateLiteral_3_wowNaB2 = _taggedTemplateLiteral(["wow\naB", " ", ""], ["wow\\naB", " ", ""]); + function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } -var foo = bar(_taggedTemplateLiteral(["wow\na", "b ", ""], ["wow\\na", "b ", ""]), 42, _.foobar()); \ No newline at end of file +var foo = bar(_taggedTemplateLiteral_3_wowNaB, 42, _.foobar()); +var bar = bar(_taggedTemplateLiteral_3_wowNab, 42, _.foobar()); +var bar = bar(_taggedTemplateLiteral_3_wowNaB2, 42, _.foobar()); \ No newline at end of file From b2e3a73e2ff406778a65415747391df6bf85a2ce Mon Sep 17 00:00:00 2001 From: kpdecker Date: Sun, 19 Jul 2015 10:39:38 +0300 Subject: [PATCH 3/6] Use generic name for templateObject Rather than using variable names that could be quite long, just use indexed generic names that use runtime lookup for the string parameter mapping. --- packages/babel/src/transformation/file/index.js | 2 +- .../es6.template-literals/tag-loose/actual.js | 2 +- .../es6.template-literals/tag-loose/expected.js | 8 ++++++-- .../transformation/es6.template-literals/tag/expected.js | 8 ++------ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/babel/src/transformation/file/index.js b/packages/babel/src/transformation/file/index.js index 7a81feb583..1253224892 100644 --- a/packages/babel/src/transformation/file/index.js +++ b/packages/babel/src/transformation/file/index.js @@ -418,7 +418,7 @@ export default class File { var declar = this.declarations[name]; if (declar) return declar; - var uid = this.declarations[name] = this.scope.generateUidIdentifier(name); + var uid = this.declarations[name] = this.scope.generateUidIdentifier("templateObject"); var helperId = this.addHelper(helperName); var init = t.callExpression(helperId, [strings, raw]); diff --git a/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/actual.js b/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/actual.js index cfa5638dbd..52419bb505 100644 --- a/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/actual.js +++ b/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/actual.js @@ -1,3 +1,3 @@ var foo = bar`wow\na${ 42 }b ${_.foobar()}`; var bar = bar`wow\nab${ 42 } ${_.foobar()}`; -var bar = bar`wow\naB${ 42 } ${_.foobar()}`; +var bar = bar`wow\naB${ 42 } ${_.baz()}`; diff --git a/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/expected.js b/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/expected.js index 3665e56ad2..9378680632 100644 --- a/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/expected.js +++ b/packages/babel/test/fixtures/transformation/es6.template-literals/tag-loose/expected.js @@ -1,7 +1,11 @@ "use strict"; -var _taggedTemplateLiteralLoose_3_wowNaB = _taggedTemplateLiteralLoose(["wow\na", "b ", ""], ["wow\\na", "b ", ""]); +var _templateObject = _taggedTemplateLiteralLoose(["wow\na", "b ", ""], ["wow\\na", "b ", ""]), + _templateObject2 = _taggedTemplateLiteralLoose(["wow\nab", " ", ""], ["wow\\nab", " ", ""]), + _templateObject3 = _taggedTemplateLiteralLoose(["wow\naB", " ", ""], ["wow\\naB", " ", ""]); function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; } -var foo = bar(_taggedTemplateLiteralLoose_3_wowNaB, 42, _.foobar()); \ No newline at end of file +var foo = bar(_templateObject, 42, _.foobar()); +var bar = bar(_templateObject2, 42, _.foobar()); +var bar = bar(_templateObject3, 42, _.baz()); \ No newline at end of file diff --git a/packages/babel/test/fixtures/transformation/es6.template-literals/tag/expected.js b/packages/babel/test/fixtures/transformation/es6.template-literals/tag/expected.js index 1a4289dd50..7749db566b 100644 --- a/packages/babel/test/fixtures/transformation/es6.template-literals/tag/expected.js +++ b/packages/babel/test/fixtures/transformation/es6.template-literals/tag/expected.js @@ -1,11 +1,7 @@ "use strict"; -var _taggedTemplateLiteral_3_wowNaB = _taggedTemplateLiteral(["wow\na", "b ", ""], ["wow\\na", "b ", ""]), - _taggedTemplateLiteral_3_wowNab = _taggedTemplateLiteral(["wow\nab", " ", ""], ["wow\\nab", " ", ""]), - _taggedTemplateLiteral_3_wowNaB2 = _taggedTemplateLiteral(["wow\naB", " ", ""], ["wow\\naB", " ", ""]); +var _templateObject = _taggedTemplateLiteral(["wow\na", "b ", ""], ["wow\\na", "b ", ""]); function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } -var foo = bar(_taggedTemplateLiteral_3_wowNaB, 42, _.foobar()); -var bar = bar(_taggedTemplateLiteral_3_wowNab, 42, _.foobar()); -var bar = bar(_taggedTemplateLiteral_3_wowNaB2, 42, _.foobar()); \ No newline at end of file +var foo = bar(_templateObject, 42, _.foobar()); From 08762098470541e9d4d70ba28ed92bcefe3f112c Mon Sep 17 00:00:00 2001 From: Franky Chung Date: Sun, 19 Jul 2015 12:01:40 +0900 Subject: [PATCH 4/6] Add number literal type annotations for flow --- .../babel/src/generation/generators/flow.js | 6 + packages/babel/src/types/definitions/flow.js | 4 + .../flow/number-literal-types/actual.js | 5 + .../flow/number-literal-types/expected.js | 5 + packages/babylon/src/plugins/flow.js | 6 + packages/babylon/test/tests-flow.js | 202 ++++++++++++++++++ 6 files changed, 228 insertions(+) create mode 100644 packages/babel/test/fixtures/generation/flow/number-literal-types/actual.js create mode 100644 packages/babel/test/fixtures/generation/flow/number-literal-types/expected.js diff --git a/packages/babel/src/generation/generators/flow.js b/packages/babel/src/generation/generators/flow.js index 5c061ce9a6..761a19928a 100644 --- a/packages/babel/src/generation/generators/flow.js +++ b/packages/babel/src/generation/generators/flow.js @@ -177,6 +177,12 @@ export function NullableTypeAnnotation(node, print) { print.plain(node.typeAnnotation); } +/** + * Prints NumberLiteralTypeAnnotation, prints value. + */ + +export { Literal as NumberLiteralTypeAnnotation } from "./types"; + /** * Prints NumberTypeAnnotation. */ diff --git a/packages/babel/src/types/definitions/flow.js b/packages/babel/src/types/definitions/flow.js index 448300e123..4380f13cf6 100644 --- a/packages/babel/src/types/definitions/flow.js +++ b/packages/babel/src/types/definitions/flow.js @@ -82,6 +82,10 @@ define("NullableTypeAnnotation", { aliases: ["Flow"] }); +define("NumberLiteralTypeAnnotation", { + aliases: ["Flow"] +}); + define("NumberTypeAnnotation", { aliases: ["Flow", "FlowBaseAnnotation"] }); diff --git a/packages/babel/test/fixtures/generation/flow/number-literal-types/actual.js b/packages/babel/test/fixtures/generation/flow/number-literal-types/actual.js new file mode 100644 index 0000000000..8aa0ffac4b --- /dev/null +++ b/packages/babel/test/fixtures/generation/flow/number-literal-types/actual.js @@ -0,0 +1,5 @@ +var a: 123; +var a: 123.0; +var a: 0x7B; +var a: 0b1111011; +var a: 0o173; diff --git a/packages/babel/test/fixtures/generation/flow/number-literal-types/expected.js b/packages/babel/test/fixtures/generation/flow/number-literal-types/expected.js new file mode 100644 index 0000000000..c8e24031f1 --- /dev/null +++ b/packages/babel/test/fixtures/generation/flow/number-literal-types/expected.js @@ -0,0 +1,5 @@ +var a: 123; +var a: 123.0; +var a: 0x7B; +var a: 123; +var a: 123; diff --git a/packages/babylon/src/plugins/flow.js b/packages/babylon/src/plugins/flow.js index c85d4b3330..1f7e058b82 100644 --- a/packages/babylon/src/plugins/flow.js +++ b/packages/babylon/src/plugins/flow.js @@ -505,6 +505,12 @@ pp.flowParsePrimaryType = function () { this.next(); return this.finishNode(node, "StringLiteralTypeAnnotation"); + case tt.num: + node.value = this.value; + node.raw = this.input.slice(this.start, this.end); + this.next(); + return this.finishNode(node, "NumberLiteralTypeAnnotation"); + default: if (this.type.keyword === "typeof") { return this.flowParseTypeofType(); diff --git a/packages/babylon/test/tests-flow.js b/packages/babylon/test/tests-flow.js index f65101449a..a9dc643cd9 100644 --- a/packages/babylon/test/tests-flow.js +++ b/packages/babylon/test/tests-flow.js @@ -10094,6 +10094,208 @@ var fbTestFixture = { } }, }, + 'Number Literal Types': { + 'var a: 123': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'a', + typeAnnotation: { + type: 'TypeAnnotation', + typeAnnotation: { + type: 'NumberLiteralTypeAnnotation', + value: 123, + raw: '123', + range: [7, 10], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 10 } + } + }, + range: [5, 10], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 10 } + } + } + }, + init: null, + range: [4, 10], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 10 } + } + }], + kind: 'var', + range: [0, 10], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + }, + 'var a: 123.0': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'a', + typeAnnotation: { + type: 'TypeAnnotation', + typeAnnotation: { + type: 'NumberLiteralTypeAnnotation', + value: 123, + raw: '123.0', + range: [7, 12], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 12 } + } + }, + range: [5, 12], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 12 } + } + } + }, + init: null, + range: [4, 12], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 12 } + } + }], + kind: 'var', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + 'var a: 0x7B': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'a', + typeAnnotation: { + type: 'TypeAnnotation', + typeAnnotation: { + type: 'NumberLiteralTypeAnnotation', + value: 123, + raw: '0x7B', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + range: [5, 11], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 11 } + } + } + }, + init: null, + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }], + kind: 'var', + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + 'var a: 0b1111011': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'a', + typeAnnotation: { + type: 'TypeAnnotation', + typeAnnotation: { + type: 'NumberLiteralTypeAnnotation', + value: 123, + raw: '0b1111011', + range: [7, 16], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 16 } + } + }, + range: [5, 16], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 16 } + } + } + }, + init: null, + range: [4, 16], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }], + kind: 'var', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + 'var a: 0o173': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'a', + typeAnnotation: { + type: 'TypeAnnotation', + typeAnnotation: { + type: 'NumberLiteralTypeAnnotation', + value: 123, + raw: '0o173', + range: [7, 12], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 12 } + } + }, + range: [5, 12], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 12 } + } + } + }, + init: null, + range: [4, 12], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 12 } + } + }], + kind: 'var', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + } + }, 'Qualified Generic Type': { 'var a : A.B': { type: 'VariableDeclaration', From 4eb1a45f0218bbd7d9e08f6397ac6a41e5d2731c Mon Sep 17 00:00:00 2001 From: kpdecker Date: Mon, 20 Jul 2015 11:06:09 +0300 Subject: [PATCH 5/6] Handle _blockHoist value of zero safely --- packages/babel/src/traversal/scope/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/babel/src/traversal/scope/index.js b/packages/babel/src/traversal/scope/index.js index e588276c68..0d577152b4 100644 --- a/packages/babel/src/traversal/scope/index.js +++ b/packages/babel/src/traversal/scope/index.js @@ -829,7 +829,7 @@ export default class Scope { var unique = opts.unique; var kind = opts.kind || "var"; - var blockHoist = opts._blockHoist || 2; + var blockHoist = opts._blockHoist == null ? 2 : opts._blockHoist; var dataKey = `declaration:${kind}:${blockHoist}`; var declar = !unique && path.getData(dataKey); From 029146719ef66c6e46a90382347eff4368409994 Mon Sep 17 00:00:00 2001 From: Jesse McCarthy Date: Mon, 20 Jul 2015 12:37:24 -0400 Subject: [PATCH 6/6] Add basic desc. & existence test for pretransform. --- packages/babel/src/transformation/pipeline.js | 2 +- packages/babel/test/api.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/babel/src/transformation/pipeline.js b/packages/babel/src/transformation/pipeline.js index 0da9f4dff8..7e2444ddc7 100644 --- a/packages/babel/src/transformation/pipeline.js +++ b/packages/babel/src/transformation/pipeline.js @@ -110,7 +110,7 @@ export default class Pipeline { } /** - * [Please add a description.] + * Build dependency graph by recursing `metadata.modules`. WIP. */ pretransform(code: string, opts?: Object) { diff --git a/packages/babel/test/api.js b/packages/babel/test/api.js index a612e11fa7..04394bcd43 100644 --- a/packages/babel/test/api.js +++ b/packages/babel/test/api.js @@ -4,6 +4,7 @@ var buildExternalHelpers = require("../lib/tools/build-external-helpers"); var PluginManager = require("../lib/transformation/file/plugin-manager"); var Transformer = require("../lib/transformation/transformer"); var transform = require("../lib/transformation"); +var Pipeline = require("../lib/transformation/pipeline"); var assert = require("assert"); var File = require("../lib/transformation/file"); @@ -413,6 +414,11 @@ suite("api", function () { assert.ok(file2.opts.extra !== file3.opts.extra); }); + // For now just signal that it's not cruft and shouldn't be deleted. + test("pretransform exists", function () { + assert.ok(Pipeline.prototype.pretransform); + }); + suite("buildExternalHelpers", function () { test("all", function () { var script = buildExternalHelpers();