@solidjs/compiler 2.0.0-rc.15 → 2.0.0-rc.16

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 CHANGED
@@ -113,7 +113,8 @@ Pass `sourceMap: true` to receive a JSON source map string in `result.map`. For
113
113
  - `generate`: `"dom"`, `"ssr"`, `"universal"`, or `"dynamic"` (default `"dom"`)
114
114
  - `hydratable`
115
115
  - `dev`
116
- - `sourceNames` (`boolean | { components?: boolean; bindings?: boolean }`, default follows `dev`): names as written in source, carried into output so dev/observe runtimes can label the reactive graph after minification. Unset, every kind is on when `dev: true` and off otherwise; `true`/`false` sets every kind (`sourceNames: false` opts a dev build out); the object form picks, and each kind it leaves unspecified follows `dev`. Production output (`dev: false`) is byte-identical with the option set or unset. Same shape and defaults as `@solidjs/babel-plugin`'s option. `components` emits the source tag name as `createComponent`'s third argument (`createComponent(Home, props, "Home")`) — DOM and SSR output (SSR keeps the `createComponent` call it otherwise inlines to `Comp(props)`); not universal or dynamic. `bindings` names every compiled binding effect by what it writes — `effect(…, { name: "span.textContent" })`, a hole `insert(el, v, undefined, undefined, { name: "div.children" })`, a spread `spread(el, props, false, undefined, "div")` (labelled `div.spread` / `div.children` by the runtime) — DOM output only. The production runtimes ignore the names. These are the JSX-level kinds only: naming the primitives themselves is the separate `transformSourceNames` pass below, which the build tool runs on every module independently of the JSX compiler
116
+ - `root` (`string`, default the working directory): the project root `sourceNames.locations` paths (and `transformSourceNames`'s `loc`) are made relative to — the same meaning as `transformDirectives`'s `root`.
117
+ - `sourceNames` (`boolean | { components?: boolean; bindings?: boolean; locations?: boolean }`, default follows `dev`): names as written in source, carried into output so dev/observe runtimes can label the reactive graph after minification. Unset, every kind is on when `dev: true` and off otherwise; `true`/`false` sets every kind (`sourceNames: false` opts a dev build out); the object form picks, and each kind it leaves unspecified follows `dev`. Production output (`dev: false`) is byte-identical with the option set or unset. Same shape and defaults as `@solidjs/babel-plugin`'s option. `components` emits the source tag name as `createComponent`'s third argument (`createComponent(Home, props, "Home")`) — DOM and SSR output (SSR keeps the `createComponent` call it otherwise inlines to `Comp(props)`); not universal or dynamic. `bindings` names every compiled binding effect by what it writes — `effect(…, { name: "span.textContent" })`, a hole `insert(el, v, undefined, undefined, { name: "div.children" })`, a spread `spread(el, props, false, undefined, "div")` (labelled `div.spread` / `div.children` by the runtime) — DOM output only. `locations` adds the source position beside each name the other two kinds emit, as `<path>:<line>:<column>` with the path relative to `root` (posix separators, `..` when the file is outside the root) and the column 1-based (the stack-trace and editor convention, so `http://localhost:5173/src/App.tsx:18:3` links to the right place): `createComponent(Home, props, "Home", "src/App.tsx:12:5")` — the start of the opening element — and `loc` right after `name` in a binding's options, `effect(…, { name: "div.class", loc: "src/App.tsx:14:7" })` — the attribute's start, a hole's `{`, a spread's `{...props}` (a spread's location rides as one more positional string after the tag). Nothing is emitted without a `filename`. The production runtimes ignore the names. These are the JSX-level kinds only: naming the primitives themselves is the separate `transformSourceNames` pass below, which the build tool runs on every module independently of the JSX compiler
117
118
  - `sourceMap`
118
119
  - `contextToCustomElements` (default `true`)
119
120
  - `delegateEvents`
@@ -130,7 +131,6 @@ Pass `sourceMap: true` to receive a JSON source map string in `result.map`. For
130
131
  - `omitLastClosingTag`
131
132
  - `builtIns` (default `["For", "Show", "Switch", "Match", "Loading", "Reveal", "Portal", "Repeat", "Dynamic", "Errored"]`)
132
133
  - `requireImportSource`
133
- - `serverComponents`
134
134
  - `hoistProps` (default `true`; SSR only)
135
135
  - `renderers`
136
136
 
@@ -162,7 +162,7 @@ The runtime module defaults to `@solidjs/web/server-functions`. Function IDs are
162
162
 
163
163
  ### Source names for primitives
164
164
 
165
- `transformSourceNames(code, { filename?, sourceMap? })` is the pass behind `@solidjs/vite-plugin`'s `sourceNames.primitives` option: it names reactive primitives after the identifier they are declared as, so the dev and observe runtimes label graph nodes `count` / `doubled` / `todos.title` instead of `signal` / `computed` / `store.title`. It is plain JavaScript in and out (JSX passes through untouched), which is why it is its own pass rather than a `transform()` option — primitives live in `.ts`/`.js` modules as much as in components. This standalone pass is the single owner of primitive naming: the build tool runs it on every module — `.ts`, `.js`, and JSX files alike — independently of which JSX compiler (this one or `@solidjs/babel-plugin`) handles the file's JSX, so there is no Babel counterpart and `transform()`'s `sourceNames` covers only the JSX-level kinds. `@solidjs/vite-plugin` (solid-vite-plugin #371, `solid: { sourceNames }`) runs it ahead of the JSX transform for the dev and `observe` postures.
165
+ `transformSourceNames(code, { filename?, locations?, root?, sourceMap? })` is the pass behind `@solidjs/vite-plugin`'s `sourceNames.primitives` option: it names reactive primitives after the identifier they are declared as, so the dev and observe runtimes label graph nodes `count` / `doubled` / `todos.title` instead of `signal` / `computed` / `store.title`. With `locations` (default `true` — the pass only runs for the dev and observe postures) and a `filename`, the options literal also carries the call's position right after the name, `createSignal(0, { name: "count", loc: "src/store.ts:3:22" })` (`filename` relative to `root`, column 1-based); an explicit `name` is kept and `loc` still added, an explicit `loc` is never overridden. It is plain JavaScript in and out (JSX passes through untouched), which is why it is its own pass rather than a `transform()` option — primitives live in `.ts`/`.js` modules as much as in components. This standalone pass is the single owner of primitive naming: the build tool runs it on every module — `.ts`, `.js`, and JSX files alike — independently of which JSX compiler (this one or `@solidjs/babel-plugin`) handles the file's JSX, so there is no Babel counterpart and `transform()`'s `sourceNames` covers only the JSX-level kinds. `@solidjs/vite-plugin` (solid-vite-plugin #371, `solid: { sourceNames }`) runs it ahead of the JSX transform for the dev and `observe` postures.
166
166
 
167
167
  ```js
168
168
  const [count, setCount] = createSignal(0); // createSignal(0, { name: "count" })
package/index.js CHANGED
@@ -10,7 +10,7 @@ function transform(code, options) {
10
10
  throw new TypeError("@solidjs/compiler transform() expects source code as a string");
11
11
  }
12
12
 
13
- const nativeOptions = validateOptions(code, options);
13
+ const nativeOptions = hostRoot(validateOptions(code, options));
14
14
  const result = native.transform(code, nativeOptions);
15
15
  const output = {
16
16
  code: result.code,
@@ -71,7 +71,7 @@ function transformDirectives(code, options) {
71
71
  throw new TypeError("@solidjs/compiler transformDirectives() expects source code as a string");
72
72
  }
73
73
 
74
- const nativeOptions = validateDirectivesOptions(options);
74
+ const nativeOptions = hostRoot(validateDirectivesOptions(options));
75
75
  const result = native.transformDirectives(code, nativeOptions);
76
76
  return {
77
77
  code: result.code,
@@ -124,7 +124,7 @@ function transformSourceNames(code, options) {
124
124
  throw new TypeError("@solidjs/compiler transformSourceNames() expects source code as a string");
125
125
  }
126
126
 
127
- const nativeOptions = validateSourceNamesOptions(options);
127
+ const nativeOptions = hostRoot(validateSourceNamesOptions(options));
128
128
  const result = native.transformSourceNames(code, nativeOptions);
129
129
  return {
130
130
  code: result.code,
@@ -136,7 +136,7 @@ function transformSourceNamesAsync(code, options) {
136
136
  return Promise.resolve().then(() => transformSourceNames(code, options));
137
137
  }
138
138
 
139
- const sourceNamesOptionKeys = new Set(["filename", "sourceMap"]);
139
+ const sourceNamesOptionKeys = new Set(["filename", "locations", "root", "sourceMap"]);
140
140
 
141
141
  function validateSourceNamesOptions(options) {
142
142
  if (options == null) return options;
@@ -149,11 +149,11 @@ function validateSourceNamesOptions(options) {
149
149
  if (!sourceNamesOptionKeys.has(key)) {
150
150
  throw new Error(`@solidjs/compiler received unknown option \`${key}\``);
151
151
  }
152
- if (key === "filename" && typeof value !== "string") {
153
- throw new TypeError("@solidjs/compiler `filename` option must be a string");
152
+ if ((key === "filename" || key === "root") && typeof value !== "string") {
153
+ throw new TypeError(`@solidjs/compiler \`${key}\` option must be a string`);
154
154
  }
155
- if (key === "sourceMap" && typeof value !== "boolean") {
156
- throw new TypeError("@solidjs/compiler `sourceMap` option must be boolean");
155
+ if ((key === "sourceMap" || key === "locations") && typeof value !== "boolean") {
156
+ throw new TypeError(`@solidjs/compiler \`${key}\` option must be boolean`);
157
157
  }
158
158
  nativeOptions[key] = value;
159
159
  }
@@ -297,6 +297,7 @@ function validateImportDefinition(key, value) {
297
297
 
298
298
  const nativeOptionKeys = new Set([
299
299
  "filename",
300
+ "root",
300
301
  "moduleName",
301
302
  "generate",
302
303
  "hydratable",
@@ -317,7 +318,6 @@ const nativeOptionKeys = new Set([
317
318
  "staticMarker",
318
319
  "omitNestedClosingTags",
319
320
  "omitLastClosingTag",
320
- "serverComponents",
321
321
  "hoistProps",
322
322
  "builtIns",
323
323
  "renderers"
@@ -368,6 +368,16 @@ function validateOptions(code, options) {
368
368
  nativeOptions.sourceNames = value;
369
369
  continue;
370
370
  }
371
+ // Removed with binding slots (2026-10-16). Still accepted, and ignored,
372
+ // because @solidjs/vite-plugin passes it for server-component builds.
373
+ if (key === "serverComponents") continue;
374
+ if (key === "root") {
375
+ if (typeof value !== "string") {
376
+ throw new TypeError("@solidjs/compiler `root` option must be a string");
377
+ }
378
+ nativeOptions.root = value;
379
+ continue;
380
+ }
371
381
  if (nativeOptionKeys.has(key)) {
372
382
  if (key === "renderers") validateRenderers(value);
373
383
  nativeOptions[key] = value;
@@ -378,7 +388,7 @@ function validateOptions(code, options) {
378
388
  return nativeOptions;
379
389
  }
380
390
 
381
- const sourceNameKinds = new Set(["components", "bindings"]);
391
+ const sourceNameKinds = new Set(["components", "bindings", "locations"]);
382
392
 
383
393
  function validateSourceNames(value) {
384
394
  if (typeof value === "boolean") return;
@@ -435,6 +445,23 @@ function tryPackage(packageName) {
435
445
  }
436
446
  }
437
447
 
448
+ // The binding makes `filename` relative to `root` (`loc` paths, directive
449
+ // hashes), resolving both against its own working directory. A WASI binding
450
+ // cannot see the host's (it starts at `/`), so hand it a `root` that needs
451
+ // none: absolute beside an absolute filename (the working directory when
452
+ // unset), relative beside a relative one. The result is unchanged on a native
453
+ // binding.
454
+ function hostRoot(nativeOptions) {
455
+ if (nativeOptions == null || typeof nativeOptions.filename !== "string") return nativeOptions;
456
+ const { filename, root } = nativeOptions;
457
+ if (path.isAbsolute(filename)) {
458
+ nativeOptions.root = path.resolve(root ?? ".");
459
+ } else if (root !== undefined && path.isAbsolute(root)) {
460
+ nativeOptions.root = path.relative(process.cwd(), root) || ".";
461
+ }
462
+ return nativeOptions;
463
+ }
464
+
438
465
  function requireBinding() {
439
466
  const explicit = process.env.SOLID_COMPILER_NATIVE;
440
467
  if (explicit) return require(explicit);
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.15",
4
+ "version": "2.0.0-rc.16",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -62,11 +62,11 @@
62
62
  "emnapi": "^1.11.3"
63
63
  },
64
64
  "optionalDependencies": {
65
- "@solidjs/compiler-darwin-x64": "2.0.0-rc.15",
66
- "@solidjs/compiler-darwin-arm64": "2.0.0-rc.15",
67
- "@solidjs/compiler-linux-x64-gnu": "2.0.0-rc.15",
68
- "@solidjs/compiler-linux-arm64-gnu": "2.0.0-rc.15",
69
- "@solidjs/compiler-win32-x64-msvc": "2.0.0-rc.15",
70
- "@solidjs/compiler-wasm32-wasi": "2.0.0-rc.15"
65
+ "@solidjs/compiler-darwin-x64": "2.0.0-rc.16",
66
+ "@solidjs/compiler-darwin-arm64": "2.0.0-rc.16",
67
+ "@solidjs/compiler-linux-x64-gnu": "2.0.0-rc.16",
68
+ "@solidjs/compiler-linux-arm64-gnu": "2.0.0-rc.16",
69
+ "@solidjs/compiler-win32-x64-msvc": "2.0.0-rc.16",
70
+ "@solidjs/compiler-wasm32-wasi": "2.0.0-rc.16"
71
71
  }
72
72
  }
package/types.d.ts CHANGED
@@ -4,10 +4,22 @@ export interface SourceNamesOptions {
4
4
  components?: boolean;
5
5
  /** Binding effect labels: the element and attribute (or hole) each compiled effect writes. */
6
6
  bindings?: boolean;
7
+ /**
8
+ * Source locations beside each emitted name: `file:line:col` (`filename`
9
+ * relative to `root`, column 1-based) as `createComponent`'s fourth
10
+ * argument and as `loc` after `name` in a binding's options. Only where
11
+ * the name is emitted, and only with a `filename`.
12
+ */
13
+ locations?: boolean;
7
14
  }
8
15
 
9
16
  export interface TransformOptions {
10
17
  filename?: string;
18
+ /**
19
+ * Project root the `sourceNames.locations` paths are made relative to.
20
+ * Defaults to the working directory.
21
+ */
22
+ root?: string;
11
23
  /** Default `"@solidjs/web"`. */
12
24
  moduleName?: string;
13
25
  /**
@@ -30,6 +42,10 @@ export interface TransformOptions {
30
42
  * binding effect named by what it writes — `span.textContent`,
31
43
  * `div.class:active`, a hole `div.children`, a spread `div.spread` — as
32
44
  * an options argument on `effect`/`insert`/`spread`; DOM output only.
45
+ * `locations`: the source position (`src/App.tsx:12:5`, `filename`
46
+ * relative to `root`) beside each emitted name — a fourth `createComponent`
47
+ * argument, `loc` after `name` in a binding's options — so a console
48
+ * report can point at the line; nothing without a `filename`.
33
49
  * The production runtimes ignore the names. Defaults to `dev`: unset,
34
50
  * every kind is on in dev and off otherwise; `true`/`false` sets every
35
51
  * kind; an object picks, and each kind it leaves unspecified follows
@@ -53,6 +69,7 @@ export interface TransformOptions {
53
69
  validate?: boolean;
54
70
  omitNestedClosingTags?: boolean;
55
71
  omitLastClosingTag?: boolean;
72
+ /** @deprecated Ignored. Binding slots, the only thing it compiled for, are removed. */
56
73
  serverComponents?: boolean;
57
74
  /** SSR-only, default `true`: component props literals with getters compile to module-level constructors with shared getters (#3511). */
58
75
  hoistProps?: boolean;
@@ -275,8 +292,27 @@ export function transformRefreshAsync(
275
292
  * `sourceNames` option covers only the JSX-level kinds.
276
293
  */
277
294
  export interface TransformSourceNamesOptions {
278
- /** Picks the parser dialect (`.ts`, `.tsx`, `.js`, `.jsx`); TSX without one. */
295
+ /**
296
+ * Picks the parser dialect (`.ts`, `.tsx`, `.js`, `.jsx`); TSX without
297
+ * one. Also the file the `loc` strings name: without one no `loc` is
298
+ * written.
299
+ */
279
300
  filename?: string;
301
+ /**
302
+ * Write `loc` after `name` in each options literal: the call's
303
+ * `file:line:col` (`filename` relative to `root`, column 1-based), so
304
+ * `createSignal(0, { name: "count", loc: "src/store.ts:3:22" })`. An
305
+ * explicit `name` is kept and `loc` still added; an explicit `loc` is
306
+ * never overridden. The pass only runs for the dev and observe postures,
307
+ * so this is on by default.
308
+ * @default true
309
+ */
310
+ locations?: boolean;
311
+ /**
312
+ * Project root the `loc` paths are made relative to. Defaults to the
313
+ * working directory.
314
+ */
315
+ root?: string;
280
316
  sourceMap?: boolean;
281
317
  }
282
318