@octanejs/rspack-plugin 0.1.49 → 0.1.50

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@octanejs/rspack-plugin",
3
- "version": "0.1.49",
3
+ "version": "0.1.50",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "engines": {
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@rspack/core": "^2.0.0",
48
- "octane": "^0.1.51 || ^0.2.0"
48
+ "octane": "^0.2.13"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@rspack/core": "^2.1.4",
@@ -54,7 +54,7 @@
54
54
  "css-loader": "6.11.0",
55
55
  "jsdom": "^30.0.1",
56
56
  "vitest": "^4.1.10",
57
- "octane": "0.2.7"
57
+ "octane": "0.2.13"
58
58
  },
59
59
  "scripts": {
60
60
  "test": "vitest run --config vitest.config.js"
package/src/loader.js CHANGED
@@ -121,6 +121,9 @@ export default function octaneLoader(source, inputSourceMap) {
121
121
  root,
122
122
  profile,
123
123
  ...(options.strong === undefined ? null : { strong: options.strong }),
124
+ ...(options.knownAttributeSpreads === undefined
125
+ ? null
126
+ : { knownAttributeSpreads: options.knownAttributeSpreads }),
124
127
  ...(options.exclude === undefined ? null : { exclude: options.exclude }),
125
128
  ...(compilerOptions.renderers === undefined
126
129
  ? null
@@ -205,11 +208,16 @@ export default function octaneLoader(source, inputSourceMap) {
205
208
  }
206
209
  setBuildInfo(this._module, {
207
210
  canonicalId: canonicalModuleId(id, root),
211
+ resourceQuery: id.slice(cleanModuleId(id).length),
208
212
  transformKind: result.kind,
213
+ ...(result.streamedSignals === true ? { streamedSignals: true } : null),
209
214
  serverRpc:
210
215
  result.kind === 'compile' &&
211
216
  (result.code.includes('_$__serverRpc(') ||
212
217
  result.code.includes('export const _$_server_$_')),
218
+ ...(Array.isArray(result.independentWidgets) && result.independentWidgets.length > 0
219
+ ? { independentWidgets: result.independentWidgets }
220
+ : null),
213
221
  ...(result.universalRuntime === undefined
214
222
  ? null
215
223
  : { universalRuntime: result.universalRuntime }),
package/src/plugin.js CHANGED
@@ -5,10 +5,12 @@ import { dirname, isAbsolute, join, resolve } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import {
7
7
  CLIENT_REFERENCE_MANIFEST_FILENAME,
8
+ INDEPENDENT_HYDRATION_MANIFEST_FILENAME,
8
9
  createClientReferenceManifest,
9
10
  createOctaneCompiler,
10
11
  } from 'octane/compiler/bundler';
11
12
  import { installCssModuleConstants } from './css-module-constants.js';
13
+ import { createStreamedSignalHmrRuntimeModule } from './streamed-signals-hmr.js';
12
14
  import {
13
15
  getOctaneRspackBuildInfo,
14
16
  inferRspackEnvironment,
@@ -182,6 +184,9 @@ function createDiscoveryCompiler(options, root, profile, specialization) {
182
184
  root,
183
185
  profile,
184
186
  ...(options.strong === undefined ? null : { strong: options.strong }),
187
+ ...(options.knownAttributeSpreads === undefined
188
+ ? null
189
+ : { knownAttributeSpreads: options.knownAttributeSpreads }),
185
190
  ...(options.exclude === undefined ? null : { exclude: options.exclude }),
186
191
  ...(renderers === undefined ? null : { renderers }),
187
192
  ...(universalRuntime === undefined ? null : { universalRuntime }),
@@ -234,16 +239,17 @@ function visitClientReferenceModules(
234
239
  inheritedChunks,
235
240
  visit,
236
241
  seen = new Set(),
242
+ executableModule = module,
237
243
  ) {
238
244
  if (!module || seen.has(module)) return;
239
245
  seen.add(module);
240
246
  const chunks = moduleChunks(compilation, module, inheritedChunks);
241
- visit(module, chunks);
247
+ visit(module, chunks, executableModule);
242
248
  for (const child of iterable(module.modules)) {
243
- visitClientReferenceModules(compilation, child, chunks, visit, seen);
249
+ visitClientReferenceModules(compilation, child, chunks, visit, seen, module);
244
250
  }
245
251
  if (module.rootModule) {
246
- visitClientReferenceModules(compilation, module.rootModule, chunks, visit, seen);
252
+ visitClientReferenceModules(compilation, module.rootModule, chunks, visit, seen, module);
247
253
  }
248
254
  }
249
255
 
@@ -279,6 +285,158 @@ function emitClientReferenceManifest(compiler, compilation) {
279
285
  );
280
286
  }
281
287
 
288
+ function emitIndependentHydrationManifest(compiler, compilation, mode) {
289
+ const modules = collectIndependentHydrationModules(compilation);
290
+ const widgets = {};
291
+ for (const { template, target } of independentHydrationTargets(modules)) {
292
+ const activationChunks = new Set(target.chunks);
293
+ for (const chunk of target.chunks) {
294
+ for (const referenced of iterable(chunk?.getAllReferencedChunks?.())) {
295
+ activationChunks.add(referenced);
296
+ }
297
+ }
298
+ const files = [...activationChunks]
299
+ .flatMap((chunk) => [...iterable(chunk.files), ...iterable(chunk.auxiliaryFiles)])
300
+ .map(String);
301
+ widgets[template.boundaryId] = {
302
+ version: 1,
303
+ boundaryId: template.boundaryId,
304
+ // Rspack chunks are runtime payloads, not native module namespaces. The
305
+ // initial runtime module below owns the actual chunk-load + require closure.
306
+ moduleId: template.boundaryId,
307
+ exportName: template.exportName,
308
+ captureSchema: template.captureSchema,
309
+ hookSeed: template.hookSeed,
310
+ idSeed: template.idSeed,
311
+ signalSites: template.signalSites,
312
+ styles: [...new Set(files.filter((file) => /\.css(?:\?|$)/.test(file)))].sort(),
313
+ parentDependencies: false,
314
+ };
315
+ }
316
+ const records = Object.fromEntries(
317
+ Object.entries(widgets).sort(([left], [right]) => left.localeCompare(right)),
318
+ );
319
+ // Match the native __webpack_hash__ value captured by the executing entry.
320
+ // A widget-schema hash does not fence changes elsewhere in its client graph.
321
+ const buildId = compilation.hash;
322
+ if (typeof buildId !== 'string' || !buildId) {
323
+ throw new Error('Octane client build has no completed compilation hash.');
324
+ }
325
+ const independentHydration = Object.keys(records).length !== 0;
326
+ compilation.emitAsset(
327
+ 'octane-client-build.json',
328
+ new compiler.webpack.sources.RawSource(
329
+ JSON.stringify(
330
+ { version: 1, buildId, mode, capabilities: { independentHydration } },
331
+ null,
332
+ 2,
333
+ ) + '\n',
334
+ ),
335
+ );
336
+ if (!independentHydration) return;
337
+ compilation.emitAsset(
338
+ INDEPENDENT_HYDRATION_MANIFEST_FILENAME,
339
+ new compiler.webpack.sources.RawSource(
340
+ JSON.stringify({ version: 1, buildId, widgets: records }, null, 2) + '\n',
341
+ ),
342
+ );
343
+ }
344
+
345
+ function collectIndependentHydrationModules(compilation) {
346
+ const modules = [];
347
+ for (const topLevelModule of iterable(compilation.modules)) {
348
+ visitClientReferenceModules(
349
+ compilation,
350
+ topLevelModule,
351
+ [],
352
+ (module, chunks, executableModule) => {
353
+ const info = getOctaneRspackBuildInfo(module);
354
+ if (info !== null) modules.push({ module, executableModule, info, chunks });
355
+ },
356
+ new Set(),
357
+ );
358
+ }
359
+ return modules;
360
+ }
361
+
362
+ function independentHydrationTargets(modules) {
363
+ const targets = [];
364
+ for (const { info } of modules) {
365
+ for (const template of info.independentWidgets ?? []) {
366
+ const query = template.request.slice(template.request.indexOf('?'));
367
+ const candidates = modules.filter(
368
+ (candidate) =>
369
+ candidate.info.canonicalId === template.moduleId &&
370
+ candidate.info.resourceQuery?.includes(query),
371
+ );
372
+ const target =
373
+ candidates.find(
374
+ (candidate) =>
375
+ candidate.executableModule != null && candidate.executableModule !== candidate.module,
376
+ ) ?? candidates[0];
377
+ if (target === undefined) {
378
+ throw new Error(
379
+ `Octane independent Hydrate ${JSON.stringify(template.boundaryId)} has no emitted activation chunk.`,
380
+ );
381
+ }
382
+ targets.push({ template, target });
383
+ }
384
+ }
385
+ return targets;
386
+ }
387
+
388
+ function independentHydrationRuntimeModule(compiler, compilation) {
389
+ const { RuntimeGlobals, RuntimeModule } = compiler.webpack;
390
+ return class OctaneIndependentHydrationRuntimeModule extends RuntimeModule {
391
+ constructor() {
392
+ super('octane independent hydration loaders');
393
+ this.fullHash = true;
394
+ }
395
+
396
+ generate() {
397
+ const registrations = [];
398
+ const seen = new Set();
399
+ for (const { template, target } of independentHydrationTargets(
400
+ collectIndependentHydrationModules(compilation),
401
+ )) {
402
+ if (seen.has(template.boundaryId)) continue;
403
+ seen.add(template.boundaryId);
404
+ const candidates = [target.executableModule, target.module, target.module?.rootModule];
405
+ const executable = candidates.find(
406
+ (module) => module != null && compilation.chunkGraph.getModuleId(module) != null,
407
+ );
408
+ if (executable === undefined) {
409
+ throw new Error(
410
+ `Octane independent Hydrate ${JSON.stringify(template.boundaryId)} has no executable Rspack module.`,
411
+ );
412
+ }
413
+ const moduleId = compilation.chunkGraph.getModuleId(executable);
414
+ const activationChunks = new Set(target.chunks);
415
+ for (const chunk of target.chunks) {
416
+ for (const referenced of iterable(chunk?.getAllReferencedChunks?.())) {
417
+ activationChunks.add(referenced);
418
+ }
419
+ }
420
+ const chunkIds = [...activationChunks]
421
+ .filter((chunk) => chunk !== this.chunk && chunk?.id != null)
422
+ .map((chunk) => chunk.id)
423
+ .sort((left, right) => String(left).localeCompare(String(right)));
424
+ const load =
425
+ chunkIds.length === 0
426
+ ? 'Promise.resolve()'
427
+ : `Promise.all(${JSON.stringify(chunkIds)}.map(${RuntimeGlobals.ensureChunk}))`;
428
+ registrations.push(
429
+ `${RuntimeGlobals.global}.__OCTANE_INDEPENDENT_MODULES__[${JSON.stringify(template.boundaryId)}] = function() { return ${load}.then(function() { return ${RuntimeGlobals.require}(${JSON.stringify(moduleId)}); }); };`,
430
+ );
431
+ }
432
+ return [
433
+ `${RuntimeGlobals.global}.__OCTANE_INDEPENDENT_MODULES__ ||= Object.create(null);`,
434
+ ...registrations,
435
+ ].join('\n');
436
+ }
437
+ };
438
+ }
439
+
282
440
  function defineMatchesBoolean(value, expected) {
283
441
  return value === expected || value === JSON.stringify(expected);
284
442
  }
@@ -382,6 +540,7 @@ export class OctaneRspackPlugin {
382
540
  dev,
383
541
  profile,
384
542
  strong: this.options.strong === true,
543
+ knownAttributeSpreads: this.options.knownAttributeSpreads,
385
544
  exclude: this.options.exclude ?? [],
386
545
  renderers: this.options.renderers?.signature,
387
546
  runtime: this.options.runtime,
@@ -429,6 +588,9 @@ export class OctaneRspackPlugin {
429
588
  environment,
430
589
  profile,
431
590
  ...(this.options.strong === undefined ? null : { strong: this.options.strong }),
591
+ ...(this.options.knownAttributeSpreads === undefined
592
+ ? null
593
+ : { knownAttributeSpreads: this.options.knownAttributeSpreads }),
432
594
  ...(this.options.hmr === undefined ? null : { hmr: this.options.hmr }),
433
595
  ...(this.options.dev === undefined ? null : { dev: this.options.dev }),
434
596
  ...(this.options.exclude === undefined ? null : { exclude: this.options.exclude }),
@@ -515,12 +677,56 @@ export class OctaneRspackPlugin {
515
677
  addDependencies(compilation.fileDependencies, current.dependencies);
516
678
  addDependencies(compilation.missingDependencies, current.missingDependencies);
517
679
  if (environment === 'client') {
680
+ const IndependentHydrationRuntimeModule = independentHydrationRuntimeModule(
681
+ compiler,
682
+ compilation,
683
+ );
684
+ compilation.hooks.additionalTreeRuntimeRequirements?.tap(
685
+ PLUGIN_NAME,
686
+ (chunk, runtimeRequirements) => {
687
+ if (!chunk.hasRuntime?.()) return;
688
+ const modules = collectIndependentHydrationModules(compilation);
689
+ const featureModules = modules.filter(
690
+ ({ info }) =>
691
+ info.streamedSignals === true || (info.independentWidgets?.length ?? 0) > 0,
692
+ );
693
+ if (
694
+ featureModules.length > 0 &&
695
+ compiler.options.plugins.some(
696
+ (plugin) => plugin instanceof compiler.webpack.HotModuleReplacementPlugin,
697
+ )
698
+ ) {
699
+ runtimeRequirements.add(compiler.webpack.RuntimeGlobals.interceptModuleExecution);
700
+ runtimeRequirements.add(compiler.webpack.RuntimeGlobals.moduleCache);
701
+ runtimeRequirements.add(compiler.webpack.RuntimeGlobals.global);
702
+ compilation.addRuntimeModule(
703
+ chunk,
704
+ createStreamedSignalHmrRuntimeModule(compiler, compilation, featureModules),
705
+ );
706
+ }
707
+ if (independentHydrationTargets(modules).length === 0) {
708
+ return;
709
+ }
710
+ runtimeRequirements.add(compiler.webpack.RuntimeGlobals.ensureChunk);
711
+ runtimeRequirements.add(compiler.webpack.RuntimeGlobals.global);
712
+ runtimeRequirements.add(compiler.webpack.RuntimeGlobals.require);
713
+ compilation.addRuntimeModule(chunk, new IndependentHydrationRuntimeModule());
714
+ },
715
+ );
518
716
  compilation.hooks.processAssets.tap(
519
717
  {
520
718
  name: PLUGIN_NAME,
521
719
  stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_REPORT,
522
720
  },
523
- () => emitClientReferenceManifest(compiler, compilation),
721
+ () => {
722
+ emitClientReferenceManifest(compiler, compilation);
723
+ emitIndependentHydrationManifest(
724
+ compiler,
725
+ compilation,
726
+ this.options.clientBuildMode ??
727
+ (compiler.options.mode === 'development' ? 'development' : 'production'),
728
+ );
729
+ },
524
730
  );
525
731
  }
526
732
  });
package/src/shared.js CHANGED
@@ -41,6 +41,7 @@ const LOADER_OPTION_KEYS = new Set([
41
41
  'dev',
42
42
  'profile',
43
43
  'strong',
44
+ 'knownAttributeSpreads',
44
45
  'exclude',
45
46
  'renderers',
46
47
  'requireDirective',
@@ -54,6 +55,7 @@ const PLUGIN_OPTION_KEYS = new Set([
54
55
  'runtime',
55
56
  'transpile',
56
57
  'cssModuleConstants',
58
+ 'clientBuildMode',
57
59
  ]);
58
60
  const LAYER_SPECIALIZATION_KEYS = new Set(['runtime', 'renderers', 'universalRuntime']);
59
61
 
@@ -198,6 +200,16 @@ function normalizeOptions(value, plugin) {
198
200
  throw new TypeError('@octanejs/rspack-plugin: `root` must be a path string.');
199
201
  }
200
202
  if (plugin) normalizeRuntimeRequest(options.runtime);
203
+ if (
204
+ plugin &&
205
+ options.clientBuildMode !== undefined &&
206
+ options.clientBuildMode !== 'production' &&
207
+ options.clientBuildMode !== 'development'
208
+ ) {
209
+ throw new TypeError(
210
+ '@octanejs/rspack-plugin: `clientBuildMode` must be "production" or "development".',
211
+ );
212
+ }
201
213
  if (
202
214
  options.environment !== undefined &&
203
215
  options.environment !== 'client' &&
@@ -255,6 +267,9 @@ function normalizeOptions(value, plugin) {
255
267
  ...(options.dev === undefined ? null : { dev: options.dev }),
256
268
  ...(options.profile === undefined ? null : { profile: options.profile }),
257
269
  ...(options.strong === undefined ? null : { strong: options.strong }),
270
+ ...(options.knownAttributeSpreads === undefined
271
+ ? null
272
+ : { knownAttributeSpreads: options.knownAttributeSpreads }),
258
273
  ...(options.exclude === undefined ? null : { exclude: [...options.exclude] }),
259
274
  ...(renderers === undefined ? null : { renderers }),
260
275
  ...(universalRuntime === undefined ? null : { universalRuntime }),
@@ -266,6 +281,9 @@ function normalizeOptions(value, plugin) {
266
281
  ? null
267
282
  : { textTypes: Object.freeze({ tsconfig: options.textTypes.tsconfig }) }),
268
283
  ...(plugin && parallel !== undefined ? { parallel } : null),
284
+ ...(plugin && options.clientBuildMode !== undefined
285
+ ? { clientBuildMode: options.clientBuildMode }
286
+ : null),
269
287
  ...(plugin && options.transpile !== undefined ? { transpile: options.transpile } : null),
270
288
  ...(plugin && options.runtime !== undefined ? { runtime: options.runtime } : null),
271
289
  ...(plugin && options.cssModuleConstants !== undefined
@@ -307,6 +325,8 @@ export function getOctaneRspackBuildInfo(module) {
307
325
  value.transformKind === 'slots' ||
308
326
  value.transformKind === 'client-only-stub') &&
309
327
  typeof value.serverRpc === 'boolean' &&
328
+ (value.resourceQuery === undefined || typeof value.resourceQuery === 'string') &&
329
+ (value.independentWidgets === undefined || Array.isArray(value.independentWidgets)) &&
310
330
  (value.clientReference === undefined || nestedReferenceValid) &&
311
331
  (value.universalRuntime === undefined || universalRuntimeValid)
312
332
  ) {
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Fence feature-bearing documents through Rspack's native module-execution
3
+ * interceptor, before authored factories run. No compiled source is rewritten.
4
+ * @param {import('@rspack/core').Compiler} compiler
5
+ * @param {import('@rspack/core').Compilation} compilation
6
+ * @param {Array<{ module: import('@rspack/core').Module, executableModule?: import('@rspack/core').Module }>} modules
7
+ */
8
+ export function createStreamedSignalHmrRuntimeModule(compiler, compilation, modules) {
9
+ const { RuntimeGlobals, RuntimeModule } = compiler.webpack;
10
+ return new (class extends RuntimeModule {
11
+ constructor() {
12
+ super('octane streamed signal HMR fence', RuntimeModule.STAGE_TRIGGER);
13
+ }
14
+
15
+ generate() {
16
+ const ids = new Set();
17
+ for (const { module, executableModule } of modules) {
18
+ for (const candidate of [executableModule, module, module?.rootModule]) {
19
+ const id = candidate == null ? null : compilation.chunkGraph.getModuleId(candidate);
20
+ if (id != null) {
21
+ ids.add(String(id));
22
+ break;
23
+ }
24
+ }
25
+ }
26
+ return `
27
+ var octaneSignalModules = new Set(${JSON.stringify([...ids].sort())});
28
+ var octaneSignalFenceInstalled = false;
29
+ var octaneSignalGenerationChanged = false;
30
+ var octaneSignalModuleExecuted = false;
31
+ function octaneReloadSignalDocument() {
32
+ ${RuntimeGlobals.global}.location?.reload?.();
33
+ throw new Error('[octane] The streamed signal client build changed. Reload this document.');
34
+ }
35
+ function octaneTrackSignalGeneration(hot) {
36
+ if (!hot || octaneSignalFenceInstalled) return;
37
+ octaneSignalFenceInstalled = true;
38
+ if (hot.status() !== 'idle') octaneSignalGenerationChanged = true;
39
+ hot.addStatusHandler(function(status) {
40
+ if (status === 'apply') octaneSignalGenerationChanged = true;
41
+ if (octaneSignalModuleExecuted && (status === 'check' || status === 'dispose' || status === 'apply')) octaneReloadSignalDocument();
42
+ });
43
+ }
44
+ // A newly introduced runtime may itself arrive during hot application. The
45
+ // entry's cached hot module supplies that state before any feature executes.
46
+ for (var octaneCachedId in ${RuntimeGlobals.moduleCache}) {
47
+ octaneTrackSignalGeneration(${RuntimeGlobals.moduleCache}[octaneCachedId].hot);
48
+ if (octaneSignalFenceInstalled) break;
49
+ }
50
+ ${RuntimeGlobals.interceptModuleExecution}.push(function(options) {
51
+ var hot = options.module.hot;
52
+ octaneTrackSignalGeneration(hot);
53
+ if (!hot || !octaneSignalModules.has(String(options.id))) return;
54
+ if (octaneSignalGenerationChanged || hot.status() !== 'idle') octaneReloadSignalDocument();
55
+ octaneSignalModuleExecuted = true;
56
+ });`;
57
+ }
58
+ })();
59
+ }
package/types/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Compiler, RspackPluginInstance } from '@rspack/core';
2
- import type { OctaneCssModuleConstants } from 'octane/compiler';
2
+ import type { KnownAttributeSpread, OctaneCssModuleConstants } from 'octane/compiler';
3
3
 
4
4
  export type { OctaneCssModuleConstants } from 'octane/compiler';
5
5
 
@@ -144,6 +144,8 @@ export interface OctaneRspackLoaderOptions {
144
144
  * @default false
145
145
  */
146
146
  strong?: boolean;
147
+ /** Fixed native-attribute shapes for trusted imported spread helpers. */
148
+ knownAttributeSpreads?: readonly KnownAttributeSpread[];
147
149
  /**
148
150
  * Path fragments excluded from the plain `.ts`/`.js` hook-slot pass. With
149
151
  * `requireDirective`, excluded paths are exempt from Octane ownership
@@ -175,6 +177,8 @@ export interface OctaneRspackLoaderOptions {
175
177
  }
176
178
 
177
179
  export interface OctaneRspackPluginOptions extends OctaneRspackLoaderOptions {
180
+ /** Build intent for SSR metadata; independent of optimization/HMR settings. */
181
+ clientBuildMode?: 'production' | 'development';
178
182
  /**
179
183
  * @experimental Prove primitive DOM text children from the TypeScript project
180
184
  * in one-shot production builds. Relative paths resolve from the plugin root.
@@ -226,8 +230,25 @@ export interface OctaneRspackPluginOptions extends OctaneRspackLoaderOptions {
226
230
 
227
231
  export interface OctaneRspackBuildInfo {
228
232
  canonicalId: string;
233
+ /** Resource query retained separately from the canonical source identity. */
234
+ resourceQuery?: string;
229
235
  transformKind: 'compile' | 'slots' | 'client-only-stub';
236
+ streamedSignals?: true;
230
237
  serverRpc: boolean;
238
+ /** Strict-independent Hydrate templates completed into the emitted client manifest. */
239
+ independentWidgets?: readonly {
240
+ readonly version: 1;
241
+ readonly boundaryId: string;
242
+ readonly moduleId: string;
243
+ readonly exportName: string;
244
+ readonly request: string;
245
+ readonly captureSchema: readonly { readonly name: string; readonly type: 'json' }[];
246
+ readonly hookSeed: number;
247
+ readonly idSeed: number;
248
+ readonly signalSites: readonly string[];
249
+ readonly styles: readonly string[];
250
+ readonly parentDependencies: false;
251
+ }[];
231
252
  /** Universal host runtime/thread identity, when this module was specialized. */
232
253
  universalRuntime?: OctaneUniversalRuntimeOptions;
233
254
  /** Stable identity shared by the client compile and its inert server stub. */