@dom-expressions/jsx-compiler 0.50.0-next.17 → 0.50.0-next.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -9
- package/index.js +59 -9
- package/package.json +23 -9
package/README.md
CHANGED
|
@@ -15,6 +15,16 @@ matching your platform automatically through `optionalDependencies`. On other
|
|
|
15
15
|
platforms, build from source with `pnpm run build` inside
|
|
16
16
|
`packages/jsx-compiler` (requires a Rust toolchain).
|
|
17
17
|
|
|
18
|
+
### WebAssembly and StackBlitz
|
|
19
|
+
|
|
20
|
+
The compiler also ships a WASI fallback for environments such as StackBlitz
|
|
21
|
+
WebContainers, where Node.js reports a native platform but cannot load `.node`
|
|
22
|
+
addons. Package managers install the WASI binding as an optional dependency
|
|
23
|
+
without requiring architecture configuration. The normal package entry point
|
|
24
|
+
prefers a native binding and falls back to
|
|
25
|
+
`@dom-expressions/jsx-compiler-wasm32-wasi` when native addons are unavailable.
|
|
26
|
+
Set `NAPI_RS_FORCE_WASI=error` to require the WASI binding for testing.
|
|
27
|
+
|
|
18
28
|
## Usage
|
|
19
29
|
|
|
20
30
|
This package exposes a compiler backend API. It is not a Vite, Rollup, or Babel
|
|
@@ -136,8 +146,9 @@ Supported options track the Babel plugin where currently implemented:
|
|
|
136
146
|
- `omitQuotes`
|
|
137
147
|
- `omitAttributeSpacing`
|
|
138
148
|
- `inlineStyles`
|
|
139
|
-
- `effectWrapper`:
|
|
140
|
-
-
|
|
149
|
+
- `effectWrapper`: custom import name string, or `false` to disable
|
|
150
|
+
- `memoWrapper`: custom import name string, or `false` to disable
|
|
151
|
+
- `wrapConditionals`
|
|
141
152
|
- `staticMarker`
|
|
142
153
|
- `validate`
|
|
143
154
|
- `omitNestedClosingTags`
|
|
@@ -146,6 +157,22 @@ Supported options track the Babel plugin where currently implemented:
|
|
|
146
157
|
- `requireImportSource`
|
|
147
158
|
- `renderers`
|
|
148
159
|
|
|
160
|
+
## Performance
|
|
161
|
+
|
|
162
|
+
Compared against `@dom-expressions/babel-plugin-jsx` compiling identical
|
|
163
|
+
sources under identical options (Apple Silicon, release build, in-process,
|
|
164
|
+
median of 7 iterations after warmup — run `pnpm bench` in this package to
|
|
165
|
+
reproduce on your machine):
|
|
166
|
+
|
|
167
|
+
| Workload | babel-plugin-jsx | jsx-compiler | Speedup |
|
|
168
|
+
| ----------------------------------------------- | ---------------: | -----------: | ------: |
|
|
169
|
+
| Fixture corpus (88 files, 174 KB, all 10 modes) | 151 ms | 8.4 ms | 18x |
|
|
170
|
+
| 129 KB single module | 230 ms | 4.6 ms | 50x |
|
|
171
|
+
| 1 MB single module | 10,164 ms | 39 ms | 258x |
|
|
172
|
+
|
|
173
|
+
Native throughput stays flat at ~20–27 MB/s as input grows, while Babel's
|
|
174
|
+
per-file cost grows super-linearly — so the gap widens with file size.
|
|
175
|
+
|
|
149
176
|
## Current Scope
|
|
150
177
|
|
|
151
178
|
This package is the AST-native compiler backend. It currently has checked fixture coverage for
|
|
@@ -159,10 +186,10 @@ the DOM, hydratable DOM, dev hydratable DOM, SSR, hydratable SSR, universal, dyn
|
|
|
159
186
|
attribute handling covered by the checked fixture suites for those targets
|
|
160
187
|
- Solid-compatible defaults such as `contextToCustomElements: true`
|
|
161
188
|
- option coverage for `hydratable`, `dev`, `delegateEvents`, `delegatedEvents`,
|
|
162
|
-
`omitQuotes`, `omitAttributeSpacing`, `inlineStyles`, `effectWrapper
|
|
163
|
-
|
|
164
|
-
`
|
|
165
|
-
|
|
189
|
+
`omitQuotes`, `omitAttributeSpacing`, `inlineStyles`, `effectWrapper`,
|
|
190
|
+
`memoWrapper`, `wrapConditionals`, `requireImportSource`, `staticMarker`,
|
|
191
|
+
`validate`, `omitNestedClosingTags`, `omitLastClosingTag`, `builtIns`, and
|
|
192
|
+
dynamic `renderers`
|
|
166
193
|
- source maps for the implemented path
|
|
167
194
|
|
|
168
195
|
## Not Implemented Yet
|
|
@@ -172,8 +199,6 @@ The compiler intentionally rejects unsupported features instead of pretending to
|
|
|
172
199
|
- DOM `namespaceElements` sections that the current Oxc parser rejects before transform
|
|
173
200
|
(for example, hyphenated JSX member segments)
|
|
174
201
|
- arbitrary custom renderer names beyond dynamic DOM renderer override plus universal fallback
|
|
175
|
-
- custom `effectWrapper` / `memoWrapper` helper names
|
|
176
|
-
- unpaired `wrapConditionals: false` or `memoWrapper: false`
|
|
177
202
|
- unknown/custom namespaced DOM attributes outside known runtime namespaces such as `xlink`
|
|
178
203
|
|
|
179
204
|
## Architecture
|
|
@@ -198,4 +223,3 @@ The module layout mirrors the Babel plugin shape where possible:
|
|
|
198
223
|
- `src/ssr/transform.rs`
|
|
199
224
|
- `src/universal/mod.rs`
|
|
200
225
|
- `src/universal/transform.rs`
|
|
201
|
-
|
package/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
|
|
6
|
-
const native =
|
|
6
|
+
const native = requireBinding();
|
|
7
7
|
|
|
8
8
|
function transform(code, options) {
|
|
9
9
|
if (typeof code !== "string") {
|
|
@@ -152,10 +152,20 @@ function platformArchSuffix() {
|
|
|
152
152
|
return null;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
function
|
|
155
|
+
function requireBinding() {
|
|
156
156
|
const explicit = process.env.JSX_DOM_EXPRESSIONS_COMPILER_NATIVE;
|
|
157
157
|
if (explicit) return require(explicit);
|
|
158
158
|
|
|
159
|
+
const forceWasi = process.env.NAPI_RS_FORCE_WASI;
|
|
160
|
+
if (forceWasi === "true" || forceWasi === "error") {
|
|
161
|
+
const wasi = requireWasi();
|
|
162
|
+
if (wasi) return wasi;
|
|
163
|
+
if (forceWasi === "error") {
|
|
164
|
+
throw new Error("WASI binding not found and NAPI_RS_FORCE_WASI is set to error");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let nativeError;
|
|
159
169
|
const suffix = platformArchSuffix();
|
|
160
170
|
|
|
161
171
|
// Local builds (napi build output) take precedence for development.
|
|
@@ -164,23 +174,63 @@ function requireNative() {
|
|
|
164
174
|
localCandidates.push("jsx-compiler.node");
|
|
165
175
|
for (const file of localCandidates) {
|
|
166
176
|
const full = path.join(__dirname, file);
|
|
167
|
-
if (fs.existsSync(full))
|
|
177
|
+
if (fs.existsSync(full)) {
|
|
178
|
+
try {
|
|
179
|
+
return require(full);
|
|
180
|
+
} catch (error) {
|
|
181
|
+
nativeError = error;
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
168
185
|
}
|
|
169
186
|
|
|
170
|
-
if (suffix) {
|
|
187
|
+
if (!nativeError && suffix) {
|
|
188
|
+
const packageName = `@dom-expressions/jsx-compiler-${suffix}`;
|
|
171
189
|
try {
|
|
172
|
-
return require(
|
|
190
|
+
return require(packageName);
|
|
173
191
|
} catch (error) {
|
|
174
|
-
if (error
|
|
192
|
+
if (!isMissingPackage(error, packageName)) nativeError = error;
|
|
175
193
|
}
|
|
176
194
|
}
|
|
177
195
|
|
|
196
|
+
const wasi = requireWasi();
|
|
197
|
+
if (wasi) return wasi;
|
|
198
|
+
|
|
199
|
+
if (nativeError) {
|
|
200
|
+
nativeError.message +=
|
|
201
|
+
"\nThe native binding could not be loaded and the optional " +
|
|
202
|
+
"@dom-expressions/jsx-compiler-wasm32-wasi fallback is not installed.";
|
|
203
|
+
throw nativeError;
|
|
204
|
+
}
|
|
205
|
+
|
|
178
206
|
throw new Error(
|
|
179
|
-
`Could not find
|
|
207
|
+
`Could not find an @dom-expressions/jsx-compiler binding for ${process.platform}-${process.arch}` +
|
|
180
208
|
(suffix
|
|
181
|
-
? ` (expected
|
|
209
|
+
? ` (expected @dom-expressions/jsx-compiler-${suffix}, @dom-expressions/jsx-compiler-wasm32-wasi, or a local build)`
|
|
182
210
|
: " (no prebuilt binary is published for this platform)") +
|
|
183
|
-
".
|
|
211
|
+
". Install with WASM support or run `pnpm run build` in packages/jsx-compiler."
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function requireWasi() {
|
|
216
|
+
const localWasi = path.join(__dirname, "jsx-compiler.wasi.cjs");
|
|
217
|
+
if (fs.existsSync(localWasi)) return require(localWasi);
|
|
218
|
+
|
|
219
|
+
const packageName = "@dom-expressions/jsx-compiler-wasm32-wasi";
|
|
220
|
+
try {
|
|
221
|
+
return require(packageName);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
if (!isMissingPackage(error, packageName)) throw error;
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function isMissingPackage(error, packageName) {
|
|
229
|
+
return (
|
|
230
|
+
error &&
|
|
231
|
+
error.code === "MODULE_NOT_FOUND" &&
|
|
232
|
+
typeof error.message === "string" &&
|
|
233
|
+
error.message.includes(`'${packageName}'`)
|
|
184
234
|
);
|
|
185
235
|
}
|
|
186
236
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dom-expressions/jsx-compiler",
|
|
3
3
|
"description": "A JSX to DOM Expressions compiler implemented with Oxc",
|
|
4
|
-
"version": "0.50.0-next.
|
|
4
|
+
"version": "0.50.0-next.19",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -31,22 +31,36 @@
|
|
|
31
31
|
"aarch64-apple-darwin",
|
|
32
32
|
"x86_64-unknown-linux-gnu",
|
|
33
33
|
"aarch64-unknown-linux-gnu",
|
|
34
|
-
"x86_64-pc-windows-msvc"
|
|
35
|
-
|
|
34
|
+
"x86_64-pc-windows-msvc",
|
|
35
|
+
"wasm32-wasip1-threads"
|
|
36
|
+
],
|
|
37
|
+
"wasm": {
|
|
38
|
+
"browser": {
|
|
39
|
+
"fs": false,
|
|
40
|
+
"asyncInit": false,
|
|
41
|
+
"buffer": false,
|
|
42
|
+
"errorEvent": true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
36
45
|
},
|
|
37
46
|
"devDependencies": {
|
|
38
|
-
"@
|
|
47
|
+
"@emnapi/core": "^1.11.2",
|
|
48
|
+
"@emnapi/runtime": "^1.11.2",
|
|
49
|
+
"@napi-rs/cli": "^3.7.2",
|
|
50
|
+
"@napi-rs/wasm-runtime": "^1.1.6"
|
|
39
51
|
},
|
|
40
52
|
"optionalDependencies": {
|
|
41
|
-
"@dom-expressions/jsx-compiler-darwin-x64": "0.50.0-next.
|
|
42
|
-
"@dom-expressions/jsx-compiler-darwin-arm64": "0.50.0-next.
|
|
43
|
-
"@dom-expressions/jsx-compiler-linux-x64-gnu": "0.50.0-next.
|
|
44
|
-
"@dom-expressions/jsx-compiler-linux-arm64-gnu": "0.50.0-next.
|
|
45
|
-
"@dom-expressions/jsx-compiler-win32-x64-msvc": "0.50.0-next.
|
|
53
|
+
"@dom-expressions/jsx-compiler-darwin-x64": "0.50.0-next.19",
|
|
54
|
+
"@dom-expressions/jsx-compiler-darwin-arm64": "0.50.0-next.19",
|
|
55
|
+
"@dom-expressions/jsx-compiler-linux-x64-gnu": "0.50.0-next.19",
|
|
56
|
+
"@dom-expressions/jsx-compiler-linux-arm64-gnu": "0.50.0-next.19",
|
|
57
|
+
"@dom-expressions/jsx-compiler-win32-x64-msvc": "0.50.0-next.19",
|
|
58
|
+
"@dom-expressions/jsx-compiler-wasm32-wasi": "0.50.0-next.19"
|
|
46
59
|
},
|
|
47
60
|
"scripts": {
|
|
48
61
|
"build": "napi build --release --strip --manifest-path ./Cargo.toml",
|
|
49
62
|
"build:debug": "napi build --manifest-path ./Cargo.toml",
|
|
63
|
+
"bench": "pnpm run build && node scripts/bench.mjs",
|
|
50
64
|
"lint": "cargo clippy --manifest-path ./Cargo.toml -- -D warnings",
|
|
51
65
|
"test": "pnpm run build:debug && jest --no-cache",
|
|
52
66
|
"artifacts": "napi artifacts",
|