Skip to content

Commit d3eb2b2

Browse files
authored
Reuse arrays in visitor keys (#18386)
1 parent c45fef1 commit d3eb2b2

File tree

21 files changed

+275
-62
lines changed

21 files changed

+275
-62
lines changed

scripts/build/config.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,10 @@ const pluginFiles = [
598598
"const LOCAL_DEBUG = false &&",
599599
);
600600

601-
text = text.replace(/(?<=\n)export .*?;/u, "export { preprocess };");
601+
text = text.replace(
602+
/(?<=\n)export .*?;/u,
603+
"export { preprocess, getVoidTags, visitorKeys };",
604+
);
602605

603606
return text;
604607
},

scripts/build/esbuild-plugins/evaluate.js

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,89 @@
1+
import assert from "node:assert";
2+
import path from "node:path";
13
import url from "node:url";
24
import { isValidIdentifier } from "@babel/types";
5+
import { outdent } from "outdent";
36
import serialize from "serialize-javascript";
47

8+
function serializeModule(module) {
9+
return Object.entries(module)
10+
.map(([specifier, value]) => {
11+
const code =
12+
value instanceof RegExp
13+
? `/${value.source}/${value.flags}`
14+
: serialize(value, { space: 2, unsafe: true });
15+
if (specifier === "default") {
16+
return `export default ${code};`;
17+
}
18+
19+
if (!isValidIdentifier(specifier)) {
20+
throw new Error(`${specifier} is not a valid specifier`);
21+
}
22+
23+
return `export const ${specifier} = ${code};`;
24+
})
25+
.join("\n");
26+
}
27+
28+
function serializeVisitorKeys(module) {
29+
const specifiers = Object.keys(module);
30+
assert.deepEqual(specifiers, ["default"]);
31+
32+
const references = new Map();
33+
const properties = Object.entries(module.default);
34+
for (const [, keys] of properties) {
35+
if (!references.has(keys)) {
36+
references.set(keys, 1);
37+
} else {
38+
references.set(keys, references.get(keys) + 1);
39+
}
40+
}
41+
42+
const variables = [];
43+
const propertiesText = [];
44+
for (const [type, keys] of properties) {
45+
const isSingleReference = references.get(keys) === 1;
46+
const key = isValidIdentifier(type) ? type : JSON.stringify(type);
47+
if (isSingleReference) {
48+
propertiesText.push(` ${key}: ${JSON.stringify(keys)},`);
49+
} else {
50+
if (!variables.includes(keys)) {
51+
variables.push(keys);
52+
}
53+
const index = variables.indexOf(keys);
54+
propertiesText.push(` ${key}: vk[${index}],`);
55+
}
56+
}
57+
58+
const code = outdent`
59+
const vk = [
60+
${variables.map((keys) => ` ${JSON.stringify(keys)},`).join("\n")}
61+
];
62+
63+
export default {
64+
${propertiesText.join("\n")}
65+
};
66+
`;
67+
68+
return code;
69+
}
70+
571
export default function esbuildPluginEvaluate() {
672
return {
773
name: "evaluate",
874
setup(build) {
975
build.onLoad(
1076
{ filter: /\.evaluate\.[cm]?js$/, namespace: "file" },
11-
async ({ path }) => {
12-
const module = await import(url.pathToFileURL(path));
13-
const text = Object.entries(module)
14-
.map(([specifier, value]) => {
15-
const code =
16-
value instanceof RegExp
17-
? `/${value.source}/${value.flags}`
18-
: serialize(value, { space: 2 });
19-
20-
if (specifier === "default") {
21-
return `export default ${code};`;
22-
}
23-
24-
if (!isValidIdentifier(specifier)) {
25-
throw new Error(`${specifier} is not a valid specifier`);
26-
}
27-
28-
return `export const ${specifier} = ${code};`;
29-
})
30-
.join("\n");
77+
async ({ path: filePath }) => {
78+
const module = await import(url.pathToFileURL(filePath));
79+
const isVisitorKeys =
80+
path.basename(filePath, path.extname(filePath)) ===
81+
"visitor-keys.evaluate";
82+
83+
const text = isVisitorKeys
84+
? serializeVisitorKeys(module)
85+
: serializeModule(module);
86+
3187
return { contents: text };
3288
},
3389
);

src/language-css/get-visitor-keys.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import createGetVisitorKeys from "../utilities/create-get-visitor-keys.js";
2-
import visitorKeys from "./visitor-keys.js";
2+
import visitorKeys from "./visitor-keys.evaluate.js";
33

44
const getVisitorKeys = createGetVisitorKeys(visitorKeys);
55

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
const visitorKeys = {
1+
import { generateReferenceSharedVisitorKeys } from "../utilities/visitor-keys.js";
2+
3+
const visitorKeys = generateReferenceSharedVisitorKeys({
24
"css-root": ["frontMatter", "nodes"],
35
"css-comment": [],
46
"css-rule": ["selector", "nodes"],
@@ -43,6 +45,6 @@ const visitorKeys = {
4345
"value-atword": [],
4446
"value-unicode-range": [],
4547
"value-unknown": [],
46-
};
48+
});
4749

4850
export default visitorKeys;

src/language-handlebars/get-visitor-keys.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import createGetVisitorKeys from "../utilities/create-get-visitor-keys.js";
2-
import visitorKeys from "./visitor-keys.evaluate.js";
2+
import visitorKeys from "./visitor-keys.js";
33

44
const getVisitorKeys = createGetVisitorKeys(visitorKeys);
55

src/language-handlebars/html-void-elements.evaluate.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/language-handlebars/utilities.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import htmlVoidElements from "./html-void-elements.evaluate.js";
1+
// Do not use void tags from other package, won't match
2+
import { getVoidTags } from "@glimmer/syntax";
3+
4+
const htmlVoidElements = new Set(getVoidTags());
25

36
function isUppercase(string) {
47
return string.toUpperCase() === string;
File renamed without changes.

src/language-html/get-visitor-keys.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import createGetVisitorKeys from "../utilities/create-get-visitor-keys.js";
2-
import visitorKeys from "./visitor-keys.js";
2+
import visitorKeys from "./visitor-keys.evaluate.js";
33

44
const getVisitorKeys = createGetVisitorKeys(visitorKeys, "kind");
55

src/language-html/visitor-keys.js renamed to src/language-html/visitor-keys.evaluate.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
const visitorKeys = {
1+
import { generateReferenceSharedVisitorKeys } from "../utilities/visitor-keys.js";
2+
3+
const visitorKeys = generateReferenceSharedVisitorKeys({
24
root: ["children"],
35
element: ["attrs", "children"],
46
ieConditionalComment: ["children"],
@@ -17,6 +19,6 @@ const visitorKeys = {
1719
angularLetDeclarationInitializer: [],
1820
angularIcuExpression: ["cases"],
1921
angularIcuCase: ["expression"],
20-
};
22+
});
2123

2224
export default visitorKeys;

0 commit comments

Comments
 (0)