Skip to content

Commit

Permalink
Optimize computed properties output (byte-wise)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist authored and nicolo-ribaudo committed Aug 28, 2023
1 parent b804bb0 commit 18c83f2
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 33 deletions.
54 changes: 35 additions & 19 deletions packages/babel-plugin-transform-computed-properties/src/index.ts
Expand Up @@ -157,36 +157,52 @@ export default declare((api, options: Options) => {
function pushComputedPropsSpec(info: PropertyInfo) {
const { objId, body, computedProps, state } = info;

for (const prop of computedProps) {
// PrivateName must not be in ObjectExpression
const key = t.toComputedKey(prop) as t.Expression;
// To prevent too deep AST structures in case of large objects
const CHUNK_LENGTH_CAP = 10;

let currentChunk: t.ObjectMember[] = null;
const computedPropsChunks: Array<
| { accessor: true; chunk: t.ObjectMethod }
| { accessor: false; chunk: t.ObjectMember[] }
> = [];
for (const prop of computedProps) {
if (
t.isObjectMethod(prop) &&
(prop.kind === "get" || prop.kind === "set")
) {
const single = pushAccessorDefine(info, prop);
currentChunk = null;
computedPropsChunks.push({ accessor: true, chunk: prop });
} else {
if (!currentChunk || currentChunk.length === CHUNK_LENGTH_CAP) {
currentChunk = [];
computedPropsChunks.push({ accessor: false, chunk: currentChunk });
}
currentChunk.push(prop);
}
}

for (const { accessor, chunk } of computedPropsChunks) {
if (accessor) {
const single = pushAccessorDefine(info, chunk);
if (single) return single;
} else {
// the value of ObjectProperty in ObjectExpression must be an expression
const value = getValue(prop);
if (computedProps.length === 1) {
return t.callExpression(state.addHelper("defineProperty"), [
info.initPropExpression,
const single = computedPropsChunks.length === 1;
let node: t.Expression = single
? info.initPropExpression
: t.cloneNode(objId);
for (const prop of chunk) {
// PrivateName must not be in ObjectExpression
const key = t.toComputedKey(prop) as t.Expression;
// the value of ObjectProperty in ObjectExpression must be an expression
const value = getValue(prop);
node = t.callExpression(state.addHelper("defineProperty"), [
t.cloneNode(node),
key,
value,
]);
} else {
body.push(
t.expressionStatement(
t.callExpression(state.addHelper("defineProperty"), [
t.cloneNode(objId),
key,
value,
]),
),
);
}
if (single) return node;
body.push(t.expressionStatement(node));
}
}
}
Expand Down
@@ -1,2 +1 @@
var _a$c;
export default (_a$c = {}, babelHelpers.defineProperty(_a$c, a, b), babelHelpers.defineProperty(_a$c, c, d), _a$c);
export default babelHelpers.defineProperty(babelHelpers.defineProperty({}, a, b), c, d);
@@ -1,6 +1,5 @@
var _obj;
var obj = (_obj = {}, babelHelpers.defineProperty(_obj, foobar, function () {
var obj = babelHelpers.defineProperty(babelHelpers.defineProperty({}, foobar, function () {
return "foobar";
}), babelHelpers.defineProperty(_obj, "test", function () {
}), "test", function () {
return "regular method after computed property";
}), _obj);
});
@@ -0,0 +1,18 @@
var heh = "heh";
var noo = "noo";
var foo = "foo";

var obj = {
["x" + heh]: "heh",
["y" + noo]: "noo",
[foo]: "foo1",
foo: "foo2",
bar: "bar",
};

expect(obj).toEqual({
xheh: "heh",
ynoo: "noo",
foo: "foo2",
bar: "bar",
});
@@ -1,6 +1,11 @@
var heh = "heh";
var noo = "noo";
var foo = "foo";

var obj = {
["x" + foo]: "heh",
["y" + bar]: "noo",
foo: "foo",
bar: "bar"
["x" + heh]: "heh",
["y" + noo]: "noo",
[foo]: "foo1",
foo: "foo2",
bar: "bar",
};
@@ -1,2 +1,4 @@
var _obj;
var obj = (_obj = {}, babelHelpers.defineProperty(_obj, "x" + foo, "heh"), babelHelpers.defineProperty(_obj, "y" + bar, "noo"), babelHelpers.defineProperty(_obj, "foo", "foo"), babelHelpers.defineProperty(_obj, "bar", "bar"), _obj);
var heh = "heh";
var noo = "noo";
var foo = "foo";
var obj = babelHelpers.defineProperty(babelHelpers.defineProperty(babelHelpers.defineProperty(babelHelpers.defineProperty(babelHelpers.defineProperty({}, "x" + heh, "heh"), "y" + noo, "noo"), foo, "foo1"), "foo", "foo2"), "bar", "bar");
@@ -0,0 +1,31 @@
var manyProps = {
[0 + 1]: 1,
[0 + 2]: 2,
[0 + 3]: 3,
[0 + 4]: 4,
[0 + 5]: 5,
[0 + 6]: 6,
[0 + 7]: 7,
[0 + 8]: 8,
[0 + 9]: 9,
[0 + 10]: 10,
[0 + 11]: 11,
[0 + 12]: 12,
[0 + 13]: 13,
};

expect(manyProps).toEqual({
1: 1,
2: 2,
3: 3,
4: 4,
5: 5,
6: 6,
7: 7,
8: 8,
9: 9,
10: 10,
11: 11,
12: 12,
13: 13,
});
Expand Up @@ -2,3 +2,20 @@ var obj = {
["x" + foo]: "heh",
["y" + bar]: "noo"
};


var manyProps = {
[0 + 1]: 1,
[0 + 2]: 2,
[0 + 3]: 3,
[0 + 4]: 4,
[0 + 5]: 5,
[0 + 6]: 6,
[0 + 7]: 7,
[0 + 8]: 8,
[0 + 9]: 9,
[0 + 10]: 10,
[0 + 11]: 11,
[0 + 12]: 12,
[0 + 13]: 13,
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 18c83f2

Please sign in to comment.