@solidjs/compiler 2.0.0-rc.2

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.
Files changed (4) hide show
  1. package/README.md +162 -0
  2. package/index.js +414 -0
  3. package/package.json +72 -0
  4. package/types.d.ts +174 -0
package/README.md ADDED
@@ -0,0 +1,162 @@
1
+ # @solidjs/compiler
2
+
3
+ Solid 2.0's native Oxc JSX compiler. Integrations call `transform()` once per source module; this package is not a Vite, Rollup, or Babel plugin by itself. The JavaScript fallback is [`@solidjs/babel-plugin`](../babel-plugin).
4
+
5
+ > **Solid 2.0 (Release Candidate).** Pin exact versions. The Node `transform()` interface is the supported public contract; the Rust `compile` API is unstable.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @solidjs/compiler
11
+ ```
12
+
13
+ The package ships prebuilt native binaries as optional per-platform packages (`@solidjs/compiler-darwin-arm64`, `-darwin-x64`, `-linux-x64-gnu`, `-linux-arm64-gnu`, `-win32-x64-msvc`). Your package manager installs the one matching your platform. On other platforms, build from source with `pnpm run build` inside `packages/compiler` (requires a Rust toolchain).
14
+
15
+ ### WebAssembly and StackBlitz
16
+
17
+ A WASI fallback covers environments such as StackBlitz WebContainers, where Node reports a native platform but cannot load `.node` addons. Package managers install `@solidjs/compiler-wasm32-wasi` as an optional dependency. The package entry prefers a native binding and falls back to WASI when native addons are unavailable.
18
+
19
+ - `NAPI_RS_FORCE_WASI=error` requires the WASI binding (useful in tests).
20
+ - `SOLID_COMPILER_NATIVE=/path/to/binding.node` loads an explicit native addon.
21
+
22
+ ## Usage
23
+
24
+ Omitted options match `@solidjs/babel-plugin` (and the old `babel-preset-solid`): `moduleName` is `"@solidjs/web"`, `generate` is `"dom"`, and control-flow tags (`For`, `Show`, `Switch`, `Match`, `Loading`, `Reveal`, `Portal`, `Repeat`, `Dynamic`, `Errored`) are auto-imported from that module.
25
+
26
+ ```js
27
+ const { transform } = require("@solidjs/compiler");
28
+
29
+ const result = transform(`const view = <div>Hello</div>;`, {
30
+ filename: "App.jsx"
31
+ });
32
+
33
+ console.log(result.code);
34
+ ```
35
+
36
+ `transformAsync()` is the same transform behind a promise, for integration points that expect one.
37
+
38
+ ### Client DOM
39
+
40
+ ```js
41
+ const result = transform(source, {
42
+ filename: "App.jsx",
43
+ generate: "dom",
44
+ hydratable: true
45
+ });
46
+ ```
47
+
48
+ `contextToCustomElements` defaults to `true`. Use `dev: true` with `hydratable: true` to emit hydration walk helpers such as `getFirstChild` / `getNextSibling`.
49
+
50
+ ### SSR
51
+
52
+ SSR still imports runtime helpers from `@solidjs/web`. Set `generate: "ssr"` (and `hydratable: true` when the client will hydrate).
53
+
54
+ ```js
55
+ const result = transform(source, {
56
+ filename: "entry-server.jsx",
57
+ generate: "ssr",
58
+ hydratable: true
59
+ });
60
+ ```
61
+
62
+ ### Universal and dynamic
63
+
64
+ Custom renderers use `generate: "universal"` with `moduleName` pointing at the renderer package. Dynamic mode uses that renderer as the fallback and can route a configured set of native tags to the DOM renderer.
65
+
66
+ ```js
67
+ const result = transform(source, {
68
+ filename: "hybrid.jsx",
69
+ moduleName: "solid-custom-dom",
70
+ generate: "dynamic",
71
+ renderers: [
72
+ {
73
+ name: "dom",
74
+ moduleName: "@solidjs/web",
75
+ elements: ["div", "span", "button", "input"]
76
+ }
77
+ ]
78
+ });
79
+ ```
80
+
81
+ ### Source maps
82
+
83
+ Pass `sourceMap: true` to receive a JSON source map string in `result.map`.
84
+
85
+ ### Options
86
+
87
+ - `filename`
88
+ - `moduleName` (default `"@solidjs/web"`)
89
+ - `generate`: `"dom"`, `"ssr"`, `"universal"`, or `"dynamic"` (default `"dom"`)
90
+ - `hydratable`
91
+ - `dev`
92
+ - `sourceMap`
93
+ - `contextToCustomElements` (default `true`)
94
+ - `delegateEvents`
95
+ - `delegatedEvents`
96
+ - `omitQuotes`
97
+ - `omitAttributeSpacing`
98
+ - `inlineStyles`
99
+ - `effectWrapper`: import name string, or `false` to disable
100
+ - `memoWrapper`: import name string, or `false` to disable
101
+ - `wrapConditionals`
102
+ - `staticMarker`
103
+ - `validate`
104
+ - `omitNestedClosingTags`
105
+ - `omitLastClosingTag`
106
+ - `builtIns` (default `["For", "Show", "Switch", "Match", "Loading", "Reveal", "Portal", "Repeat", "Dynamic", "Errored"]`)
107
+ - `requireImportSource`
108
+ - `serverComponents`
109
+ - `renderers`
110
+
111
+ ### Server function directives (experimental)
112
+
113
+ `transformDirectives(code, options)` is a second pass for `"use server"`. It applies to plain `.js`/`.ts` as well as JSX/TSX.
114
+
115
+ ```js
116
+ const { transformDirectives } = require("@solidjs/compiler");
117
+
118
+ const result = transformDirectives(source, {
119
+ filename: "/project/src/api.ts",
120
+ root: "/project",
121
+ mode: "server" // or "client"
122
+ });
123
+
124
+ result.valid; // false when no directive matched — keep the original module
125
+ result.code;
126
+ result.functions; // [{ id, name, exports }] for manifest building
127
+ ```
128
+
129
+ The runtime module defaults to `@solidjs/web/server-functions`. Function IDs use `xxhash32(root-relative path)-<count>` (name-suffixed with `env: "development"`). There are also experimental `transformLazy` and `transformRefresh` passes.
130
+
131
+ ## Rust compiler core
132
+
133
+ The crate also exposes a host-independent Rust API. The crate name is `solidjs-compiler`; the Node `transform()` delegates to the same core.
134
+
135
+ ```rust
136
+ use solidjs_compiler::{compile, CompileOptions};
137
+
138
+ let output = compile(
139
+ "const view = <div>{name()}</div>;",
140
+ &CompileOptions::default(),
141
+ )?;
142
+ ```
143
+
144
+ `CompileOptions::default()` uses `module_name: "@solidjs/web"` and the same control-flow `built_ins` as the Babel plugin. Build with `--no-default-features` when embedding without the Node-API adapter.
145
+
146
+ > **Stability:** the Rust API is unstable while the compiler is pre-1.0. Options, output, and error types may change in any release — pin an exact revision when embedding it.
147
+
148
+ ## Performance
149
+
150
+ Compared against `@solidjs/babel-plugin` compiling identical sources under identical options (Apple M5, 10 cores, 32 GB RAM, Node 26, release build, in-process, median of 7 iterations after warmup — run `pnpm bench` in this package to reproduce):
151
+
152
+ | Workload | babel-plugin | compiler | Speedup |
153
+ | ----------------------------------------------- | -----------: | -------: | ------: |
154
+ | Fixture corpus (88 files, 175 KB, all 10 modes) | 440 ms | 19 ms | 23x |
155
+ | 129 KB single module | 545 ms | 9.4 ms | 58x |
156
+ | 1 MB single module | 24,975 ms | 70 ms | 355x |
157
+
158
+ Native throughput stays roughly flat as input grows, while Babel's per-file cost grows super-linearly.
159
+
160
+ ## Architecture
161
+
162
+ Parse with Oxc, transform JSX with `VisitMut`, build replacements with `AstBuilder`, codegen once. Unsupported features are rejected rather than silently ignored. The module layout follows the Babel plugin (`shared`, `dom`, `ssr`, `universal`) where that mapping is useful.
package/index.js ADDED
@@ -0,0 +1,414 @@
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+
6
+ const native = requireBinding();
7
+
8
+ function transform(code, options) {
9
+ if (typeof code !== "string") {
10
+ throw new TypeError("@solidjs/compiler transform() expects source code as a string");
11
+ }
12
+
13
+ const nativeOptions = validateOptions(code, options);
14
+ const result = native.transform(code, nativeOptions);
15
+ return {
16
+ code: result.code,
17
+ map: result.map ?? null
18
+ };
19
+ }
20
+
21
+ function transformAsync(code, options) {
22
+ return Promise.resolve().then(() => transform(code, options));
23
+ }
24
+
25
+ function transformDirectives(code, options) {
26
+ if (typeof code !== "string") {
27
+ throw new TypeError("@solidjs/compiler transformDirectives() expects source code as a string");
28
+ }
29
+
30
+ const nativeOptions = validateDirectivesOptions(options);
31
+ const result = native.transformDirectives(code, nativeOptions);
32
+ return {
33
+ code: result.code,
34
+ map: result.map ?? null,
35
+ valid: result.valid,
36
+ functions: result.functions
37
+ };
38
+ }
39
+
40
+ function transformDirectivesAsync(code, options) {
41
+ return Promise.resolve().then(() => transformDirectives(code, options));
42
+ }
43
+
44
+ function transformLazy(code, options) {
45
+ if (typeof code !== "string") {
46
+ throw new TypeError("@solidjs/compiler transformLazy() expects source code as a string");
47
+ }
48
+
49
+ const nativeOptions = validateLazyOptions(options);
50
+ const result = native.transformLazy(code, nativeOptions);
51
+ return {
52
+ code: result.code,
53
+ map: result.map ?? null
54
+ };
55
+ }
56
+
57
+ function transformLazyAsync(code, options) {
58
+ return Promise.resolve().then(() => transformLazy(code, options));
59
+ }
60
+
61
+ function transformRefresh(code, options) {
62
+ if (typeof code !== "string") {
63
+ throw new TypeError("@solidjs/compiler transformRefresh() expects source code as a string");
64
+ }
65
+
66
+ const nativeOptions = validateRefreshOptions(options);
67
+ const result = native.transformRefresh(code, nativeOptions);
68
+ return {
69
+ code: result.code,
70
+ map: result.map ?? null
71
+ };
72
+ }
73
+
74
+ function transformRefreshAsync(code, options) {
75
+ return Promise.resolve().then(() => transformRefresh(code, options));
76
+ }
77
+
78
+ const lazyOptionKeys = new Set(["filename", "sourceMap"]);
79
+
80
+ function validateLazyOptions(options) {
81
+ if (options == null) return options;
82
+ if (typeof options !== "object" || Array.isArray(options)) {
83
+ throw new TypeError("@solidjs/compiler transformLazy() expects options to be an object");
84
+ }
85
+
86
+ const nativeOptions = {};
87
+ for (const [key, value] of Object.entries(options)) {
88
+ if (!lazyOptionKeys.has(key)) {
89
+ throw new Error(`@solidjs/compiler received unknown option \`${key}\``);
90
+ }
91
+ if (key === "filename" && typeof value !== "string") {
92
+ throw new TypeError("@solidjs/compiler `filename` option must be a string");
93
+ }
94
+ if (key === "sourceMap" && typeof value !== "boolean") {
95
+ throw new TypeError("@solidjs/compiler `sourceMap` option must be boolean");
96
+ }
97
+ nativeOptions[key] = value;
98
+ }
99
+ return nativeOptions;
100
+ }
101
+
102
+ const refreshOptionKeys = new Set([
103
+ "filename",
104
+ "bundler",
105
+ "fixRender",
106
+ "granular",
107
+ "jsx",
108
+ "importSource",
109
+ "sourceMap"
110
+ ]);
111
+
112
+ const refreshBundlers = new Set(["esm", "vite", "webpack5", "rspack-esm", "standard"]);
113
+
114
+ function validateRefreshOptions(options) {
115
+ if (options == null) return options;
116
+ if (typeof options !== "object" || Array.isArray(options)) {
117
+ throw new TypeError("@solidjs/compiler transformRefresh() expects options to be an object");
118
+ }
119
+
120
+ const nativeOptions = {};
121
+ for (const [key, value] of Object.entries(options)) {
122
+ if (!refreshOptionKeys.has(key)) {
123
+ throw new Error(`@solidjs/compiler received unknown option \`${key}\``);
124
+ }
125
+ if ((key === "filename" || key === "importSource") && typeof value !== "string") {
126
+ throw new TypeError(`@solidjs/compiler \`${key}\` option must be a string`);
127
+ }
128
+ if (
129
+ (key === "fixRender" || key === "granular" || key === "sourceMap") &&
130
+ typeof value !== "boolean"
131
+ ) {
132
+ throw new TypeError(`@solidjs/compiler \`${key}\` option must be boolean`);
133
+ }
134
+ if (key === "bundler" && !refreshBundlers.has(value)) {
135
+ throw new TypeError(
136
+ '@solidjs/compiler `bundler` option must be "esm", "vite", "webpack5", "rspack-esm" or "standard"'
137
+ );
138
+ }
139
+ if (key === "jsx") {
140
+ // The Babel plugin's JSX-granularity mode (its default!) is not
141
+ // ported; only the vite-plugin-solid configuration (`jsx: false`) is.
142
+ if (value !== false) {
143
+ throw new Error(
144
+ "@solidjs/compiler transformRefresh() does not support `jsx: true` yet; pass `jsx: false`"
145
+ );
146
+ }
147
+ nativeOptions.jsx = false;
148
+ continue;
149
+ }
150
+ nativeOptions[key] = value;
151
+ }
152
+ return nativeOptions;
153
+ }
154
+
155
+ const directivesOptionKeys = new Set([
156
+ "filename",
157
+ "root",
158
+ "mode",
159
+ "env",
160
+ "directive",
161
+ "sourceMap",
162
+ "register",
163
+ "create"
164
+ ]);
165
+
166
+ function validateDirectivesOptions(options) {
167
+ if (options == null || typeof options !== "object" || Array.isArray(options)) {
168
+ throw new TypeError("@solidjs/compiler transformDirectives() expects options to be an object");
169
+ }
170
+
171
+ const nativeOptions = {};
172
+ for (const [key, value] of Object.entries(options)) {
173
+ if (!directivesOptionKeys.has(key)) {
174
+ throw new Error(`@solidjs/compiler received unknown option \`${key}\``);
175
+ }
176
+ if (key === "mode") {
177
+ if (value !== "server" && value !== "client") {
178
+ throw new TypeError('@solidjs/compiler `mode` option must be "server" or "client"');
179
+ }
180
+ }
181
+ if (key === "env") {
182
+ if (value !== "production" && value !== "development") {
183
+ throw new TypeError('@solidjs/compiler `env` option must be "production" or "development"');
184
+ }
185
+ }
186
+ if (key === "register" || key === "create") {
187
+ validateImportDefinition(key, value);
188
+ }
189
+ nativeOptions[key] = value;
190
+ }
191
+ if (typeof nativeOptions.filename !== "string") {
192
+ throw new TypeError("@solidjs/compiler transformDirectives() requires `filename`");
193
+ }
194
+ return nativeOptions;
195
+ }
196
+
197
+ function validateImportDefinition(key, value) {
198
+ if (typeof value !== "object" || value == null || Array.isArray(value)) {
199
+ throw new TypeError(`@solidjs/compiler \`${key}\` option must be an object`);
200
+ }
201
+ for (const nested of Object.keys(value)) {
202
+ if (nested !== "kind" && nested !== "name" && nested !== "source") {
203
+ throw new Error(`@solidjs/compiler received unknown \`${key}\` option \`${nested}\``);
204
+ }
205
+ }
206
+ if (typeof value.source !== "string") {
207
+ throw new TypeError(`@solidjs/compiler \`${key}.source\` must be a string`);
208
+ }
209
+ if (value.kind != null && value.kind !== "named" && value.kind !== "default") {
210
+ throw new TypeError(`@solidjs/compiler \`${key}.kind\` must be "named" or "default"`);
211
+ }
212
+ }
213
+
214
+ const nativeOptionKeys = new Set([
215
+ "filename",
216
+ "moduleName",
217
+ "generate",
218
+ "hydratable",
219
+ "dev",
220
+ "sourceMap",
221
+ "contextToCustomElements",
222
+ "delegateEvents",
223
+ "delegatedEvents",
224
+ "omitQuotes",
225
+ "omitAttributeSpacing",
226
+ "inlineStyles",
227
+ "effectWrapper",
228
+ "wrapConditionals",
229
+ "memoWrapper",
230
+ "requireImportSource",
231
+ "validate",
232
+ "staticMarker",
233
+ "omitNestedClosingTags",
234
+ "omitLastClosingTag",
235
+ "serverComponents",
236
+ "builtIns",
237
+ "renderers"
238
+ ]);
239
+
240
+ function validateOptions(code, options) {
241
+ if (options == null) return options;
242
+ if (typeof options !== "object" || Array.isArray(options)) {
243
+ throw new TypeError("@solidjs/compiler transform() expects options to be an object");
244
+ }
245
+
246
+ const nativeOptions = {};
247
+ for (const [key, value] of Object.entries(options)) {
248
+ if (key === "effectWrapper" || key === "memoWrapper") {
249
+ if (typeof value !== "string" && typeof value !== "boolean") {
250
+ throw new TypeError(
251
+ `@solidjs/compiler \`${key}\` option must be a string import name or false`
252
+ );
253
+ }
254
+ nativeOptions[key] = value;
255
+ continue;
256
+ }
257
+ if (key === "requireImportSource") {
258
+ if (value !== false && typeof value !== "string") {
259
+ throw new TypeError(
260
+ "@solidjs/compiler `requireImportSource` option must be false or a string"
261
+ );
262
+ }
263
+ if (value !== false) nativeOptions.requireImportSource = value;
264
+ continue;
265
+ }
266
+ if (key === "wrapConditionals") {
267
+ if (typeof value !== "boolean") {
268
+ throw new TypeError("@solidjs/compiler `wrapConditionals` option must be boolean");
269
+ }
270
+ nativeOptions.wrapConditionals = value;
271
+ continue;
272
+ }
273
+ if (key === "validate") {
274
+ if (typeof value !== "boolean") {
275
+ throw new TypeError("@solidjs/compiler `validate` option must be boolean");
276
+ }
277
+ nativeOptions.validate = value;
278
+ continue;
279
+ }
280
+ if (nativeOptionKeys.has(key)) {
281
+ if (key === "renderers") validateRenderers(value);
282
+ nativeOptions[key] = value;
283
+ continue;
284
+ }
285
+ throw new Error(`@solidjs/compiler received unknown option \`${key}\``);
286
+ }
287
+ return nativeOptions;
288
+ }
289
+
290
+ function validateRenderers(renderers) {
291
+ if (renderers == null) return;
292
+ if (!Array.isArray(renderers)) {
293
+ throw new TypeError("@solidjs/compiler `renderers` option must be an array");
294
+ }
295
+
296
+ for (const renderer of renderers) {
297
+ if (typeof renderer !== "object" || renderer == null || Array.isArray(renderer)) {
298
+ throw new TypeError("@solidjs/compiler renderer entries must be objects");
299
+ }
300
+ for (const key of Object.keys(renderer)) {
301
+ if (key !== "name" && key !== "moduleName" && key !== "elements") {
302
+ throw new Error(`@solidjs/compiler received unknown renderer option \`${key}\``);
303
+ }
304
+ }
305
+ if (renderer.name !== "dom") {
306
+ throw new Error(
307
+ "@solidjs/compiler dynamic renderers only support the `dom` renderer override"
308
+ );
309
+ }
310
+ }
311
+ }
312
+
313
+ function platformArchSuffix() {
314
+ const { platform, arch } = process;
315
+ if (platform === "darwin" && (arch === "x64" || arch === "arm64")) return `darwin-${arch}`;
316
+ if (platform === "linux" && (arch === "x64" || arch === "arm64")) return `linux-${arch}-gnu`;
317
+ if (platform === "win32" && arch === "x64") return "win32-x64-msvc";
318
+ return null;
319
+ }
320
+
321
+ function tryPackage(packageName) {
322
+ try {
323
+ return { binding: require(packageName) };
324
+ } catch (error) {
325
+ if (isMissingPackage(error, packageName)) return { missing: true };
326
+ return { error };
327
+ }
328
+ }
329
+
330
+ function requireBinding() {
331
+ const explicit = process.env.SOLID_COMPILER_NATIVE;
332
+ if (explicit) return require(explicit);
333
+
334
+ const forceWasi = process.env.NAPI_RS_FORCE_WASI;
335
+ if (forceWasi === "true" || forceWasi === "error") {
336
+ const wasi = requireWasi();
337
+ if (wasi) return wasi;
338
+ if (forceWasi === "error") {
339
+ throw new Error("WASI binding not found and NAPI_RS_FORCE_WASI is set to error");
340
+ }
341
+ }
342
+
343
+ let nativeError;
344
+ const suffix = platformArchSuffix();
345
+
346
+ if (suffix) {
347
+ const next = tryPackage(`@solidjs/compiler-${suffix}`);
348
+ if (next.binding) return next.binding;
349
+ if (next.error) nativeError = next.error;
350
+ }
351
+
352
+ const localCandidates = [];
353
+ if (suffix) localCandidates.push(`compiler.${suffix}.node`);
354
+ localCandidates.push("compiler.node");
355
+ for (const file of localCandidates) {
356
+ const full = path.join(__dirname, file);
357
+ if (fs.existsSync(full)) {
358
+ try {
359
+ return require(full);
360
+ } catch (error) {
361
+ nativeError = error;
362
+ break;
363
+ }
364
+ }
365
+ }
366
+
367
+ const wasi = requireWasi();
368
+ if (wasi) return wasi;
369
+
370
+ if (nativeError) {
371
+ nativeError.message +=
372
+ "\nThe native binding could not be loaded and the optional " +
373
+ "@solidjs/compiler-wasm32-wasi fallback is not installed.";
374
+ throw nativeError;
375
+ }
376
+
377
+ throw new Error(
378
+ `Could not find an @solidjs/compiler binding for ${process.platform}-${process.arch}` +
379
+ (suffix
380
+ ? ` (expected @solidjs/compiler-${suffix}, @solidjs/compiler-wasm32-wasi, or a local build)`
381
+ : " (no prebuilt binary is published for this platform)") +
382
+ ". Install with WASM support or run `pnpm run build` in packages/compiler."
383
+ );
384
+ }
385
+
386
+ function requireWasi() {
387
+ const next = tryPackage("@solidjs/compiler-wasm32-wasi");
388
+ if (next.binding) return next.binding;
389
+ if (next.error) throw next.error;
390
+
391
+ const localWasi = path.join(__dirname, "compiler.wasi.cjs");
392
+ if (fs.existsSync(localWasi)) return require(localWasi);
393
+ return null;
394
+ }
395
+
396
+ function isMissingPackage(error, packageName) {
397
+ return (
398
+ error &&
399
+ error.code === "MODULE_NOT_FOUND" &&
400
+ typeof error.message === "string" &&
401
+ error.message.includes(`'${packageName}'`)
402
+ );
403
+ }
404
+
405
+ module.exports = {
406
+ transform,
407
+ transformAsync,
408
+ transformDirectives,
409
+ transformDirectivesAsync,
410
+ transformLazy,
411
+ transformLazyAsync,
412
+ transformRefresh,
413
+ transformRefreshAsync
414
+ };
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@solidjs/compiler",
3
+ "description": "Solid's native Oxc JSX compiler",
4
+ "version": "2.0.0-rc.2",
5
+ "author": "Ryan Carniato",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/solidjs/solid.git",
10
+ "directory": "packages/compiler"
11
+ },
12
+ "main": "index.js",
13
+ "types": "types.d.ts",
14
+ "sideEffects": false,
15
+ "exports": {
16
+ ".": {
17
+ "types": "./types.d.ts",
18
+ "require": "./index.js",
19
+ "default": "./index.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "index.js",
24
+ "types.d.ts",
25
+ "README.md"
26
+ ],
27
+ "scripts": {
28
+ "build": "napi build --release --strip --manifest-path ./Cargo.toml",
29
+ "build:debug": "napi build --manifest-path ./Cargo.toml",
30
+ "bench": "pnpm run build && node scripts/bench.mjs",
31
+ "lint": "cargo clippy --manifest-path ./Cargo.toml -- -D warnings",
32
+ "test": "pnpm run test:rust && pnpm run build:debug && vitest run",
33
+ "test:rust": "cargo test --manifest-path ./Cargo.toml && cargo test --manifest-path ./Cargo.toml --no-default-features",
34
+ "artifacts": "napi artifacts",
35
+ "napi:version": "napi version && node ./sync-optional-deps.mjs",
36
+ "create-npm-dirs": "napi create-npm-dirs"
37
+ },
38
+ "napi": {
39
+ "binaryName": "compiler",
40
+ "targets": [
41
+ "x86_64-apple-darwin",
42
+ "aarch64-apple-darwin",
43
+ "x86_64-unknown-linux-gnu",
44
+ "aarch64-unknown-linux-gnu",
45
+ "x86_64-pc-windows-msvc",
46
+ "wasm32-wasip1-threads"
47
+ ],
48
+ "wasm": {
49
+ "browser": {
50
+ "fs": false,
51
+ "asyncInit": false,
52
+ "buffer": false,
53
+ "errorEvent": true
54
+ }
55
+ }
56
+ },
57
+ "devDependencies": {
58
+ "@emnapi/core": "^1.11.3",
59
+ "@emnapi/runtime": "^1.11.3",
60
+ "@napi-rs/cli": "^3.7.2",
61
+ "@napi-rs/wasm-runtime": "^1.1.6",
62
+ "emnapi": "^1.11.3"
63
+ },
64
+ "optionalDependencies": {
65
+ "@solidjs/compiler-darwin-x64": "2.0.0-rc.2",
66
+ "@solidjs/compiler-darwin-arm64": "2.0.0-rc.2",
67
+ "@solidjs/compiler-linux-x64-gnu": "2.0.0-rc.2",
68
+ "@solidjs/compiler-linux-arm64-gnu": "2.0.0-rc.2",
69
+ "@solidjs/compiler-win32-x64-msvc": "2.0.0-rc.2",
70
+ "@solidjs/compiler-wasm32-wasi": "2.0.0-rc.2"
71
+ }
72
+ }
package/types.d.ts ADDED
@@ -0,0 +1,174 @@
1
+ export interface TransformOptions {
2
+ filename?: string;
3
+ /** Default `"@solidjs/web"`. */
4
+ moduleName?: string;
5
+ generate?: "dom" | "ssr" | "universal" | "dynamic";
6
+ hydratable?: boolean;
7
+ dev?: boolean;
8
+ sourceMap?: boolean;
9
+ contextToCustomElements?: boolean;
10
+ delegateEvents?: boolean;
11
+ delegatedEvents?: string[];
12
+ omitQuotes?: boolean;
13
+ omitAttributeSpacing?: boolean;
14
+ inlineStyles?: boolean;
15
+ effectWrapper?: "effect" | false;
16
+ wrapConditionals?: boolean;
17
+ memoWrapper?: "memo" | false;
18
+ staticMarker?: string;
19
+ validate?: boolean;
20
+ omitNestedClosingTags?: boolean;
21
+ omitLastClosingTag?: boolean;
22
+ serverComponents?: boolean;
23
+ /** Default `["For", "Show", "Switch", "Match", "Loading", "Reveal", "Portal", "Repeat", "Dynamic", "Errored"]`. */
24
+ builtIns?: string[];
25
+ requireImportSource?: false | string;
26
+ renderers?: RendererOption[];
27
+ }
28
+
29
+ export interface RendererOption {
30
+ name: string;
31
+ moduleName?: string;
32
+ elements: string[];
33
+ }
34
+
35
+ export interface TransformResult {
36
+ code: string;
37
+ map?: string | null;
38
+ }
39
+
40
+ export function transform(code: string, options?: TransformOptions | null): TransformResult;
41
+ export function transformAsync(
42
+ code: string,
43
+ options?: TransformOptions | null
44
+ ): Promise<TransformResult>;
45
+
46
+ export interface DirectiveImportDefinition {
47
+ kind?: "named" | "default";
48
+ name?: string;
49
+ source: string;
50
+ }
51
+
52
+ /**
53
+ * Options for the experimental `"use server"` directive pass. Applies to
54
+ * plain `.js`/`.ts` modules as well as JSX/TSX.
55
+ */
56
+ export interface TransformDirectivesOptions {
57
+ /** Required — function IDs hash the root-relative file path. */
58
+ filename: string;
59
+ /** Project root for ID hashing. Defaults to the working directory. */
60
+ root?: string;
61
+ /**
62
+ * `"server"` keeps the module and registers extracted functions;
63
+ * `"client"` replaces them with reference proxies and strips server-only
64
+ * code.
65
+ */
66
+ mode: "server" | "client";
67
+ /** `"development"` appends function names to generated IDs. */
68
+ env?: "production" | "development";
69
+ /** @default "use server" */
70
+ directive?: string;
71
+ sourceMap?: boolean;
72
+ /** Runtime import for `registerServerReference` (server output). */
73
+ register?: DirectiveImportDefinition;
74
+ /** Runtime import for `createServerReference` (both outputs). */
75
+ create?: DirectiveImportDefinition;
76
+ }
77
+
78
+ /** One extracted server function, for building a bundler manifest. */
79
+ export interface ServerFunctionMeta {
80
+ /** The wire ID (`<hash>-<count>[-<name>]`). */
81
+ id: string;
82
+ name: string;
83
+ /** Export names bound to this function (module-level directives only). */
84
+ exports: string[];
85
+ }
86
+
87
+ export interface TransformDirectivesResult {
88
+ code: string;
89
+ map?: string | null;
90
+ /** False when the module contained no matching directive. */
91
+ valid: boolean;
92
+ functions: ServerFunctionMeta[];
93
+ }
94
+
95
+ export function transformDirectives(
96
+ code: string,
97
+ options: TransformDirectivesOptions
98
+ ): TransformDirectivesResult;
99
+ export function transformDirectivesAsync(
100
+ code: string,
101
+ options: TransformDirectivesOptions
102
+ ): Promise<TransformDirectivesResult>;
103
+
104
+ /**
105
+ * Options for the experimental `lazy()` module-URL pass (ported from
106
+ * vite-plugin-solid's `lazy-module-url` Babel plugin).
107
+ */
108
+ export interface TransformLazyOptions {
109
+ /**
110
+ * Mirrors the Babel plugin: without a filename the pass is a no-op (the
111
+ * emitted placeholder is only useful to a bundler resolving relative to a
112
+ * module id).
113
+ */
114
+ filename?: string;
115
+ sourceMap?: boolean;
116
+ }
117
+
118
+ export function transformLazy(code: string, options?: TransformLazyOptions | null): TransformResult;
119
+ export function transformLazyAsync(
120
+ code: string,
121
+ options?: TransformLazyOptions | null
122
+ ): Promise<TransformResult>;
123
+
124
+ /**
125
+ * Options for the experimental solid-refresh HMR pass (ported from the
126
+ * `solid-refresh` Babel plugin, `jsx: false` mode). Dev-only.
127
+ */
128
+ export interface TransformRefreshOptions {
129
+ /**
130
+ * Used for `location` metadata (cwd-relative, matching the Babel plugin)
131
+ * and to pick the parser dialect. Without it no locations are emitted.
132
+ */
133
+ filename?: string;
134
+ /**
135
+ * Selects the HMR API: `import.meta.hot` (esm/vite),
136
+ * `import.meta.webpackHot` (webpack5/rspack-esm) or `module.hot`
137
+ * (standard).
138
+ * @default "standard"
139
+ */
140
+ bundler?: "esm" | "vite" | "webpack5" | "rspack-esm" | "standard";
141
+ /**
142
+ * Wrap top-level `render()`/`hydrate()` calls (imported from
143
+ * `@solidjs/web`) with `hot.dispose` cleanup.
144
+ * @default true
145
+ */
146
+ fixRender?: boolean;
147
+ /**
148
+ * Emit per-component `signature`/`dependencies` metadata for granular HMR.
149
+ * @default true
150
+ */
151
+ granular?: boolean;
152
+ /**
153
+ * The Babel plugin's JSX-granularity mode is not ported; only `false` is
154
+ * accepted (what vite-plugin-solid passes).
155
+ */
156
+ jsx?: false;
157
+ /**
158
+ * Module the runtime helpers (`$$registry`, `$$component`, `$$refresh`,
159
+ * `$$decline`) are imported from. The dev-only `solid-js/refresh` entry
160
+ * exposes the same frozen ABI.
161
+ * @default "solid-refresh"
162
+ */
163
+ importSource?: string;
164
+ sourceMap?: boolean;
165
+ }
166
+
167
+ export function transformRefresh(
168
+ code: string,
169
+ options?: TransformRefreshOptions | null
170
+ ): TransformResult;
171
+ export function transformRefreshAsync(
172
+ code: string,
173
+ options?: TransformRefreshOptions | null
174
+ ): Promise<TransformResult>;