@rsvelte/vite-plugin-svelte-native 0.3.1 → 0.3.3

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/envelope.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // Lazy decoder for the Rust↔JS raw-transfer envelope produced by
2
2
  // `binding.compileEnvelope`. The byte format is owned by
3
- // `src/napi_raw.rs`; keep both ends in sync.
3
+ // `crates/rsvelte_bindings_support/src/napi_raw.rs`; keep both ends in sync.
4
4
  //
5
5
  // The returned object is shaped like the legacy `compile()` result
6
6
  // (`{ js: { code, map }, css: {…}|null, warnings: […], metadata, ast }`)
@@ -47,9 +47,10 @@ function assertWindow(bufLen, off, len, label) {
47
47
  * Decode an envelope produced by `compileEnvelope` / `compileModuleEnvelope`.
48
48
  *
49
49
  * @param {Buffer|Uint8Array} buf
50
+ * @param {string} [sourceContent]
50
51
  * @returns {object} CompileResult-shaped object with lazy fields
51
52
  */
52
- function decodeEnvelope(buf) {
53
+ function decodeEnvelope(buf, sourceContent) {
53
54
  if (!buf || buf.byteLength < HEADER_LEN) {
54
55
  throw new Error(
55
56
  `[rsvelte] envelope too small (${buf ? buf.byteLength : 0} bytes, ` +
@@ -117,11 +118,27 @@ function decodeEnvelope(buf) {
117
118
  // js — eagerly construct the wrapper object, but defer string/JSON
118
119
  // realisation. Vite always touches `js.code`; the map is only
119
120
  // touched when emitting sourcemaps.
120
- const js = makeCodeMapObject(buf, slice, jsCodeOff, jsCodeLen, jsMapOff, jsMapLen);
121
+ const js = makeCodeMapObject(
122
+ buf,
123
+ slice,
124
+ jsCodeOff,
125
+ jsCodeLen,
126
+ jsMapOff,
127
+ jsMapLen,
128
+ sourceContent,
129
+ );
121
130
 
122
131
  let css = null;
123
132
  if (hasCss) {
124
- css = makeCodeMapObject(buf, slice, cssCodeOff, cssCodeLen, cssMapOff, cssMapLen);
133
+ css = makeCodeMapObject(
134
+ buf,
135
+ slice,
136
+ cssCodeOff,
137
+ cssCodeLen,
138
+ cssMapOff,
139
+ cssMapLen,
140
+ sourceContent,
141
+ );
125
142
  css.hasGlobal = (flags & FLAG_CSS_HAS_GLOBAL) !== 0;
126
143
  }
127
144
 
@@ -150,7 +167,7 @@ function decodeEnvelope(buf) {
150
167
  return result;
151
168
  }
152
169
 
153
- function makeCodeMapObject(buf, slice, codeOff, codeLen, mapOff, mapLen) {
170
+ function makeCodeMapObject(buf, slice, codeOff, codeLen, mapOff, mapLen, sourceContent) {
154
171
  const obj = {};
155
172
  let codeCache = null;
156
173
  // `code` and `map` need setters as well as getters — upstream
@@ -182,7 +199,7 @@ function makeCodeMapObject(buf, slice, codeOff, codeLen, mapOff, mapLen) {
182
199
  // parsed object matches the legacy compile() shape —
183
200
  // callers that just want the raw JSON to write to disk
184
201
  // should prefer `mapBytes` / `mapText` (no JSON.parse).
185
- mapCache = JSON.parse(slice(mapOff, mapLen));
202
+ mapCache = attachSourceContent(JSON.parse(slice(mapOff, mapLen)), sourceContent);
186
203
  }
187
204
  return mapCache;
188
205
  },
@@ -199,6 +216,10 @@ function makeCodeMapObject(buf, slice, codeOff, codeLen, mapOff, mapLen) {
199
216
  configurable: true,
200
217
  get() {
201
218
  if (!hasMap) return null;
219
+ const raw = slice(mapOff, mapLen);
220
+ if (hasExternalSourceContent(raw, sourceContent)) {
221
+ return Buffer.from(materializeMapText(raw, sourceContent));
222
+ }
202
223
  return buf.subarray
203
224
  ? buf.subarray(mapOff, mapOff + mapLen)
204
225
  : new Uint8Array(buf.buffer, buf.byteOffset + mapOff, mapLen);
@@ -212,12 +233,36 @@ function makeCodeMapObject(buf, slice, codeOff, codeLen, mapOff, mapLen) {
212
233
  configurable: true,
213
234
  get() {
214
235
  if (!hasMap) return null;
215
- return slice(mapOff, mapLen);
236
+ return materializeMapText(slice(mapOff, mapLen), sourceContent);
216
237
  },
217
238
  });
218
239
  return obj;
219
240
  }
220
241
 
242
+ function attachSourceContent(map, sourceContent) {
243
+ if (
244
+ sourceContent !== undefined &&
245
+ Array.isArray(map.sourcesContent) &&
246
+ map.sourcesContent.length === 1 &&
247
+ map.sourcesContent[0] === null
248
+ ) {
249
+ map.sourcesContent[0] = sourceContent;
250
+ }
251
+ return map;
252
+ }
253
+
254
+ function hasExternalSourceContent(mapText, sourceContent) {
255
+ return sourceContent !== undefined && mapText.includes('"sourcesContent":[null]');
256
+ }
257
+
258
+ function materializeMapText(mapText, sourceContent) {
259
+ if (!hasExternalSourceContent(mapText, sourceContent)) return mapText;
260
+ return mapText.replace(
261
+ '"sourcesContent":[null]',
262
+ () => `"sourcesContent":[${JSON.stringify(sourceContent)}]`,
263
+ );
264
+ }
265
+
221
266
  function decodeWarnings(buf, view, off, regionLen, count, slice) {
222
267
  // Every record field is bounds-checked against the warnings region
223
268
  // (already validated to lie inside the buffer by the caller) so a
@@ -322,9 +367,10 @@ const BATCH_STATUS_ERR = 1;
322
367
  * or an `Error` carrying the per-entry failure message.
323
368
  *
324
369
  * @param {Buffer|Uint8Array} buf
370
+ * @param {string[]} [sourceContents]
325
371
  * @returns {Array<object|Error>}
326
372
  */
327
- function decodeBatch(buf) {
373
+ function decodeBatch(buf, sourceContents) {
328
374
  if (!buf || buf.byteLength < BATCH_HEADER_LEN) {
329
375
  throw new Error(
330
376
  `[rsvelte] batch envelope too small (${buf ? buf.byteLength : 0} bytes, ` +
@@ -376,7 +422,7 @@ function decodeBatch(buf) {
376
422
  ? buf.subarray(payloadOff, payloadOff + payloadLen)
377
423
  : new Uint8Array(buf.buffer, buf.byteOffset + payloadOff, payloadLen);
378
424
  if (status === BATCH_STATUS_OK) {
379
- out[i] = decodeEnvelope(slice);
425
+ out[i] = decodeEnvelope(slice, sourceContents?.[i]);
380
426
  } else if (status === BATCH_STATUS_ERR) {
381
427
  const msg = bufferIsNodeBuffer(slice)
382
428
  ? slice.toString('utf8')
package/index.cjs CHANGED
@@ -118,10 +118,12 @@ function applyWarningFilter(result, warningFilter) {
118
118
  }
119
119
 
120
120
  // `compile` / `compileModule` are wrapped to route through the
121
- // raw-transfer envelope (`compileEnvelope`): the Rust side hands us
121
+ // raw-transfer envelope: the Rust side hands us
122
122
  // one `Buffer`, the JS side lazy-decodes only the fields the caller
123
123
  // reads. This avoids the V8 string copy + `serde_json` round-trip
124
- // that the legacy JSON path pays for every call.
124
+ // that the legacy JSON path pays for every call. The wrapper-only
125
+ // native entry points leave `sourcesContent` external so the source
126
+ // already owned by JavaScript is not copied into the envelope.
125
127
  //
126
128
  // Callers that need the raw envelope (e.g. to ship it across a worker
127
129
  // boundary without re-encoding) can still grab `binding.compileEnvelope`
@@ -136,7 +138,10 @@ function compile(source, options) {
136
138
  );
137
139
  }
138
140
  const { options: resolved, warningFilter } = prepareCompileOptions(options);
139
- return applyWarningFilter(decodeEnvelope(binding.compileEnvelope(source, resolved)), warningFilter);
141
+ return applyWarningFilter(
142
+ decodeEnvelope(binding.compileEnvelopeExternalSources(source, resolved), source),
143
+ warningFilter,
144
+ );
140
145
  }
141
146
 
142
147
  function compileModule(source, options) {
@@ -170,7 +175,11 @@ function compileBatch(inputs) {
170
175
  if (warningFilter) filters[i] = warningFilter;
171
176
  return options === input.options ? input : { source: input.source, options };
172
177
  });
173
- const results = decodeBatch(binding.compileBatch(prepared));
178
+ const sourceContents = prepared.map((input) => input.source);
179
+ const results = decodeBatch(
180
+ binding.compileBatchExternalSources(prepared),
181
+ sourceContents,
182
+ );
174
183
  if (filters.length) {
175
184
  results.forEach((result, i) => applyWarningFilter(result, filters[i]));
176
185
  }
@@ -194,7 +203,10 @@ async function compileAsync(source, options) {
194
203
  return applyWarningFilter(result, warningFilter);
195
204
  }
196
205
  return applyWarningFilter(
197
- decodeEnvelope(await binding.compileEnvelopeAsync(source, resolved)),
206
+ decodeEnvelope(
207
+ await binding.compileEnvelopeExternalSourcesAsync(source, resolved),
208
+ source,
209
+ ),
198
210
  warningFilter,
199
211
  );
200
212
  }
@@ -207,7 +219,11 @@ async function compileBatchAsync(inputs) {
207
219
  if (warningFilter) filters[i] = warningFilter;
208
220
  return options === input.options ? input : { source: input.source, options };
209
221
  });
210
- const results = decodeBatch(await binding.compileBatchAsync(prepared));
222
+ const sourceContents = prepared.map((input) => input.source);
223
+ const results = decodeBatch(
224
+ await binding.compileBatchExternalSourcesAsync(prepared),
225
+ sourceContents,
226
+ );
211
227
  if (filters.length) {
212
228
  results.forEach((result, i) => applyWarningFilter(result, filters[i]));
213
229
  }
package/index.d.ts CHANGED
@@ -138,9 +138,9 @@ export interface CompileResultJs {
138
138
  map: unknown;
139
139
  /**
140
140
  * Zero-copy `Buffer` / `Uint8Array` view over the raw sourcemap
141
- * JSON bytes in the envelope. `null` if no map was produced. Stable
142
- * for the lifetime of the parent `CompileResult` (becomes invalid
143
- * once a `compileEnvelopeZeroCopy` buffer is GC'd).
141
+ * JSON bytes in a raw envelope. The standard `compile` wrappers
142
+ * externalize the source text and materialize a complete buffer on
143
+ * access instead. `null` if no map was produced.
144
144
  */
145
145
  mapBytes: Buffer | Uint8Array | null;
146
146
  /** Raw sourcemap JSON as a string — no `JSON.parse`. `null` if no map. */
@@ -180,7 +180,8 @@ export function compileModule(
180
180
  /**
181
181
  * Lower-level raw-transfer entry point. Returns a single `Buffer`
182
182
  * containing the entire compile result in the rsvelte envelope format
183
- * (see `src/napi_raw.rs`). Pair with {@link decodeEnvelope} to obtain
183
+ * (see `crates/rsvelte_bindings_support/src/napi_raw.rs`). Pair with
184
+ * {@link decodeEnvelope} to obtain
184
185
  * the legacy {@link CompileResult} shape; or pass the buffer through
185
186
  * worker `postMessage` (transferable) to avoid a copy.
186
187
  */
@@ -214,8 +215,8 @@ export function compileModuleEnvelopeZeroCopy(
214
215
  options?: ModuleCompileOptions,
215
216
  ): Buffer;
216
217
 
217
- /** Decode a buffer produced by {@link compileEnvelope}. */
218
- export function decodeEnvelope(buf: Buffer | Uint8Array): CompileResult;
218
+ /** Decode an envelope, optionally restoring externally supplied source text. */
219
+ export function decodeEnvelope(buf: Buffer | Uint8Array, sourceContent?: string): CompileResult;
219
220
 
220
221
  /**
221
222
  * Single entry in a {@link compileBatch} worklist. `options` is
@@ -249,8 +250,11 @@ export function compileBatch(
249
250
  */
250
251
  export function compileBatchRaw(inputs: CompileBatchInput[]): Buffer;
251
252
 
252
- /** Decode a batch envelope produced by {@link compileBatchRaw}. */
253
- export function decodeBatch(buf: Buffer | Uint8Array): Array<CompileResult | Error>;
253
+ /** Decode a batch envelope, optionally restoring externally supplied source text. */
254
+ export function decodeBatch(
255
+ buf: Buffer | Uint8Array,
256
+ sourceContents?: string[],
257
+ ): Array<CompileResult | Error>;
254
258
 
255
259
  /**
256
260
  * Async variant of {@link compile}. The Rust side runs on a libuv
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsvelte/vite-plugin-svelte-native",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "NAPI bindings to the rsvelte compiler — used by the @rsvelte vite-plugin-svelte shim",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,11 +29,11 @@
29
29
  "index.d.ts"
30
30
  ],
31
31
  "optionalDependencies": {
32
- "@rsvelte/vite-plugin-svelte-native-darwin-arm64": "^0.3.1",
33
- "@rsvelte/vite-plugin-svelte-native-linux-arm64-gnu": "^0.3.1",
34
- "@rsvelte/vite-plugin-svelte-native-darwin-x64": "^0.3.1",
35
- "@rsvelte/vite-plugin-svelte-native-linux-x64-gnu": "^0.3.1",
36
- "@rsvelte/vite-plugin-svelte-native-win32-x64-msvc": "^0.3.1"
32
+ "@rsvelte/vite-plugin-svelte-native-darwin-arm64": "^0.3.3",
33
+ "@rsvelte/vite-plugin-svelte-native-darwin-x64": "^0.3.3",
34
+ "@rsvelte/vite-plugin-svelte-native-linux-arm64-gnu": "^0.3.3",
35
+ "@rsvelte/vite-plugin-svelte-native-linux-x64-gnu": "^0.3.3",
36
+ "@rsvelte/vite-plugin-svelte-native-win32-x64-msvc": "^0.3.3"
37
37
  },
38
38
  "publishConfig": {
39
39
  "access": "public"