mirror of https://github.com/pyodide/pyodide.git
140 lines
4.8 KiB
Diff
140 lines
4.8 KiB
Diff
From b1502949816e4a343b90ca8a6e0411160dbc33ce Mon Sep 17 00:00:00 2001
|
|
From: Alon Zakai <azakai@google.com>
|
|
Date: Thu, 5 Oct 2023 16:29:07 -0700
|
|
Subject: [PATCH] JSDCE: Add support for destructuring declarations (#20402)
|
|
|
|
Rather than let x = 10, these look like let {x: y, ..} = ... or
|
|
let [x, y] = ...
|
|
|
|
Fixes https://github.com/emscripten-core/emscripten/issues/20393
|
|
---
|
|
test/optimizer/JSDCE-objectPattern-output.js | 16 ++++++++++
|
|
test/optimizer/JSDCE-objectPattern.js | 28 +++++++++++++++++
|
|
test/test_other.py | 1 +
|
|
tools/acorn-optimizer.js | 32 ++++++++++++++++++--
|
|
4 files changed, 74 insertions(+), 3 deletions(-)
|
|
create mode 100644 test/optimizer/JSDCE-objectPattern-output.js
|
|
create mode 100644 test/optimizer/JSDCE-objectPattern.js
|
|
|
|
diff --git a/test/optimizer/JSDCE-objectPattern-output.js b/test/optimizer/JSDCE-objectPattern-output.js
|
|
new file mode 100644
|
|
index 000000000..fb6ecf8ad
|
|
--- /dev/null
|
|
+++ b/test/optimizer/JSDCE-objectPattern-output.js
|
|
@@ -0,0 +1,16 @@
|
|
+let d = 40;
|
|
+
|
|
+let z = 50;
|
|
+
|
|
+globalThis.f = function(r) {
|
|
+ let {a: a, b: b} = r;
|
|
+ let {z: c} = r;
|
|
+ return g(a, b, c, d, z);
|
|
+};
|
|
+
|
|
+let d2 = 40;
|
|
+
|
|
+globalThis.f2 = function(r2) {
|
|
+ let [a2, b2, c2] = r2;
|
|
+ return g2(a2, b2, c2, d2);
|
|
+};
|
|
diff --git a/test/optimizer/JSDCE-objectPattern.js b/test/optimizer/JSDCE-objectPattern.js
|
|
new file mode 100644
|
|
index 000000000..61ff37638
|
|
--- /dev/null
|
|
+++ b/test/optimizer/JSDCE-objectPattern.js
|
|
@@ -0,0 +1,28 @@
|
|
+// Of all these, only d must remain: the others are defined in the function, and
|
|
+// used from that scope, not the global scope.
|
|
+let a = 10;
|
|
+let b = 20;
|
|
+let c = 30;
|
|
+let d = 40;
|
|
+
|
|
+// This one must also remain: z in the function is not a local variable, but the
|
|
+// id in an object, so it does not affect scoping at all, and we use the global
|
|
+// z.
|
|
+let z = 50;
|
|
+
|
|
+globalThis.f = function(r) {
|
|
+ let { a, b } = r;
|
|
+ let { z: c } = r;
|
|
+ return g(a, b, c, d, z);
|
|
+};
|
|
+
|
|
+// As above, but now with array destructuring.
|
|
+let a2 = 10;
|
|
+let b2 = 20;
|
|
+let c2 = 30;
|
|
+let d2 = 40;
|
|
+
|
|
+globalThis.f2 = function(r2) {
|
|
+ let [ a2, b2, c2 ] = r2;
|
|
+ return g2(a2, b2, c2, d2);
|
|
+};
|
|
diff --git a/test/test_other.py b/test/test_other.py
|
|
index cc775be0f..fe75f7683 100644
|
|
--- a/test/test_other.py
|
|
+++ b/test/test_other.py
|
|
@@ -2492,6 +2492,7 @@ int f() {
|
|
'JSDCE': ('optimizer/JSDCE.js', ['JSDCE']),
|
|
'JSDCE-hasOwnProperty': ('optimizer/JSDCE-hasOwnProperty.js', ['JSDCE']),
|
|
'JSDCE-fors': ('optimizer/JSDCE-fors.js', ['JSDCE']),
|
|
+ 'JSDCE-objectPattern': ('optimizer/JSDCE-objectPattern.js', ['JSDCE']),
|
|
'AJSDCE': ('optimizer/AJSDCE.js', ['AJSDCE']),
|
|
'emitDCEGraph': ('optimizer/emitDCEGraph.js', ['emitDCEGraph', 'noPrint']),
|
|
'emitDCEGraph-closure': ('optimizer/emitDCEGraph.js', ['emitDCEGraph', 'noPrint', '--closureFriendly']),
|
|
diff --git a/tools/acorn-optimizer.js b/tools/acorn-optimizer.js
|
|
index 5274f3114..281b21b25 100755
|
|
--- a/tools/acorn-optimizer.js
|
|
+++ b/tools/acorn-optimizer.js
|
|
@@ -319,7 +319,16 @@ function runJSDCE(ast, aggressive) {
|
|
const old = node.declarations;
|
|
let removedHere = 0;
|
|
node.declarations = node.declarations.filter((node) => {
|
|
- const curr = node.id.name;
|
|
+ assert(node.type === 'VariableDeclarator');
|
|
+ const id = node.id;
|
|
+ if (id.type === 'ObjectPattern' || id.type === 'ArrayPattern') {
|
|
+ // TODO: DCE into object patterns, that is, things like
|
|
+ // let { a, b } = ..
|
|
+ // let [ a, b ] = ..
|
|
+ return true;
|
|
+ }
|
|
+ assert(id.type === 'Identifier');
|
|
+ const curr = id.name;
|
|
const value = node.init;
|
|
const keep = !(curr in names) || (value && hasSideEffects(value));
|
|
if (!keep) removedHere = 1;
|
|
@@ -390,8 +399,25 @@ function runJSDCE(ast, aggressive) {
|
|
|
|
recursiveWalk(ast, {
|
|
VariableDeclarator(node, c) {
|
|
- const name = node.id.name;
|
|
- ensureData(scopes[scopes.length - 1], name).def = 1;
|
|
+ const id = node.id;
|
|
+ if (id.type === 'ObjectPattern') {
|
|
+ id.properties.forEach((node) => {
|
|
+ const value = node.value;
|
|
+ assert(value.type === 'Identifier');
|
|
+ const name = value.name;
|
|
+ ensureData(scopes[scopes.length - 1], name).def = 1;
|
|
+ });
|
|
+ } else if (id.type === 'ArrayPattern') {
|
|
+ id.elements.forEach((node) => {
|
|
+ assert(node.type === 'Identifier');
|
|
+ const name = node.name;
|
|
+ ensureData(scopes[scopes.length - 1], name).def = 1;
|
|
+ });
|
|
+ } else {
|
|
+ assert(id.type === 'Identifier');
|
|
+ const name = id.name;
|
|
+ ensureData(scopes[scopes.length - 1], name).def = 1;
|
|
+ }
|
|
if (node.init) c(node.init);
|
|
},
|
|
ObjectExpression(node, c) {
|
|
--
|
|
2.25.1
|
|
|