Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9e4b5fa4a | ||
|
|
7ca5f2d8a0 | ||
|
|
555877b438 | ||
|
|
afcf3afea1 |
@@ -628,22 +628,35 @@ describe("results of methods on an escaped receiver", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps a shared result uncertain across a wide escaped receiver (#1495)", () => {
|
it("expands a receiver's methods once rather than once per call (#1495)", () => {
|
||||||
const count = 2000;
|
const receiverCalls = (count: number) => {
|
||||||
const methods = Array.from(
|
const methods = Array.from(
|
||||||
{ length: count },
|
{ length: count },
|
||||||
(_, index) => `m${index}() { return shared; },`,
|
(_, index) => `m${index}() { return shared; },`,
|
||||||
).join(" ");
|
).join(" ");
|
||||||
const calls = Array.from(
|
const calls = Array.from(
|
||||||
{ length: count },
|
{ length: count },
|
||||||
(_, index) => `box.m${index}().p${index} = ${index};`,
|
(_, index) => `box.m${index}().p${index} = ${index};`,
|
||||||
).join(" ");
|
).join(" ");
|
||||||
const value = resultValue(
|
return `const shared = { token: "TOKEN" }; const box = { ${methods} }; ${calls} return [shared.token];`;
|
||||||
`const shared = { token: "TOKEN" }; const box = { ${methods} }; ${calls} return [shared.token];`,
|
};
|
||||||
);
|
const fastest = (body: string) =>
|
||||||
expect(value).toMatchObject({
|
Math.min(
|
||||||
|
...[0, 1].map(() => {
|
||||||
|
const start = performance.now();
|
||||||
|
resultValue(body);
|
||||||
|
return performance.now() - start;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
resultValue(receiverCalls(100));
|
||||||
|
// Compare growth rather than wall time, which depends on the runner and on
|
||||||
|
// coverage instrumentation. Four times the calls costs about 5-6x here;
|
||||||
|
// re-expanding every method per call cost about 13-14x.
|
||||||
|
const ratio = fastest(receiverCalls(1600)) / fastest(receiverCalls(400));
|
||||||
|
expect(ratio).toBeLessThan(10);
|
||||||
|
expect(resultValue(receiverCalls(400))).toMatchObject({
|
||||||
status: "array",
|
status: "array",
|
||||||
items: [{ value: { status: "unknown" } }],
|
items: [{ value: { status: "unknown" } }],
|
||||||
});
|
});
|
||||||
}, 30000);
|
}, 60000);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -47,10 +47,6 @@ const writes = {
|
|||||||
constructor:
|
constructor:
|
||||||
"function Box() { return shared; } const t = new Box(); t.x = 2;",
|
"function Box() { return shared; } const t = new Box(); t.x = 2;",
|
||||||
callback: "const get = () => shared; [0].forEach(() => { get().x = 2; });",
|
callback: "const get = () => shared; [0].forEach(() => { get().x = 2; });",
|
||||||
wideMethods: `const box = { ${Array.from(
|
|
||||||
{ length: 64 },
|
|
||||||
(_, index) => `m${index}() { return shared; }`,
|
|
||||||
).join(", ")} }; box.m0().x = 2; box.m63().other = 3;`,
|
|
||||||
};
|
};
|
||||||
const source = [
|
const source = [
|
||||||
...Object.entries(writes).map(
|
...Object.entries(writes).map(
|
||||||
@@ -65,8 +61,6 @@ const source = [
|
|||||||
"export function unused(){ const shared = {x: 1}; const get = () => shared; get(); return shared.x; }",
|
"export function unused(){ const shared = {x: 1}; const get = () => shared; get(); return shared.x; }",
|
||||||
"export function nestedCallable(){ const shared = {x: 1}; const get = () => { const inner = () => shared; return {x: 0}; }; get().x = 2; return shared.x; }",
|
"export function nestedCallable(){ const shared = {x: 1}; const get = () => { const inner = () => shared; return {x: 0}; }; get().x = 2; return shared.x; }",
|
||||||
"export function unrelated(){ const shared = {x: 1}; const other = {x: 9}; const get = () => shared; get().x = 2; return other.x; }",
|
"export function unrelated(){ const shared = {x: 1}; const other = {x: 9}; const get = () => shared; get().x = 2; return other.x; }",
|
||||||
"export function receiverDistinctScopes(){ const shared = {x: 1}; const box = {outer(){ return shared; }, inner(){ const shared = {x: 9}; return shared; }, noop(){}}; box.noop(); return {outer: shared.x, inner: box.inner().x}; }",
|
|
||||||
"export function receiverDistinctPaths(){ const parent = {left: {x: 1}, right: {x: 9}, keep: 7}; const box = {left(){ return parent.left; }, right(){ return parent.right; }, noop(){}}; box.noop(); return {left: parent.left.x, right: parent.right.x, keep: parent.keep}; }",
|
|
||||||
].join("\n");
|
].join("\n");
|
||||||
|
|
||||||
const assertReturns = (fields: JavaScriptReturnFields): void => {
|
const assertReturns = (fields: JavaScriptReturnFields): void => {
|
||||||
@@ -97,17 +91,6 @@ const assertReturns = (fields: JavaScriptReturnFields): void => {
|
|||||||
expect(fields("unrelated")).toContainEqual(
|
expect(fields("unrelated")).toContainEqual(
|
||||||
expect.objectContaining({ path: "", state: "literal", value: 9 }),
|
expect.objectContaining({ path: "", state: "literal", value: 9 }),
|
||||||
);
|
);
|
||||||
for (const path of ["/outer", "/inner"])
|
|
||||||
expect(fields("receiverDistinctScopes")).toContainEqual(
|
|
||||||
expect.objectContaining({ path, state: "unknown" }),
|
|
||||||
);
|
|
||||||
for (const path of ["/left", "/right"])
|
|
||||||
expect(fields("receiverDistinctPaths")).toContainEqual(
|
|
||||||
expect.objectContaining({ path, state: "unknown" }),
|
|
||||||
);
|
|
||||||
expect(fields("receiverDistinctPaths")).toContainEqual(
|
|
||||||
expect.objectContaining({ path: "/keep", state: "literal", value: 7 }),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
cliTest(
|
cliTest(
|
||||||
|
|||||||
Reference in New Issue
Block a user