Skip to content

Commit

Permalink
optimās: respect noDocumentAll when transforming obj?.#p (babel#12762)
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung authored and nicolo-ribaudo committed Feb 11, 2021
1 parent e148e0e commit 3630b02
Show file tree
Hide file tree
Showing 12 changed files with 659 additions and 42 deletions.
Expand Up @@ -130,7 +130,7 @@ function privateNameVisitorFactory(visitor) {
}

const privateNameVisitor = privateNameVisitorFactory({
PrivateName(path) {
PrivateName(path, { noDocumentAll }) {
const { privateNamesMap, redeclared } = this;
const { node, parentPath } = path;

Expand All @@ -144,7 +144,7 @@ const privateNameVisitor = privateNameVisitorFactory({
if (!privateNamesMap.has(name)) return;
if (redeclared && redeclared.includes(name)) return;

this.handle(parentPath);
this.handle(parentPath, noDocumentAll);
},
});

Expand Down Expand Up @@ -376,7 +376,7 @@ export function transformPrivateNamesUsage(
ref,
path,
privateNamesMap,
{ privateFieldsAsProperties },
{ privateFieldsAsProperties, noDocumentAll },
state,
) {
if (!privateNamesMap.size) return;
Expand All @@ -391,6 +391,7 @@ export function transformPrivateNamesUsage(
classRef: ref,
file: state,
...handler,
noDocumentAll,
});
body.traverse(privateInVisitor, {
privateNamesMap,
Expand Down
Expand Up @@ -41,6 +41,7 @@ export function createClassFeaturePlugin({
}) {
const setPublicClassFields = api.assumption("setPublicClassFields");
const privateFieldsAsProperties = api.assumption("privateFieldsAsProperties");
const noDocumentAll = api.assumption("noDocumentAll");

if (loose) {
const explicit = [];
Expand Down Expand Up @@ -189,7 +190,10 @@ export function createClassFeaturePlugin({
ref,
path,
privateNamesMap,
{ privateFieldsAsProperties: privateFieldsAsProperties ?? loose },
{
privateFieldsAsProperties: privateFieldsAsProperties ?? loose,
noDocumentAll,
},
state,
);

Expand Down
82 changes: 44 additions & 38 deletions packages/babel-helper-member-expression-to-functions/src/index.js
Expand Up @@ -84,7 +84,7 @@ const handle = {
// noop.
},

handle(member) {
handle(member: t.NodePath<t.Expression>, noDocumentAll: boolean) {
const { node, parent, parentPath, scope } = member;

if (member.isOptionalMemberExpression()) {
Expand Down Expand Up @@ -241,50 +241,56 @@ const handle = {
regular = endParentPath.node;
}

const baseMemoised = baseNeedsMemoised
? t.assignmentExpression(
"=",
t.cloneNode(baseRef),
t.cloneNode(startingNode),
)
: t.cloneNode(baseRef);

if (willEndPathCastToBoolean) {
const nonNullishCheck = t.logicalExpression(
"&&",
t.binaryExpression(
"!==",
baseNeedsMemoised
? t.assignmentExpression(
"=",
t.cloneNode(baseRef),
t.cloneNode(startingNode),
)
: t.cloneNode(baseRef),
let nonNullishCheck;
if (noDocumentAll) {
nonNullishCheck = t.binaryExpression(
"!=",
baseMemoised,
t.nullLiteral(),
),
t.binaryExpression(
"!==",
t.cloneNode(baseRef),
scope.buildUndefinedNode(),
),
);
);
} else {
nonNullishCheck = t.logicalExpression(
"&&",
t.binaryExpression("!==", baseMemoised, t.nullLiteral()),
t.binaryExpression(
"!==",
t.cloneNode(baseRef),
scope.buildUndefinedNode(),
),
);
}
replacementPath.replaceWith(
t.logicalExpression("&&", nonNullishCheck, regular),
);
} else {
// todo: respect assumptions.noDocumentAll when assumptions are implemented
const nullishCheck = t.logicalExpression(
"||",
t.binaryExpression(
"===",
baseNeedsMemoised
? t.assignmentExpression(
"=",
t.cloneNode(baseRef),
t.cloneNode(startingNode),
)
: t.cloneNode(baseRef),
let nullishCheck;
if (noDocumentAll) {
nullishCheck = t.binaryExpression(
"==",
baseMemoised,
t.nullLiteral(),
),
t.binaryExpression(
"===",
t.cloneNode(baseRef),
scope.buildUndefinedNode(),
),
);
);
} else {
nullishCheck = t.logicalExpression(
"||",
t.binaryExpression("===", baseMemoised, t.nullLiteral()),
t.binaryExpression(
"===",
t.cloneNode(baseRef),
scope.buildUndefinedNode(),
),
);
}

replacementPath.replaceWith(
t.conditionalExpression(
nullishCheck,
Expand Down
@@ -0,0 +1,122 @@
class Foo {
static #x = 1;
static #m = function() { return this.#x; };
static #self = Foo;
static self = Foo;
static getSelf() { return this }

static test() {
const o = { Foo: Foo };
const deep = { very: { o } };
function fn() {
return o;
}
function fnDeep() {
return deep;
}

expect(o?.Foo.#m()).toEqual(1);
expect(o?.Foo.#m().toString).toEqual(1..toString);
expect(o?.Foo.#m().toString()).toEqual('1');

expect(deep?.very.o?.Foo.#m()).toEqual(1);
expect(deep?.very.o?.Foo.#m().toString).toEqual(1..toString);
expect(deep?.very.o?.Foo.#m().toString()).toEqual('1');

expect(o?.Foo.#self.#m()).toEqual(1);
expect(o?.Foo.#self.self.#m()).toEqual(1);
expect(o?.Foo.#self?.self.#m()).toEqual(1);
expect(o?.Foo.#self.self?.self.#m()).toEqual(1);
expect(o?.Foo.#self?.self?.self.#m()).toEqual(1);

expect(o?.Foo.#self.getSelf().#m()).toEqual(1);
expect(o?.Foo.#self.getSelf?.().#m()).toEqual(1);
expect(o?.Foo.#self?.getSelf().#m()).toEqual(1);
expect(o?.Foo.#self?.getSelf?.().#m()).toEqual(1);
expect(o?.Foo.#self.getSelf()?.self.#m()).toEqual(1);
expect(o?.Foo.#self.getSelf?.()?.self.#m()).toEqual(1);
expect(o?.Foo.#self?.getSelf()?.self.#m()).toEqual(1);
expect(o?.Foo.#self?.getSelf?.()?.self.#m()).toEqual(1);

expect(fn?.().Foo.#m()).toEqual(1);
expect(fn?.().Foo.#m().toString).toEqual(1..toString);
expect(fn?.().Foo.#m().toString()).toEqual('1');

expect(fnDeep?.().very.o?.Foo.#m()).toEqual(1);
expect(fnDeep?.().very.o?.Foo.#m().toString).toEqual(1..toString);
expect(fnDeep?.().very.o?.Foo.#m().toString()).toEqual('1');

expect(fn?.().Foo.#self.#m()).toEqual(1);
expect(fn?.().Foo.#self.self.#m()).toEqual(1);
expect(fn?.().Foo.#self?.self.#m()).toEqual(1);
expect(fn?.().Foo.#self.self?.self.#m()).toEqual(1);
expect(fn?.().Foo.#self?.self?.self.#m()).toEqual(1);

expect(fn?.().Foo.#self.getSelf().#m()).toEqual(1);
expect(fn?.().Foo.#self.getSelf?.().#m()).toEqual(1);
expect(fn?.().Foo.#self?.getSelf().#m()).toEqual(1);
expect(fn?.().Foo.#self?.getSelf?.().#m()).toEqual(1);
expect(fn?.().Foo.#self.getSelf()?.self.#m()).toEqual(1);
expect(fn?.().Foo.#self.getSelf?.()?.self.#m()).toEqual(1);
expect(fn?.().Foo.#self?.getSelf()?.self.#m()).toEqual(1);
expect(fn?.().Foo.#self?.getSelf?.()?.self.#m()).toEqual(1);
}

static testNull() {
const o = null;;
const deep = { very: { o } };
const fn = null;
function fnDeep() {
return deep;
}

expect(o?.Foo.#m()).toEqual(undefined);
expect(o?.Foo.#m().toString).toEqual(undefined);
expect(o?.Foo.#m().toString()).toEqual(undefined);

expect(deep?.very.o?.Foo.#m()).toEqual(undefined);
expect(deep?.very.o?.Foo.#m().toString).toEqual(undefined);
expect(deep?.very.o?.Foo.#m().toString()).toEqual(undefined);

expect(o?.Foo.#self.#m()).toEqual(undefined);
expect(o?.Foo.#self.self.#m()).toEqual(undefined);
expect(o?.Foo.#self?.self.#m()).toEqual(undefined);
expect(o?.Foo.#self.self?.self.#m()).toEqual(undefined);
expect(o?.Foo.#self?.self?.self.#m()).toEqual(undefined);

expect(o?.Foo.#self.getSelf().#m()).toEqual(undefined);
expect(o?.Foo.#self.getSelf?.().#m()).toEqual(undefined);
expect(o?.Foo.#self?.getSelf().#m()).toEqual(undefined);
expect(o?.Foo.#self?.getSelf?.().#m()).toEqual(undefined);
expect(o?.Foo.#self.getSelf()?.self.#m()).toEqual(undefined);
expect(o?.Foo.#self.getSelf?.()?.self.#m()).toEqual(undefined);
expect(o?.Foo.#self?.getSelf()?.self.#m()).toEqual(undefined);
expect(o?.Foo.#self?.getSelf?.()?.self.#m()).toEqual(undefined);

expect(fn?.().Foo.#m()).toEqual(undefined);
expect(fn?.().Foo.#m().toString).toEqual(undefined);
expect(fn?.().Foo.#m().toString()).toEqual(undefined);

expect(fnDeep?.().very.o?.Foo.#m()).toEqual(undefined);
expect(fnDeep?.().very.o?.Foo.#m().toString).toEqual(undefined);
expect(fnDeep?.().very.o?.Foo.#m().toString()).toEqual(undefined);

expect(fn?.().Foo.#self.#m()).toEqual(undefined);
expect(fn?.().Foo.#self.self.#m()).toEqual(undefined);
expect(fn?.().Foo.#self?.self.#m()).toEqual(undefined);
expect(fn?.().Foo.#self.self?.self.#m()).toEqual(undefined);
expect(fn?.().Foo.#self?.self?.self.#m()).toEqual(undefined);

expect(fn?.().Foo.#self.getSelf().#m()).toEqual(undefined);
expect(fn?.().Foo.#self.getSelf?.().#m()).toEqual(undefined);
expect(fn?.().Foo.#self?.getSelf().#m()).toEqual(undefined);
expect(fn?.().Foo.#self?.getSelf?.().#m()).toEqual(undefined);
expect(fn?.().Foo.#self.getSelf()?.self.#m()).toEqual(undefined);
expect(fn?.().Foo.#self.getSelf?.()?.self.#m()).toEqual(undefined);
expect(fn?.().Foo.#self?.getSelf()?.self.#m()).toEqual(undefined);
expect(fn?.().Foo.#self?.getSelf?.()?.self.#m()).toEqual(undefined);
}
}

Foo.test();
Foo.testNull();
@@ -0,0 +1,66 @@
class Foo {
static #x = 1;
static #m = function() { return this.#x; };
static #self = Foo;
static self = Foo;
static getSelf() { return this }

static test() {
const o = { Foo: Foo };
const deep = { very: { o } };
function fn() {
return o;
}
function fnDeep() {
return deep;
}

o?.Foo.#m();
o?.Foo.#m().toString;
o?.Foo.#m().toString();

deep?.very.o?.Foo.#m();
deep?.very.o?.Foo.#m().toString;
deep?.very.o?.Foo.#m().toString();

o?.Foo.#self.#m();
o?.Foo.#self.self.#m();
o?.Foo.#self?.self.#m();
o?.Foo.#self.self?.self.#m();
o?.Foo.#self?.self?.self.#m();

o?.Foo.#self.getSelf().#m();
o?.Foo.#self.getSelf?.().#m();
o?.Foo.#self?.getSelf().#m();
o?.Foo.#self?.getSelf?.().#m();
o?.Foo.#self.getSelf()?.self.#m();
o?.Foo.#self.getSelf?.()?.self.#m();
o?.Foo.#self?.getSelf()?.self.#m();
o?.Foo.#self?.getSelf?.()?.self.#m();

fn?.().Foo.#m();
fn?.().Foo.#m().toString;
fn?.().Foo.#m().toString();

fnDeep?.().very.o?.Foo.#m();
fnDeep?.().very.o?.Foo.#m().toString;
fnDeep?.().very.o?.Foo.#m().toString();

fn?.().Foo.#self.#m();
fn?.().Foo.#self.self.#m();
fn?.().Foo.#self?.self.#m();
fn?.().Foo.#self.self?.self.#m();
fn?.().Foo.#self?.self?.self.#m();

fn?.().Foo.#self.getSelf().#m();
fn?.().Foo.#self.getSelf?.().#m();
fn?.().Foo.#self?.getSelf().#m();
fn?.().Foo.#self?.getSelf?.().#m();
fn?.().Foo.#self.getSelf()?.self.#m();
fn?.().Foo.#self.getSelf?.()?.self.#m();
fn?.().Foo.#self?.getSelf()?.self.#m();
fn?.().Foo.#self?.getSelf?.()?.self.#m();
}
}

Foo.test();
@@ -0,0 +1,4 @@
{
"plugins": ["proposal-class-properties"],
"minNodeVersion": "14.0.0"
}

0 comments on commit 3630b02

Please sign in to comment.