Skip to content

Commit 6afe64f

Browse files
authored
Merge pull request #361 from karthik2804/readd_regex_precompilation
add regex precompilation to build step
2 parents 06dcba7 + dc5c773 commit 6afe64f

File tree

6 files changed

+232
-17
lines changed

6 files changed

+232
-17
lines changed

packages/build-tools/package-lock.json

Lines changed: 138 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/build-tools/package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "@spinframework/build-tools",
3-
"version": "1.0.1",
3+
"version": "1.0.2",
44
"description": "",
55
"main": "index.js",
66
"scripts": {
7-
"build": "make && rm -rf dist && tsc && chmod +x dist/*",
7+
"build": "make && rm -rf dist && tsc && chmod +x dist/* && cp src/*.js dist/",
88
"fmt": "prettier --write \"src/**/*.{ts,tsx,js,jsx}\"",
99
"test": "npm run build && mocha --require ts-node/register test/**/*.spec.ts"
1010
},
@@ -31,7 +31,11 @@
3131
"dependencies": {
3232
"@bytecodealliance/componentize-js": "^0.18.1",
3333
"@bytecodealliance/jco": "^1.10.2",
34-
"yargs": "^17.7.2"
34+
"yargs": "^17.7.2",
35+
"acorn-walk": "^8.3.4",
36+
"acron": "^1.0.5",
37+
"magic-string": "^0.30.17",
38+
"regexpu-core": "^6.2.0"
3539
},
3640
"files": [
3741
"lib",

packages/build-tools/src/index.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
import { componentize } from '@bytecodealliance/componentize-js';
44
import { version as componentizeVersion } from '@bytecodealliance/componentize-js';
55
import { getPackagesWithWasiDeps, processWasiDeps } from './wasiDepsParser.js';
6-
76
import {
87
calculateChecksum,
98
saveBuildData,
109
} from './utils.js';
1110
import { getCliArgs } from './cli.js';
1211
import { getBuildDataPath, ShouldComponentize } from './build.js';
13-
import { writeFile } from 'node:fs/promises';
12+
import { readFile, writeFile } from 'node:fs/promises';
1413
import { mergeWit } from '../lib/wit_tools.js';
14+
//@ts-ignore
15+
import { precompile } from "./precompile.js"
16+
import path from 'node:path'
1517

1618
async function main() {
1719
try {
@@ -61,8 +63,17 @@ async function main() {
6163
'combined-wit:[email protected]',
6264
);
6365

66+
const source = await readFile(src, 'utf8');
67+
const precompiledSource = precompile(source, src, true) as string;
68+
69+
// Write precompiled source to disk for debugging purposes In the future we
70+
// will also write a source map to make debugging easier
71+
let srcDir = path.dirname(src);
72+
let precompiledSourcePath = path.join(srcDir, 'precompiled-source.js');
73+
await writeFile(precompiledSourcePath, precompiledSource);
74+
6475
const { component } = await componentize({
65-
sourcePath: src,
76+
sourcePath: precompiledSourcePath,
6677
// @ts-ignore
6778
witWorld: inlineWit,
6879
runtimeArgs,
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2024 Fastly Inc.
2+
// License: the Apache License v2.0 with LLVM Exceptions.
3+
// See https://llvm.org/LICENSE.txt for license information.
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
6+
import regexpuc from 'regexpu-core';
7+
import { parse } from 'acorn';
8+
import MagicString from 'magic-string';
9+
import { simple as simpleWalk } from 'acorn-walk';
10+
11+
const PREAMBLE = `;{
12+
// Precompiled regular expressions
13+
const precompile = (r) => { r.exec('a'); r.exec('\\u1000'); };`;
14+
const POSTAMBLE = '}';
15+
16+
/// Emit a block of javascript that will pre-compile the regular expressions given. As spidermonkey
17+
/// will intern regular expressions, duplicating them at the top level and testing them with both
18+
/// an ascii and utf8 string should ensure that they won't be re-compiled when run in the fetch
19+
/// handler.
20+
export function precompile(source, filename = '<input>', moduleMode = false) {
21+
const magicString = new MagicString(source, {
22+
filename,
23+
});
24+
25+
const ast = parse(source, {
26+
ecmaVersion: 'latest',
27+
sourceType: moduleMode ? 'module' : 'script',
28+
});
29+
30+
const precompileCalls = [];
31+
simpleWalk(ast, {
32+
Literal(node) {
33+
if (!node.regex) return;
34+
let transpiledPattern;
35+
try {
36+
transpiledPattern = regexpuc(node.regex.pattern, node.regex.flags, {
37+
unicodePropertyEscapes: 'transform',
38+
});
39+
} catch {
40+
// swallow regex parse errors here to instead throw them at the engine level
41+
// this then also avoids regex parser bugs being thrown unnecessarily
42+
transpiledPattern = node.regex.pattern;
43+
}
44+
const transpiledRegex = `/${transpiledPattern}/${node.regex.flags}`;
45+
precompileCalls.push(`precompile(${transpiledRegex});`);
46+
magicString.overwrite(node.start, node.end, transpiledRegex);
47+
},
48+
});
49+
50+
if (!precompileCalls.length) return source;
51+
52+
magicString.prepend(`${PREAMBLE}${precompileCalls.join('\n')}${POSTAMBLE}`);
53+
54+
// When we're ready to pipe in source maps:
55+
// const map = magicString.generateMap({
56+
// source: 'source.js',
57+
// file: 'converted.js.map',
58+
// includeContent: true
59+
// });
60+
61+
return magicString.toString();
62+
}

test/test-app/package-lock.json

Lines changed: 10 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/test.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ echo "built the test app successfully"
2323
# Start the spin app in the background
2424
echo "Starting Spin app"
2525
spin up &
26-
SPIN_PID=$!
2726

2827
# wait for app to be up and running
2928
echo "Waiting for Spin app to be ready"
@@ -36,7 +35,7 @@ echo "\n\nTest completed"
3635

3736
# kill the spin app
3837
echo "Stopping Spin"
39-
kill -9 $SPIN_PID
38+
killall spin
4039

4140

4241
if [ "$isFailed" = true ] ; then

0 commit comments

Comments
 (0)