@solidjs/compiler 2.0.0-rc.5 → 2.0.0-rc.6
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 +39 -6
- package/index.js +46 -1
- package/package.json +8 -8
- package/types.d.ts +54 -0
package/README.md
CHANGED
|
@@ -78,14 +78,38 @@ const result = transform(source, {
|
|
|
78
78
|
});
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
### TSRX (experimental)
|
|
82
|
+
|
|
83
|
+
TSRX (TypeScript Render Extensions) is a syntax for declarative UI whose constructs (`@if`/`@else`, `@for … @empty`, `@switch`/`@case`, `@try`/`@catch`/`@pending`, and `@{}` statement containers) desugar to the Solid control-flow components. `.tsrx` filenames route through the TSRX frontend automatically and compile to the same output as `@solidjs/babel-plugin`'s TSRX support, byte for byte.
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
const result = transform(tsrxSource, { filename: "App.tsrx" });
|
|
87
|
+
// TSRX <style> blocks are extracted alongside the JavaScript:
|
|
88
|
+
result.css;
|
|
89
|
+
result.cssHash;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Routing follows the filename by default (`syntax: "auto"`); pass `syntax: "tsrx"` or `syntax: "jsx"` to force a frontend regardless of filename. No extra install is needed — the shipped binaries include the frontend (Rust embedders can disable the default `tsrx` cargo feature).
|
|
93
|
+
|
|
94
|
+
Scoped `<style>` blocks are compile-time only. The compiler removes the style element, adds its `tsrx-<hash>` class to matching native and dynamic elements, scopes and prunes the CSS, and returns the stylesheet in `css` with its scope identifier in `cssHash`. Style expressions produce class-map objects, `<style ref={styles}>` initializes the requested class map, and `:global(...)` opts individual selectors out of scoping. A bundler integration must emit the returned CSS; the core compiler does not inject a runtime style helper.
|
|
95
|
+
|
|
96
|
+
Solid rejects authored TSRX lazy destructuring (`&{ … }` / `&[ … ]`). Keep accessor calls and reactive property reads explicit in Solid source.
|
|
97
|
+
|
|
98
|
+
Destructured bindings in keyed `@for` loops and `@catch` clauses stay deferred against Solid's item and error accessors, including nested patterns, defaults, computed keys, and rest.
|
|
99
|
+
|
|
100
|
+
The frontend uses the community [oxc-tsrx](https://github.com/tsrx-org/oxc) parser at a pinned revision. Statement containers can be used as function bodies, statements, expressions (`const x = @{ … }`), and JSX children or expression containers. See `documentation/tsrx/frontend-notes.md` in the repository for the full frontend notes.
|
|
101
|
+
|
|
102
|
+
`projectTsrxForTypecheck(source, { filename })` is an experimental compiler-owned projection for editor and typecheck integrations. It returns independently typecheckable post-rewrite TSX without running the DOM/SSR/universal transforms, injecting collision-safe imports for generated Solid control-flow and dynamic-element helpers. The tooling-only path recovers common incomplete editor snapshots while normal compilation remains strict. The result also includes an authored `.tsrx` source map, exact equal-text `mappings`, processed `css`/`cssHash`, and parser-authored embedded CSS/raw-script regions. Mapping and embedded offsets use JavaScript UTF-16 string coordinates. The ranges deliberately omit generated-only text; host adapters such as Volar attach feature capabilities to them.
|
|
103
|
+
|
|
81
104
|
### Source maps
|
|
82
105
|
|
|
83
|
-
Pass `sourceMap: true` to receive a JSON source map string in `result.map`.
|
|
106
|
+
Pass `sourceMap: true` to receive a JSON source map string in `result.map`. For TSRX, the compiler composes Oxc's generated-JavaScript map through the internal TSX text projection, returning the original `.tsrx` filename and source in `sources` and `sourcesContent`. Authored expressions and lazy/accessor rewrites map back to their TSRX locations; projection-only scaffolding remains explicitly unmapped rather than being attributed to nearby syntax.
|
|
84
107
|
|
|
85
108
|
### Options
|
|
86
109
|
|
|
87
110
|
- `filename`
|
|
88
111
|
- `moduleName` (default `"@solidjs/web"`)
|
|
112
|
+
- `syntax`: `"auto"`, `"jsx"`, or `"tsrx"` (default `"auto"` — routes `.tsrx` filenames through the TSRX frontend)
|
|
89
113
|
- `generate`: `"dom"`, `"ssr"`, `"universal"`, or `"dynamic"` (default `"dom"`)
|
|
90
114
|
- `hydratable`
|
|
91
115
|
- `dev`
|
|
@@ -110,7 +134,7 @@ Pass `sourceMap: true` to receive a JSON source map string in `result.map`.
|
|
|
110
134
|
|
|
111
135
|
### Server function directives (experimental)
|
|
112
136
|
|
|
113
|
-
`transformDirectives(code, options)` is a second pass for `"use server"`. It
|
|
137
|
+
`transformDirectives(code, options)` is a second pass for `"use server"`. It accepts ordinary JavaScript/TypeScript, including JSX/TSX. For a `.tsrx` module, run `transform()` first, then pass its generated code to `transformDirectives()` with the same original `.tsrx` filename so function IDs use the manifest path. `transformDirectives()` does not parse raw TSRX syntax itself.
|
|
114
138
|
|
|
115
139
|
```js
|
|
116
140
|
const { transformDirectives } = require("@solidjs/compiler");
|
|
@@ -133,16 +157,25 @@ The runtime module defaults to `@solidjs/web/server-functions`. Function IDs use
|
|
|
133
157
|
The crate also exposes a host-independent Rust API. The crate name is `solidjs-compiler`; the Node `transform()` delegates to the same core.
|
|
134
158
|
|
|
135
159
|
```rust
|
|
136
|
-
use solidjs_compiler::{
|
|
160
|
+
use solidjs_compiler::{
|
|
161
|
+
compile, project_tsrx_for_typecheck, CompileOptions,
|
|
162
|
+
TsrxTypecheckProjectionOptions,
|
|
163
|
+
};
|
|
137
164
|
|
|
138
165
|
let output = compile(
|
|
139
166
|
"const view = <div>{name()}</div>;",
|
|
140
167
|
&CompileOptions::default(),
|
|
141
168
|
)?;
|
|
169
|
+
|
|
170
|
+
let tsrx_source = "export function View() @{ <div /> }";
|
|
171
|
+
let virtual_tsx =
|
|
172
|
+
project_tsrx_for_typecheck(tsrx_source, &TsrxTypecheckProjectionOptions::default())?;
|
|
142
173
|
```
|
|
143
174
|
|
|
144
175
|
`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
176
|
|
|
177
|
+
The unstable Rust typecheck projection reports embedded ranges in authored UTF-8 bytes. The N-API adapter converts those ranges to UTF-16 code units for JavaScript tooling.
|
|
178
|
+
|
|
146
179
|
> **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
180
|
|
|
148
181
|
## Performance
|
|
@@ -151,9 +184,9 @@ Compared against `@solidjs/babel-plugin` compiling identical sources under ident
|
|
|
151
184
|
|
|
152
185
|
| Workload | babel-plugin | compiler | Speedup |
|
|
153
186
|
| ----------------------------------------------- | -----------: | -------: | ------: |
|
|
154
|
-
| Fixture corpus (88 files, 175 KB, all 10 modes) |
|
|
155
|
-
| 129 KB single module |
|
|
156
|
-
| 1 MB single module |
|
|
187
|
+
| Fixture corpus (88 files, 175 KB, all 10 modes) | 440 ms | 19 ms | 23x |
|
|
188
|
+
| 129 KB single module | 545 ms | 9.4 ms | 58x |
|
|
189
|
+
| 1 MB single module | 24,975 ms | 70 ms | 355x |
|
|
157
190
|
|
|
158
191
|
Native throughput stays roughly flat as input grows, while Babel's per-file cost grows super-linearly.
|
|
159
192
|
|
package/index.js
CHANGED
|
@@ -12,16 +12,60 @@ function transform(code, options) {
|
|
|
12
12
|
|
|
13
13
|
const nativeOptions = validateOptions(code, options);
|
|
14
14
|
const result = native.transform(code, nativeOptions);
|
|
15
|
-
|
|
15
|
+
const output = {
|
|
16
16
|
code: result.code,
|
|
17
17
|
map: result.map ?? null
|
|
18
18
|
};
|
|
19
|
+
// Preserve the established JSX result shape. Native TSRX transforms always
|
|
20
|
+
// return a CSS string (including `""` when no styles are present), which
|
|
21
|
+
// makes the sidecar fields a route-specific extension.
|
|
22
|
+
if (result.css != null) {
|
|
23
|
+
output.css = result.css;
|
|
24
|
+
output.cssHash = result.cssHash ?? null;
|
|
25
|
+
}
|
|
26
|
+
return output;
|
|
19
27
|
}
|
|
20
28
|
|
|
21
29
|
function transformAsync(code, options) {
|
|
22
30
|
return Promise.resolve().then(() => transform(code, options));
|
|
23
31
|
}
|
|
24
32
|
|
|
33
|
+
function projectTsrxForTypecheck(code, options) {
|
|
34
|
+
if (typeof code !== "string") {
|
|
35
|
+
throw new TypeError(
|
|
36
|
+
"@solidjs/compiler projectTsrxForTypecheck() expects source code as a string"
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
const nativeOptions = validateTypecheckProjectionOptions(options);
|
|
40
|
+
const result = native.projectTsrxForTypecheck(code, nativeOptions);
|
|
41
|
+
return {
|
|
42
|
+
code: result.code,
|
|
43
|
+
map: result.map,
|
|
44
|
+
mappings: result.mappings,
|
|
45
|
+
css: result.css,
|
|
46
|
+
cssHash: result.cssHash ?? null,
|
|
47
|
+
embeddedRegions: result.embeddedRegions
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function validateTypecheckProjectionOptions(options) {
|
|
52
|
+
if (options == null) return options;
|
|
53
|
+
if (typeof options !== "object" || Array.isArray(options)) {
|
|
54
|
+
throw new TypeError(
|
|
55
|
+
"@solidjs/compiler projectTsrxForTypecheck() expects options to be an object"
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
for (const key of Object.keys(options)) {
|
|
59
|
+
if (key !== "filename") {
|
|
60
|
+
throw new Error(`@solidjs/compiler received unknown option \`${key}\``);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (options.filename !== undefined && typeof options.filename !== "string") {
|
|
64
|
+
throw new TypeError("@solidjs/compiler `filename` option must be a string");
|
|
65
|
+
}
|
|
66
|
+
return options;
|
|
67
|
+
}
|
|
68
|
+
|
|
25
69
|
function transformDirectives(code, options) {
|
|
26
70
|
if (typeof code !== "string") {
|
|
27
71
|
throw new TypeError("@solidjs/compiler transformDirectives() expects source code as a string");
|
|
@@ -427,6 +471,7 @@ function isMissingPackage(error, packageName) {
|
|
|
427
471
|
module.exports = {
|
|
428
472
|
transform,
|
|
429
473
|
transformAsync,
|
|
474
|
+
projectTsrxForTypecheck,
|
|
430
475
|
transformDirectives,
|
|
431
476
|
transformDirectivesAsync,
|
|
432
477
|
transformLazy,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidjs/compiler",
|
|
3
3
|
"description": "Solid's native Oxc JSX compiler",
|
|
4
|
-
"version": "2.0.0-rc.
|
|
4
|
+
"version": "2.0.0-rc.6",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"bench": "pnpm run build && node scripts/bench.mjs",
|
|
31
31
|
"lint": "cargo clippy --manifest-path ./Cargo.toml -- -D warnings",
|
|
32
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",
|
|
33
|
+
"test:rust": "cargo test --manifest-path ./Cargo.toml && cargo test --manifest-path ./Cargo.toml --no-default-features && cargo test --manifest-path ./Cargo.toml --no-default-features --features tsrx",
|
|
34
34
|
"artifacts": "napi artifacts",
|
|
35
35
|
"napi:version": "napi version && node ./sync-optional-deps.mjs",
|
|
36
36
|
"create-npm-dirs": "napi create-npm-dirs"
|
|
@@ -62,11 +62,11 @@
|
|
|
62
62
|
"emnapi": "^1.11.3"
|
|
63
63
|
},
|
|
64
64
|
"optionalDependencies": {
|
|
65
|
-
"@solidjs/compiler-darwin-x64": "2.0.0-rc.
|
|
66
|
-
"@solidjs/compiler-darwin-arm64": "2.0.0-rc.
|
|
67
|
-
"@solidjs/compiler-linux-x64-gnu": "2.0.0-rc.
|
|
68
|
-
"@solidjs/compiler-linux-arm64-gnu": "2.0.0-rc.
|
|
69
|
-
"@solidjs/compiler-win32-x64-msvc": "2.0.0-rc.
|
|
70
|
-
"@solidjs/compiler-wasm32-wasi": "2.0.0-rc.
|
|
65
|
+
"@solidjs/compiler-darwin-x64": "2.0.0-rc.6",
|
|
66
|
+
"@solidjs/compiler-darwin-arm64": "2.0.0-rc.6",
|
|
67
|
+
"@solidjs/compiler-linux-x64-gnu": "2.0.0-rc.6",
|
|
68
|
+
"@solidjs/compiler-linux-arm64-gnu": "2.0.0-rc.6",
|
|
69
|
+
"@solidjs/compiler-win32-x64-msvc": "2.0.0-rc.6",
|
|
70
|
+
"@solidjs/compiler-wasm32-wasi": "2.0.0-rc.6"
|
|
71
71
|
}
|
|
72
72
|
}
|
package/types.d.ts
CHANGED
|
@@ -2,6 +2,13 @@ export interface TransformOptions {
|
|
|
2
2
|
filename?: string;
|
|
3
3
|
/** Default `"@solidjs/web"`. */
|
|
4
4
|
moduleName?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Source syntax frontend, matching `@solidjs/babel-plugin`: `"auto"`
|
|
7
|
+
* (default) routes `.tsrx` filenames through the TSRX frontend and
|
|
8
|
+
* everything else through standard JSX; `"tsrx"` and `"jsx"` force a
|
|
9
|
+
* frontend regardless of filename. TSRX support is experimental.
|
|
10
|
+
*/
|
|
11
|
+
syntax?: "auto" | "jsx" | "tsrx";
|
|
5
12
|
generate?: "dom" | "ssr" | "universal" | "dynamic";
|
|
6
13
|
hydratable?: boolean;
|
|
7
14
|
dev?: boolean;
|
|
@@ -44,6 +51,10 @@ export interface RendererOption {
|
|
|
44
51
|
export interface TransformResult {
|
|
45
52
|
code: string;
|
|
46
53
|
map?: string | null;
|
|
54
|
+
/** Extracted scoped CSS for TSRX sources. */
|
|
55
|
+
css?: string | null;
|
|
56
|
+
/** Space-separated TSRX scope hashes. */
|
|
57
|
+
cssHash?: string | null;
|
|
47
58
|
}
|
|
48
59
|
|
|
49
60
|
export function transform(code: string, options?: TransformOptions | null): TransformResult;
|
|
@@ -52,6 +63,49 @@ export function transformAsync(
|
|
|
52
63
|
options?: TransformOptions | null
|
|
53
64
|
): Promise<TransformResult>;
|
|
54
65
|
|
|
66
|
+
export interface ProjectTsrxForTypecheckOptions {
|
|
67
|
+
filename?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface TsrxTypecheckEmbeddedRegion {
|
|
71
|
+
kind: "css" | "script";
|
|
72
|
+
/** Authored JavaScript string offset in UTF-16 code units. */
|
|
73
|
+
start: number;
|
|
74
|
+
/** Authored JavaScript string offset in UTF-16 code units. */
|
|
75
|
+
end: number;
|
|
76
|
+
content: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface TsrxTypecheckMapping {
|
|
80
|
+
/** Authored JavaScript string offset in UTF-16 code units. */
|
|
81
|
+
sourceStart: number;
|
|
82
|
+
/** Generated JavaScript string offset in UTF-16 code units. */
|
|
83
|
+
generatedStart: number;
|
|
84
|
+
sourceLength: number;
|
|
85
|
+
generatedLength: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface TsrxTypecheckProjectionResult {
|
|
89
|
+
/** Valid post-semantic-rewrite TypeScript/TSX. */
|
|
90
|
+
code: string;
|
|
91
|
+
/** JSON source map from virtual TSX back to the authored `.tsrx` source. */
|
|
92
|
+
map: string;
|
|
93
|
+
/** Exact equal-text ranges suitable for editor feature mappings. */
|
|
94
|
+
mappings: TsrxTypecheckMapping[];
|
|
95
|
+
css: string;
|
|
96
|
+
cssHash: string | null;
|
|
97
|
+
embeddedRegions: TsrxTypecheckEmbeddedRegion[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Experimental compiler-owned TSRX projection for typechecking and editor
|
|
102
|
+
* tooling. This API is host-independent and does not run a runtime renderer.
|
|
103
|
+
*/
|
|
104
|
+
export function projectTsrxForTypecheck(
|
|
105
|
+
code: string,
|
|
106
|
+
options?: ProjectTsrxForTypecheckOptions | null
|
|
107
|
+
): TsrxTypecheckProjectionResult;
|
|
108
|
+
|
|
55
109
|
export interface DirectiveImportDefinition {
|
|
56
110
|
kind?: "named" | "default";
|
|
57
111
|
name?: string;
|