diff --git a/packages/babel-helpers/src/helpers.ts b/packages/babel-helpers/src/helpers.ts index 1e95f57b0b1d..729deaea9d67 100644 --- a/packages/babel-helpers/src/helpers.ts +++ b/packages/babel-helpers/src/helpers.ts @@ -651,10 +651,14 @@ helpers.superPropBase = helper("7.0.0-beta.0")` } `; +// https://tc39.es/ecma262/multipage/reflection.html#sec-reflect.get +// +// 28.1.5 Reflect.get ( target, propertyKey [ , receiver ] ) +// helpers.get = helper("7.0.0-beta.0")` import superPropBase from "superPropBase"; - export default function _get(target, property, receiver) { + export default function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { @@ -665,13 +669,14 @@ helpers.get = helper("7.0.0-beta.0")` var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { - return desc.get.call(receiver); + // STEP 3. If receiver is not present, then set receiver to target. + return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } - return _get(target, property, receiver || target); + return _get.apply(this, arguments); } `; diff --git a/packages/babel-helpers/test/fixtures/behavior/get-with-falsy-receiver/exec.js b/packages/babel-helpers/test/fixtures/behavior/get-with-falsy-receiver/exec.js new file mode 100644 index 000000000000..7bc638f1c15a --- /dev/null +++ b/packages/babel-helpers/test/fixtures/behavior/get-with-falsy-receiver/exec.js @@ -0,0 +1,23 @@ +// ensure we test the helper implementation, +// not built-in Reflect.get to which it defers +delete Reflect; + +class Target { + get typeOf() { + return this === null ? "null" : typeof this; + } +}; + +// check that the 1st argument (target) *is not* used +// in place of present but undefined 3rd argument (receiver) +expect(HELPER_GET(new Target, "typeOf", undefined)).toBe("undefined"); + +// because the helper replaces itself upon invocation, +// check it again with nullish arguments +expect(HELPER_GET(new Target, "typeOf", undefined)).toBe("undefined"); +expect(HELPER_GET(new Target, "typeOf", null)).toBe("null"); + +// check other falsy types +expect(HELPER_GET(new Target, "typeOf", false)).toBe("boolean"); +expect(HELPER_GET(new Target, "typeOf", 0)).toBe("number"); +expect(HELPER_GET(new Target, "typeOf", "")).toBe("string"); diff --git a/packages/babel-helpers/test/fixtures/behavior/get-with-falsy-receiver/options.json b/packages/babel-helpers/test/fixtures/behavior/get-with-falsy-receiver/options.json new file mode 100644 index 000000000000..14af0e5feac8 --- /dev/null +++ b/packages/babel-helpers/test/fixtures/behavior/get-with-falsy-receiver/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["./plugin"] +} diff --git a/packages/babel-helpers/test/fixtures/behavior/get-with-falsy-receiver/plugin.js b/packages/babel-helpers/test/fixtures/behavior/get-with-falsy-receiver/plugin.js new file mode 100644 index 000000000000..f9d875c6e8ae --- /dev/null +++ b/packages/babel-helpers/test/fixtures/behavior/get-with-falsy-receiver/plugin.js @@ -0,0 +1,12 @@ +module.exports = function() { + return { + visitor: { + Identifier(path) { + if (path.node.name === "HELPER_GET") { + const helper = this.addHelper("get"); + path.replaceWith(helper); + } + }, + }, + }; +}; diff --git a/packages/babel-helpers/test/fixtures/behavior/get-without-receiver/exec.js b/packages/babel-helpers/test/fixtures/behavior/get-without-receiver/exec.js new file mode 100644 index 000000000000..24f7a790dd6f --- /dev/null +++ b/packages/babel-helpers/test/fixtures/behavior/get-without-receiver/exec.js @@ -0,0 +1,17 @@ +// ensure we test the helper implementation, +// not built-in Reflect.get to which it defers +delete Reflect; + +class Target { + get receiver() { + return this; + } +}; + +// check that the 1st argument (target) *is* used +// in place of missing 3rd argument (receiver) +expect(HELPER_GET(new Target, "receiver")).toBeInstanceOf(Target); + +// because the helper replaces itself upon invocation, +// check it again with the same arguments +expect(HELPER_GET(new Target, "receiver")).toBeInstanceOf(Target); diff --git a/packages/babel-helpers/test/fixtures/behavior/get-without-receiver/options.json b/packages/babel-helpers/test/fixtures/behavior/get-without-receiver/options.json new file mode 100644 index 000000000000..14af0e5feac8 --- /dev/null +++ b/packages/babel-helpers/test/fixtures/behavior/get-without-receiver/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["./plugin"] +} diff --git a/packages/babel-helpers/test/fixtures/behavior/get-without-receiver/plugin.js b/packages/babel-helpers/test/fixtures/behavior/get-without-receiver/plugin.js new file mode 100644 index 000000000000..f9d875c6e8ae --- /dev/null +++ b/packages/babel-helpers/test/fixtures/behavior/get-without-receiver/plugin.js @@ -0,0 +1,12 @@ +module.exports = function() { + return { + visitor: { + Identifier(path) { + if (path.node.name === "HELPER_GET") { + const helper = this.addHelper("get"); + path.replaceWith(helper); + } + }, + }, + }; +};