From a7a6ee80f2b21233b305705709ccc4921450749a Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 6 Dec 2014 19:37:23 +1100 Subject: [PATCH] add object getter memoization and this shorthand to playground --- doc/playground.md | 52 ++++++++++++++++++ lib/6to5/transformation/transform.js | 9 ++-- .../playground-object-getter-memoization.js | 37 +++++++++++++ .../object-getter-memoization/actual.js | 19 +++++++ .../object-getter-memoization/expected.js | 53 +++++++++++++++++++ 5 files changed, 166 insertions(+), 4 deletions(-) create mode 100644 lib/6to5/transformation/transformers/playground-object-getter-memoization.js create mode 100644 test/fixtures/transformation/playground/object-getter-memoization/actual.js create mode 100644 test/fixtures/transformation/playground/object-getter-memoization/expected.js diff --git a/doc/playground.md b/doc/playground.md index 99fa85a256..2a7f82e726 100644 --- a/doc/playground.md +++ b/doc/playground.md @@ -18,6 +18,8 @@ to5.transform("code", { playground: true }); * [Memoization operator](#memoization-operator) * [Method binding](#method-binding) + * [Object getter memoisation](#object-getter-memoisation) + * [This shorthand](#this-shorthand) ### Memoization assignment operator @@ -66,3 +68,53 @@ var fn = obj.method.bind(obj, "foob"); ["foo", "bar"].map(function (val) { return val.toUpperCase(); }); [1.1234, 23.53245, 3].map(function (val) { return val.toFixed(2); }); ``` + +### Object getter memoisation + +```javascript +var foo = { + memo bar() { + return complex(); + } +}; + +class Foo { + memo bar() { + return complex(); + } +} +``` + +equivalent to + +```javascript +var foo = { + get bar() { + if (this._barRan) return this._bar; + this._barRan = true; + return this._bar = complex(); + } +}; + +class Foo { + get bar() { + if (this._barRan) return this._bar; + this._barRan = true; + return this._bar = complex(); + } +} +``` + +**NOTE:** Memoised functions will return the result of the **first** execution, regardless of arguments. + +### This shorthand + +```javascript +@foo +``` + +equivalent to + +```javascirpt +this.foo +``` diff --git a/lib/6to5/transformation/transform.js b/lib/6to5/transformation/transform.js index baf69321e1..4824e44548 100644 --- a/lib/6to5/transformation/transform.js +++ b/lib/6to5/transformation/transform.js @@ -29,6 +29,11 @@ transform.moduleFormatters = { }; _.each({ + // plyground + methodBinding: require("./transformers/playground-method-binding"), + memoizationOperator: require("./transformers/playground-memoization-operator"), + objectGetterMemoization: require("./transformers/playground-object-getter-memoization"), + modules: require("./transformers/es6-modules"), propertyNameShorthand: require("./transformers/es6-property-name-shorthand"), arrayComprehension: require("./transformers/es7-array-comprehension"), @@ -56,10 +61,6 @@ _.each({ generators: require("./transformers/es6-generators"), - // plyground - methodBinding: require("./transformers/playground-method-binding"), - memoizationOperator: require("./transformers/playground-memoization-operator"), - _blockHoist: require("./transformers/_block-hoist"), _declarations: require("./transformers/_declarations"), _aliasFunctions: require("./transformers/_alias-functions"), diff --git a/lib/6to5/transformation/transformers/playground-object-getter-memoization.js b/lib/6to5/transformation/transformers/playground-object-getter-memoization.js new file mode 100644 index 0000000000..8c3c835023 --- /dev/null +++ b/lib/6to5/transformation/transformers/playground-object-getter-memoization.js @@ -0,0 +1,37 @@ +var traverse = require("../../traverse"); +var t = require("../../types"); + +exports.Property = +exports.MethodDefinition = function (node, parent, file, scope) { + if (node.kind !== "memo") return; + node.kind = "get"; + + var value = node.value; + t.ensureBlock(value); + + var body = value.body.body; + var key = node.key; + + if (t.isIdentifier(key) && !node.computed) { + key = "_" + key.name; + } else { + key = file.generateUid("memo", scope); + } + + var memoId = t.memberExpression(t.thisExpression(), t.identifier(key)); + var doneId = t.memberExpression(t.thisExpression(), t.identifier(key + "Done")); + + traverse(value, function (node) { + if (t.isFunction(node)) return; + + if (t.isReturnStatement(node) && node.argument) { + node.argument = t.assignmentExpression("=", memoId, node.argument); + } + }); + + // this._barDone = true; + body.unshift(t.expressionStatement(t.assignmentExpression("=", doneId, t.literal(true)))); + + // if (this._barDone) return this._bar; + body.unshift(t.ifStatement(doneId, t.returnStatement(memoId))); +}; diff --git a/test/fixtures/transformation/playground/object-getter-memoization/actual.js b/test/fixtures/transformation/playground/object-getter-memoization/actual.js new file mode 100644 index 0000000000..9b0d317c04 --- /dev/null +++ b/test/fixtures/transformation/playground/object-getter-memoization/actual.js @@ -0,0 +1,19 @@ +class Foo { + memo bar() { + return complex(); + } + + memo [bar]() { + return complex(); + } +} + +var foo = { + memo bar() { + return complex(); + }, + + memo [bar]() { + return complex(); + } +}; diff --git a/test/fixtures/transformation/playground/object-getter-memoization/expected.js b/test/fixtures/transformation/playground/object-getter-memoization/expected.js new file mode 100644 index 0000000000..83441a35f4 --- /dev/null +++ b/test/fixtures/transformation/playground/object-getter-memoization/expected.js @@ -0,0 +1,53 @@ +"use strict"; + +var _classProps = function (child, staticProps, instanceProps) { + if (staticProps) Object.defineProperties(child, staticProps); + if (instanceProps) Object.defineProperties(child.prototype, instanceProps); +}; + +var Foo = (function () { + var Foo = function Foo() {}; + + _classProps(Foo, null, (function (_ref) { + _ref[bar] = { + get: function () { + if (this._memoDone) return this._memo; + this._memoDone = true; + return this._memo = complex(); + } + }; + return _ref; + })({ + bar: { + get: function () { + if (this._barDone) return this._bar; + this._barDone = true; + return this._bar = complex(); + } + } + })); + + return Foo; +})(); + +var foo = (function (_foo) { + _foo[bar] = function () { + if (this._memo2Done) return this._memo2; + this._memo2Done = true; + return this._memo2 = complex(); + }; + + return _foo; +})((function (_ref2) { + Object.defineProperties(_ref2, { + bar: { + get: function () { + if (this._barDone) return this._bar; + this._barDone = true; + return this._bar = complex(); + } + } + }); + + return _ref2; +})({}));