Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(helpers): match Reflect.get behaviour #13862

Merged
merged 2 commits into from Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 8 additions & 3 deletions packages/babel-helpers/src/helpers.ts
Expand Up @@ -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 {
Expand All @@ -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);
}
`;

Expand Down
@@ -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");
@@ -0,0 +1,3 @@
{
"plugins": ["./plugin"]
}
@@ -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);
}
},
},
};
};
@@ -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);
@@ -0,0 +1,3 @@
{
"plugins": ["./plugin"]
}
@@ -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);
}
},
},
};
};