From 0e19006641a06d34e5b276d1c9ea7ee845884a52 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Mon, 29 Sep 2014 18:29:08 +1000 Subject: [PATCH] add destructuring support --- FEATURES.md | 4 +- README.md | 4 +- lib/6to5/templates/variable-assign.js | 1 + .../transformers/destructuring-assignment.js | 0 lib/6to5/transformers/destructuring.js | 112 ++++++++++++++++++ test/fixtures/destructuring/array/actual.js | 1 + test/fixtures/destructuring/array/expected.js | 5 + test/fixtures/destructuring/mixed/actual.js | 1 + test/fixtures/destructuring/mixed/expected.js | 4 + .../fixtures/destructuring/multiple/actual.js | 1 + .../destructuring/multiple/expected.js | 3 + .../destructuring/object-advanced/actual.js | 1 + .../destructuring/object-advanced/expected.js | 4 + .../destructuring/object-basic/actual.js | 1 + .../destructuring/object-basic/expected.js | 2 + 15 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 lib/6to5/templates/variable-assign.js delete mode 100644 lib/6to5/transformers/destructuring-assignment.js create mode 100644 lib/6to5/transformers/destructuring.js create mode 100644 test/fixtures/destructuring/array/actual.js create mode 100644 test/fixtures/destructuring/array/expected.js create mode 100644 test/fixtures/destructuring/mixed/actual.js create mode 100644 test/fixtures/destructuring/mixed/expected.js create mode 100644 test/fixtures/destructuring/multiple/actual.js create mode 100644 test/fixtures/destructuring/multiple/expected.js create mode 100644 test/fixtures/destructuring/object-advanced/actual.js create mode 100644 test/fixtures/destructuring/object-advanced/expected.js create mode 100644 test/fixtures/destructuring/object-basic/actual.js create mode 100644 test/fixtures/destructuring/object-basic/expected.js diff --git a/FEATURES.md b/FEATURES.md index d012284d20..fdcc27fdad 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -98,7 +98,7 @@ console.log(`${x} + ${y} = ${x + y}`); // "5 + 10 = 15" 0o767 === 503; // true ``` -## Iterators +## For Of ```javascript ``` @@ -134,7 +134,7 @@ function f(x, y) { [for (i of [1, 2, 3]) i * i]; // [1, 4, 9] ``` -## Destructuring assignment +## Destructuring ```javascript var [a, [b], c, d] = ["hello", [", ", "junk"], ["world"]]; diff --git a/README.md b/README.md index 6c895ce29f..41c92a1aa0 100644 --- a/README.md +++ b/README.md @@ -45,9 +45,9 @@ | [Computed property names](FEATURES.md#computed-property-names) | ✓ | | | [Constants](FEATURES.md#constants) | ✓ | | | [Binary and Octal Literals](FEATURES.md#binary-and-octal-literals) | ✓ | | -| [Iterators](FEATURES.md#iterators) | ✓ | ✓ | +| [For of](FEATURES.md#for-of) | ✓ | ✓ | | [Array comprehension](FEATURES.md#array-comprehension) | ✓ | | -| [Destructuring assignment](FEATURES.md#destructuring-assignment) | | | +| [Destructuring](FEATURES.md#destructuring) | ✓ | | | [Generators](FEATURES.md#generators) | | | ## Installation diff --git a/lib/6to5/templates/variable-assign.js b/lib/6to5/templates/variable-assign.js new file mode 100644 index 0000000000..28f15a6d0c --- /dev/null +++ b/lib/6to5/templates/variable-assign.js @@ -0,0 +1 @@ +var KEY = VALUE; diff --git a/lib/6to5/transformers/destructuring-assignment.js b/lib/6to5/transformers/destructuring-assignment.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/6to5/transformers/destructuring.js b/lib/6to5/transformers/destructuring.js new file mode 100644 index 0000000000..db58ddb879 --- /dev/null +++ b/lib/6to5/transformers/destructuring.js @@ -0,0 +1,112 @@ +var util = require("../util"); +var _ = require("lodash"); + +var isPattern = function (id) { + return id.type === "ArrayPattern" || id.type === "ObjectPattern"; +}; + +exports.VariableDeclaration = function (node, parent, opts, generateUid) { + var nodes = []; + + var hasPattern = false; + _.each(node.declarations, function (declar) { + if (isPattern(declar.id)) { + hasPattern = true; + return false; + } + }); + if (!hasPattern) return; + + // + + var buildVariableAssign = function (id, init) { + return { + type: "VariableDeclaration", + kind: node.kind, + declarations: [{ + type: "VariableDeclarator", + id: id, + init: init + }] + }; + }; + + var push = function (pattern, parentId) { + if (pattern.type === "ObjectPattern") { + pushObjectPattern(pattern, parentId); + } else if (pattern.type === "ArrayPattern") { + pushArrayPattern(pattern, parentId); + } + }; + + var pushObjectPattern = function (pattern, parentId) { + _.each(pattern.properties, function (prop) { + var id = prop.value; + + var init = { + type: "MemberExpression", + object: parentId, + property: prop.key + }; + + if (isPattern(id)) { + push(id, init); + } else { + nodes.push(buildVariableAssign(id, init)); + } + }); + }; + + var pushArrayPattern = function (pattern, parentId) { + _.each(pattern.elements, function (id, i) { + var init = { + type: "MemberExpression", + computed: true, + object: parentId, + property: { + type: "Literal", + value: i + } + }; + + if (id.type === "Identifier") { + nodes.push(buildVariableAssign(id, init)); + } else { + push(id, init); + } + }); + }; + + var pushPattern = function (id, init) { + if (init.type !== "MemberExpression" && init.type !== "Identifier") { + var key = generateUid("ref"); + + nodes.push(util.template("variable-assign", { + KEY: key, + VALUE: init + }, true)); + + init = { + type: "Identifier", + name: key + }; + } + + push(id, init); + }; + + // + + _.each(node.declarations, function (declar) { + var init = declar.init; + var id = declar.id; + + if (isPattern(id)) { + pushPattern(id, init); + } else { + nodes.push(buildVariableAssign(id, init)); + } + }); + + return nodes; +}; diff --git a/test/fixtures/destructuring/array/actual.js b/test/fixtures/destructuring/array/actual.js new file mode 100644 index 0000000000..10aa8799ed --- /dev/null +++ b/test/fixtures/destructuring/array/actual.js @@ -0,0 +1 @@ +var [a, [b], [c], d] = ["hello", [", ", "junk"], ["world"]]; diff --git a/test/fixtures/destructuring/array/expected.js b/test/fixtures/destructuring/array/expected.js new file mode 100644 index 0000000000..fd4e31e621 --- /dev/null +++ b/test/fixtures/destructuring/array/expected.js @@ -0,0 +1,5 @@ +var _ref = ["hello", [", ", "junk"], ["world"]]; +var a = _ref[0]; +var b = _ref[1][0]; +var c = _ref[2][0]; +var d = _ref[3]; diff --git a/test/fixtures/destructuring/mixed/actual.js b/test/fixtures/destructuring/mixed/actual.js new file mode 100644 index 0000000000..79ac2cb22f --- /dev/null +++ b/test/fixtures/destructuring/mixed/actual.js @@ -0,0 +1 @@ +var {topLeft: [x1, y1], bottomRight: [x2, y2] } = rect; diff --git a/test/fixtures/destructuring/mixed/expected.js b/test/fixtures/destructuring/mixed/expected.js new file mode 100644 index 0000000000..e5f59c7965 --- /dev/null +++ b/test/fixtures/destructuring/mixed/expected.js @@ -0,0 +1,4 @@ +var x1 = rect.topLeft[0]; +var y1 = rect.topLeft[1]; +var x2 = rect.bottomRight[0]; +var y2 = rect.bottomRight[1]; diff --git a/test/fixtures/destructuring/multiple/actual.js b/test/fixtures/destructuring/multiple/actual.js new file mode 100644 index 0000000000..41dc62261f --- /dev/null +++ b/test/fixtures/destructuring/multiple/actual.js @@ -0,0 +1 @@ +var { x, y } = coords, foo = "bar"; diff --git a/test/fixtures/destructuring/multiple/expected.js b/test/fixtures/destructuring/multiple/expected.js new file mode 100644 index 0000000000..0dcad7cc0f --- /dev/null +++ b/test/fixtures/destructuring/multiple/expected.js @@ -0,0 +1,3 @@ +var x = coords.x; +var y = coords.y; +var foo = "bar"; diff --git a/test/fixtures/destructuring/object-advanced/actual.js b/test/fixtures/destructuring/object-advanced/actual.js new file mode 100644 index 0000000000..c4b85492cf --- /dev/null +++ b/test/fixtures/destructuring/object-advanced/actual.js @@ -0,0 +1 @@ +var {topLeft: {x: x1, y: y1}, bottomRight: {x: x2, y: y2}} = rect; diff --git a/test/fixtures/destructuring/object-advanced/expected.js b/test/fixtures/destructuring/object-advanced/expected.js new file mode 100644 index 0000000000..ed6a605810 --- /dev/null +++ b/test/fixtures/destructuring/object-advanced/expected.js @@ -0,0 +1,4 @@ +var x1 = rect.topLeft.x; +var y1 = rect.topLeft.y; +var x2 = rect.bottomRight.x; +var y2 = rect.bottomRight.y; diff --git a/test/fixtures/destructuring/object-basic/actual.js b/test/fixtures/destructuring/object-basic/actual.js new file mode 100644 index 0000000000..dae014575e --- /dev/null +++ b/test/fixtures/destructuring/object-basic/actual.js @@ -0,0 +1 @@ +var { x, y } = coords; diff --git a/test/fixtures/destructuring/object-basic/expected.js b/test/fixtures/destructuring/object-basic/expected.js new file mode 100644 index 0000000000..5ee3fb667e --- /dev/null +++ b/test/fixtures/destructuring/object-basic/expected.js @@ -0,0 +1,2 @@ +var x = coords.x; +var y = coords.y;