@octanejs/rspack-plugin 0.1.48 → 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 +3 -3
- package/src/loader.js +66 -6
- package/src/plugin.js +233 -9
- package/src/shared.js +39 -3
- package/src/streamed-signals-hmr.js +59 -0
- package/src/text-types.js +62 -0
- package/types/index.d.ts +33 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octanejs/rspack-plugin",
|
|
3
|
-
"version": "0.1.
|
|
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.
|
|
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.
|
|
57
|
+
"octane": "0.2.13"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
60
|
"test": "vitest run --config vitest.config.js"
|
package/src/loader.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { realpathSync } from 'node:fs';
|
|
1
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
2
2
|
import { dirname, isAbsolute, resolve } from 'node:path';
|
|
3
3
|
import remapping from '@jridgewell/remapping';
|
|
4
4
|
import { canonicalModuleId, cleanModuleId, createOctaneCompiler } from 'octane/compiler/bundler';
|
|
5
|
+
import { resolveRendererForFile } from 'octane/compiler/renderers';
|
|
5
6
|
import {
|
|
6
7
|
clearCssModuleBuildInfo,
|
|
7
8
|
CSS_MODULE_CONTEXT_KEY,
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
selectLayerCompilerOptions,
|
|
15
16
|
} from './shared.js';
|
|
16
17
|
import { loadDescriptorChildrenImports } from './descriptor-children.js';
|
|
18
|
+
import { textTypeFactsForLoader } from './text-types.js';
|
|
17
19
|
|
|
18
20
|
function realRoot(path) {
|
|
19
21
|
try {
|
|
@@ -119,7 +121,9 @@ export default function octaneLoader(source, inputSourceMap) {
|
|
|
119
121
|
root,
|
|
120
122
|
profile,
|
|
121
123
|
...(options.strong === undefined ? null : { strong: options.strong }),
|
|
122
|
-
...(options.
|
|
124
|
+
...(options.knownAttributeSpreads === undefined
|
|
125
|
+
? null
|
|
126
|
+
: { knownAttributeSpreads: options.knownAttributeSpreads }),
|
|
123
127
|
...(options.exclude === undefined ? null : { exclude: options.exclude }),
|
|
124
128
|
...(compilerOptions.renderers === undefined
|
|
125
129
|
? null
|
|
@@ -135,6 +139,41 @@ export default function octaneLoader(source, inputSourceMap) {
|
|
|
135
139
|
});
|
|
136
140
|
const id = realModuleId(this.resource ?? this.resourcePath);
|
|
137
141
|
const authoredSource = String(source);
|
|
142
|
+
const textTypeCandidate =
|
|
143
|
+
options.textTypes !== undefined && this.mode === 'production' && !dev && this.hot !== true;
|
|
144
|
+
let textTypeFilename;
|
|
145
|
+
if (textTypeCandidate) {
|
|
146
|
+
const file = cleanModuleId(id);
|
|
147
|
+
if (
|
|
148
|
+
/(?:\.tsrx|\.tsx)$/i.test(file) &&
|
|
149
|
+
existsSync(file) &&
|
|
150
|
+
compiler._isProjectOwnedSource(file)
|
|
151
|
+
) {
|
|
152
|
+
const canonical = compiler._canonicalModuleId(file);
|
|
153
|
+
const pragmaOwned =
|
|
154
|
+
file.endsWith('.tsx') && compiler._pragmaClaimsOwnership(authoredSource);
|
|
155
|
+
if (compiler._passesOwnershipGate(file, canonical, pragmaOwned)) {
|
|
156
|
+
const renderer = resolveRendererForFile(compiler.renderers, canonical);
|
|
157
|
+
if (
|
|
158
|
+
renderer.target === 'dom' &&
|
|
159
|
+
!(environment === 'server' && renderer.server === 'client-only')
|
|
160
|
+
) {
|
|
161
|
+
textTypeFilename = canonical;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (textTypeFilename !== undefined) {
|
|
167
|
+
// An imported type can change while this module's source stays the same.
|
|
168
|
+
// Rspack's persistent module cache has no dependency edges to every TS
|
|
169
|
+
// Program input. Production watches stay syntax-only but must not persist
|
|
170
|
+
// their generic output for a later one-shot typed build either.
|
|
171
|
+
this.cacheable?.(false);
|
|
172
|
+
}
|
|
173
|
+
const textTypes =
|
|
174
|
+
textTypeFilename !== undefined &&
|
|
175
|
+
this._compiler?.watchMode !== true &&
|
|
176
|
+
this._compiler?.options?.watch !== true;
|
|
138
177
|
const cssModuleConstants =
|
|
139
178
|
this[CSS_MODULE_CONTEXT_KEY]?.enabled === true
|
|
140
179
|
? prepareCssModuleConstants(this, compiler, authoredSource, id, {
|
|
@@ -143,7 +182,7 @@ export default function octaneLoader(source, inputSourceMap) {
|
|
|
143
182
|
dev,
|
|
144
183
|
})
|
|
145
184
|
: null;
|
|
146
|
-
const finish = (clientOnlyImports, isDescriptorChildrenImport, callback) => {
|
|
185
|
+
const finish = (clientOnlyImports, isDescriptorChildrenImport, textTypeFacts, callback) => {
|
|
147
186
|
try {
|
|
148
187
|
const result = compiler.transform(authoredSource, id, {
|
|
149
188
|
environment,
|
|
@@ -152,6 +191,7 @@ export default function octaneLoader(source, inputSourceMap) {
|
|
|
152
191
|
profile,
|
|
153
192
|
...(clientOnlyImports.length > 0 ? { clientOnlyImports } : null),
|
|
154
193
|
...(isDescriptorChildrenImport === null ? null : { isDescriptorChildrenImport }),
|
|
194
|
+
...(textTypeFacts === undefined ? null : { textTypeFacts }),
|
|
155
195
|
...cssModuleConstants?.transformOptions,
|
|
156
196
|
});
|
|
157
197
|
|
|
@@ -168,11 +208,16 @@ export default function octaneLoader(source, inputSourceMap) {
|
|
|
168
208
|
}
|
|
169
209
|
setBuildInfo(this._module, {
|
|
170
210
|
canonicalId: canonicalModuleId(id, root),
|
|
211
|
+
resourceQuery: id.slice(cleanModuleId(id).length),
|
|
171
212
|
transformKind: result.kind,
|
|
213
|
+
...(result.streamedSignals === true ? { streamedSignals: true } : null),
|
|
172
214
|
serverRpc:
|
|
173
215
|
result.kind === 'compile' &&
|
|
174
216
|
(result.code.includes('_$__serverRpc(') ||
|
|
175
217
|
result.code.includes('export const _$_server_$_')),
|
|
218
|
+
...(Array.isArray(result.independentWidgets) && result.independentWidgets.length > 0
|
|
219
|
+
? { independentWidgets: result.independentWidgets }
|
|
220
|
+
: null),
|
|
176
221
|
...(result.universalRuntime === undefined
|
|
177
222
|
? null
|
|
178
223
|
: { universalRuntime: result.universalRuntime }),
|
|
@@ -206,18 +251,33 @@ export default function octaneLoader(source, inputSourceMap) {
|
|
|
206
251
|
/\.(?:tsrx|tsx)$/.test(cleanModuleId(id)) &&
|
|
207
252
|
/<\s*[A-Z_$]/.test(authoredSource) &&
|
|
208
253
|
authoredSource.includes('import');
|
|
209
|
-
if (requests.length > 0 || mayUseDescriptorImports) {
|
|
254
|
+
if (requests.length > 0 || mayUseDescriptorImports || textTypes) {
|
|
210
255
|
const asyncCallback = this.async?.() ?? callback;
|
|
211
256
|
Promise.all([
|
|
212
257
|
requests.length > 0 ? resolveClientOnlyImports(this, compiler, authoredSource, id) : [],
|
|
213
258
|
mayUseDescriptorImports ? loadDescriptorChildrenImports(this, authoredSource, id) : null,
|
|
259
|
+
textTypes
|
|
260
|
+
? textTypeFactsForLoader(
|
|
261
|
+
this._compiler,
|
|
262
|
+
options.textTypes.tsconfig,
|
|
263
|
+
compilerOptions.renderers,
|
|
264
|
+
cleanModuleId(id),
|
|
265
|
+
authoredSource,
|
|
266
|
+
).then((facts) => ({
|
|
267
|
+
...facts,
|
|
268
|
+
// The neutral compiler uses a project-relative module identity;
|
|
269
|
+
// the checker necessarily reads the real filesystem filename.
|
|
270
|
+
filename: textTypeFilename,
|
|
271
|
+
}))
|
|
272
|
+
: undefined,
|
|
214
273
|
]).then(
|
|
215
|
-
([imports, descriptorImport]) =>
|
|
274
|
+
([imports, descriptorImport, textTypeFacts]) =>
|
|
275
|
+
finish(imports, descriptorImport, textTypeFacts, asyncCallback),
|
|
216
276
|
(error) => asyncCallback(error instanceof Error ? error : new Error(String(error))),
|
|
217
277
|
);
|
|
218
278
|
return;
|
|
219
279
|
}
|
|
220
|
-
finish([], null, callback);
|
|
280
|
+
finish([], null, undefined, callback);
|
|
221
281
|
} catch (error) {
|
|
222
282
|
this.callback(error instanceof Error ? error : new Error(String(error)));
|
|
223
283
|
}
|
package/src/plugin.js
CHANGED
|
@@ -5,15 +5,22 @@ 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,
|
|
15
17
|
normalizePluginOptions,
|
|
16
18
|
} from './shared.js';
|
|
19
|
+
import {
|
|
20
|
+
disposeTextTypeCompiler,
|
|
21
|
+
invalidateTextTypeCompiler,
|
|
22
|
+
registerTextTypeCompiler,
|
|
23
|
+
} from './text-types.js';
|
|
17
24
|
|
|
18
25
|
const PLUGIN_NAME = 'OctaneRspackPlugin';
|
|
19
26
|
const PROFILE_DEFINE = '__OCTANE_PROFILE_ENABLED__';
|
|
@@ -177,7 +184,9 @@ function createDiscoveryCompiler(options, root, profile, specialization) {
|
|
|
177
184
|
root,
|
|
178
185
|
profile,
|
|
179
186
|
...(options.strong === undefined ? null : { strong: options.strong }),
|
|
180
|
-
...(options.
|
|
187
|
+
...(options.knownAttributeSpreads === undefined
|
|
188
|
+
? null
|
|
189
|
+
: { knownAttributeSpreads: options.knownAttributeSpreads }),
|
|
181
190
|
...(options.exclude === undefined ? null : { exclude: options.exclude }),
|
|
182
191
|
...(renderers === undefined ? null : { renderers }),
|
|
183
192
|
...(universalRuntime === undefined ? null : { universalRuntime }),
|
|
@@ -230,16 +239,17 @@ function visitClientReferenceModules(
|
|
|
230
239
|
inheritedChunks,
|
|
231
240
|
visit,
|
|
232
241
|
seen = new Set(),
|
|
242
|
+
executableModule = module,
|
|
233
243
|
) {
|
|
234
244
|
if (!module || seen.has(module)) return;
|
|
235
245
|
seen.add(module);
|
|
236
246
|
const chunks = moduleChunks(compilation, module, inheritedChunks);
|
|
237
|
-
visit(module, chunks);
|
|
247
|
+
visit(module, chunks, executableModule);
|
|
238
248
|
for (const child of iterable(module.modules)) {
|
|
239
|
-
visitClientReferenceModules(compilation, child, chunks, visit, seen);
|
|
249
|
+
visitClientReferenceModules(compilation, child, chunks, visit, seen, module);
|
|
240
250
|
}
|
|
241
251
|
if (module.rootModule) {
|
|
242
|
-
visitClientReferenceModules(compilation, module.rootModule, chunks, visit, seen);
|
|
252
|
+
visitClientReferenceModules(compilation, module.rootModule, chunks, visit, seen, module);
|
|
243
253
|
}
|
|
244
254
|
}
|
|
245
255
|
|
|
@@ -275,6 +285,158 @@ function emitClientReferenceManifest(compiler, compilation) {
|
|
|
275
285
|
);
|
|
276
286
|
}
|
|
277
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
|
+
|
|
278
440
|
function defineMatchesBoolean(value, expected) {
|
|
279
441
|
return value === expected || value === JSON.stringify(expected);
|
|
280
442
|
}
|
|
@@ -360,6 +522,16 @@ export class OctaneRspackPlugin {
|
|
|
360
522
|
compiler.options.mode === 'production' &&
|
|
361
523
|
!dev &&
|
|
362
524
|
!hotModuleReplacement;
|
|
525
|
+
// Loader worker pools cannot share one TypeScript Program. Watch and HMR
|
|
526
|
+
// use syntax-only compilation, including production-mode watch builds.
|
|
527
|
+
const textTypes =
|
|
528
|
+
this.options.textTypes !== undefined &&
|
|
529
|
+
compiler.options.mode === 'production' &&
|
|
530
|
+
!dev &&
|
|
531
|
+
!hotModuleReplacement;
|
|
532
|
+
const tsconfig = textTypes
|
|
533
|
+
? realRoot(resolve(root, this.options.textTypes.tsconfig))
|
|
534
|
+
: undefined;
|
|
363
535
|
assertProfilingDefineAvailable(compiler, profile);
|
|
364
536
|
saltPersistentCacheVersion(compiler, {
|
|
365
537
|
root,
|
|
@@ -368,7 +540,7 @@ export class OctaneRspackPlugin {
|
|
|
368
540
|
dev,
|
|
369
541
|
profile,
|
|
370
542
|
strong: this.options.strong === true,
|
|
371
|
-
|
|
543
|
+
knownAttributeSpreads: this.options.knownAttributeSpreads,
|
|
372
544
|
exclude: this.options.exclude ?? [],
|
|
373
545
|
renderers: this.options.renderers?.signature,
|
|
374
546
|
runtime: this.options.runtime,
|
|
@@ -379,7 +551,14 @@ export class OctaneRspackPlugin {
|
|
|
379
551
|
requireDirective: this.options.requireDirective === true,
|
|
380
552
|
transpile: this.options.transpile !== false,
|
|
381
553
|
cssModuleConstants,
|
|
554
|
+
textTypes: tsconfig,
|
|
382
555
|
});
|
|
556
|
+
if (tsconfig !== undefined) {
|
|
557
|
+
registerTextTypeCompiler(compiler, tsconfig, root);
|
|
558
|
+
compiler.hooks.run?.tap(PLUGIN_NAME, () => invalidateTextTypeCompiler(compiler));
|
|
559
|
+
compiler.hooks.watchRun?.tap(PLUGIN_NAME, () => invalidateTextTypeCompiler(compiler));
|
|
560
|
+
compiler.hooks.shutdown?.tap(PLUGIN_NAME, () => disposeTextTypeCompiler(compiler));
|
|
561
|
+
}
|
|
383
562
|
installProfilingDefine(compiler, profile);
|
|
384
563
|
if (cssModuleConstants) {
|
|
385
564
|
installCssModuleConstants(compiler, {
|
|
@@ -409,9 +588,9 @@ export class OctaneRspackPlugin {
|
|
|
409
588
|
environment,
|
|
410
589
|
profile,
|
|
411
590
|
...(this.options.strong === undefined ? null : { strong: this.options.strong }),
|
|
412
|
-
...(this.options.
|
|
591
|
+
...(this.options.knownAttributeSpreads === undefined
|
|
413
592
|
? null
|
|
414
|
-
: {
|
|
593
|
+
: { knownAttributeSpreads: this.options.knownAttributeSpreads }),
|
|
415
594
|
...(this.options.hmr === undefined ? null : { hmr: this.options.hmr }),
|
|
416
595
|
...(this.options.dev === undefined ? null : { dev: this.options.dev }),
|
|
417
596
|
...(this.options.exclude === undefined ? null : { exclude: this.options.exclude }),
|
|
@@ -425,13 +604,14 @@ export class OctaneRspackPlugin {
|
|
|
425
604
|
...(this.options.requireDirective === undefined
|
|
426
605
|
? null
|
|
427
606
|
: { requireDirective: this.options.requireDirective }),
|
|
607
|
+
...(tsconfig === undefined ? null : { textTypes: { tsconfig } }),
|
|
428
608
|
};
|
|
429
609
|
compiler.options.module.rules.push({
|
|
430
610
|
test: OCTANE_RULE,
|
|
431
611
|
type: 'javascript/auto',
|
|
432
612
|
enforce: 'pre',
|
|
433
613
|
use:
|
|
434
|
-
this.options.parallel === false
|
|
614
|
+
this.options.parallel === false || textTypes
|
|
435
615
|
? [{ loader: loaderPath, options: loaderOptions }]
|
|
436
616
|
: [
|
|
437
617
|
{ loader: finalizeLoaderPath, options: loaderOptions },
|
|
@@ -497,12 +677,56 @@ export class OctaneRspackPlugin {
|
|
|
497
677
|
addDependencies(compilation.fileDependencies, current.dependencies);
|
|
498
678
|
addDependencies(compilation.missingDependencies, current.missingDependencies);
|
|
499
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
|
+
);
|
|
500
716
|
compilation.hooks.processAssets.tap(
|
|
501
717
|
{
|
|
502
718
|
name: PLUGIN_NAME,
|
|
503
719
|
stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_REPORT,
|
|
504
720
|
},
|
|
505
|
-
() =>
|
|
721
|
+
() => {
|
|
722
|
+
emitClientReferenceManifest(compiler, compilation);
|
|
723
|
+
emitIndependentHydrationManifest(
|
|
724
|
+
compiler,
|
|
725
|
+
compilation,
|
|
726
|
+
this.options.clientBuildMode ??
|
|
727
|
+
(compiler.options.mode === 'development' ? 'development' : 'production'),
|
|
728
|
+
);
|
|
729
|
+
},
|
|
506
730
|
);
|
|
507
731
|
}
|
|
508
732
|
});
|
package/src/shared.js
CHANGED
|
@@ -41,12 +41,13 @@ const LOADER_OPTION_KEYS = new Set([
|
|
|
41
41
|
'dev',
|
|
42
42
|
'profile',
|
|
43
43
|
'strong',
|
|
44
|
-
'
|
|
44
|
+
'knownAttributeSpreads',
|
|
45
45
|
'exclude',
|
|
46
46
|
'renderers',
|
|
47
47
|
'requireDirective',
|
|
48
48
|
'universalRuntime',
|
|
49
49
|
'layerSpecializations',
|
|
50
|
+
'textTypes',
|
|
50
51
|
]);
|
|
51
52
|
const PLUGIN_OPTION_KEYS = new Set([
|
|
52
53
|
...LOADER_OPTION_KEYS,
|
|
@@ -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' &&
|
|
@@ -209,7 +221,6 @@ function normalizeOptions(value, plugin) {
|
|
|
209
221
|
assertBooleanOption(options, 'dev');
|
|
210
222
|
assertBooleanOption(options, 'profile');
|
|
211
223
|
assertBooleanOption(options, 'strong');
|
|
212
|
-
assertBooleanOption(options, 'nativeReads');
|
|
213
224
|
assertBooleanOption(options, 'requireDirective');
|
|
214
225
|
if (
|
|
215
226
|
options.exclude !== undefined &&
|
|
@@ -218,6 +229,21 @@ function normalizeOptions(value, plugin) {
|
|
|
218
229
|
throw new TypeError('@octanejs/rspack-plugin: `exclude` must be an array of path strings.');
|
|
219
230
|
}
|
|
220
231
|
if (plugin) assertBooleanOption(options, 'transpile');
|
|
232
|
+
if (options.textTypes !== undefined) {
|
|
233
|
+
if (
|
|
234
|
+
options.textTypes === null ||
|
|
235
|
+
typeof options.textTypes !== 'object' ||
|
|
236
|
+
Array.isArray(options.textTypes) ||
|
|
237
|
+
Object.keys(options.textTypes).some((key) => key !== 'tsconfig') ||
|
|
238
|
+
typeof options.textTypes.tsconfig !== 'string' ||
|
|
239
|
+
options.textTypes.tsconfig.trim() !== options.textTypes.tsconfig ||
|
|
240
|
+
!options.textTypes.tsconfig
|
|
241
|
+
) {
|
|
242
|
+
throw new TypeError(
|
|
243
|
+
'@octanejs/rspack-plugin: `textTypes` must be an object with a non-empty `tsconfig` path.',
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
221
247
|
if (
|
|
222
248
|
plugin &&
|
|
223
249
|
options.cssModuleConstants !== undefined &&
|
|
@@ -241,7 +267,9 @@ function normalizeOptions(value, plugin) {
|
|
|
241
267
|
...(options.dev === undefined ? null : { dev: options.dev }),
|
|
242
268
|
...(options.profile === undefined ? null : { profile: options.profile }),
|
|
243
269
|
...(options.strong === undefined ? null : { strong: options.strong }),
|
|
244
|
-
...(options.
|
|
270
|
+
...(options.knownAttributeSpreads === undefined
|
|
271
|
+
? null
|
|
272
|
+
: { knownAttributeSpreads: options.knownAttributeSpreads }),
|
|
245
273
|
...(options.exclude === undefined ? null : { exclude: [...options.exclude] }),
|
|
246
274
|
...(renderers === undefined ? null : { renderers }),
|
|
247
275
|
...(universalRuntime === undefined ? null : { universalRuntime }),
|
|
@@ -249,7 +277,13 @@ function normalizeOptions(value, plugin) {
|
|
|
249
277
|
...(options.requireDirective === undefined
|
|
250
278
|
? null
|
|
251
279
|
: { requireDirective: options.requireDirective }),
|
|
280
|
+
...(options.textTypes === undefined
|
|
281
|
+
? null
|
|
282
|
+
: { textTypes: Object.freeze({ tsconfig: options.textTypes.tsconfig }) }),
|
|
252
283
|
...(plugin && parallel !== undefined ? { parallel } : null),
|
|
284
|
+
...(plugin && options.clientBuildMode !== undefined
|
|
285
|
+
? { clientBuildMode: options.clientBuildMode }
|
|
286
|
+
: null),
|
|
253
287
|
...(plugin && options.transpile !== undefined ? { transpile: options.transpile } : null),
|
|
254
288
|
...(plugin && options.runtime !== undefined ? { runtime: options.runtime } : null),
|
|
255
289
|
...(plugin && options.cssModuleConstants !== undefined
|
|
@@ -291,6 +325,8 @@ export function getOctaneRspackBuildInfo(module) {
|
|
|
291
325
|
value.transformKind === 'slots' ||
|
|
292
326
|
value.transformKind === 'client-only-stub') &&
|
|
293
327
|
typeof value.serverRpc === 'boolean' &&
|
|
328
|
+
(value.resourceQuery === undefined || typeof value.resourceQuery === 'string') &&
|
|
329
|
+
(value.independentWidgets === undefined || Array.isArray(value.independentWidgets)) &&
|
|
294
330
|
(value.clientReference === undefined || nestedReferenceValid) &&
|
|
295
331
|
(value.universalRuntime === undefined || universalRuntimeValid)
|
|
296
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
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type analysis is an opt-in production build concern. Keep TypeScript out of
|
|
3
|
+
* the ordinary loader's module graph and retain one project per compiler and
|
|
4
|
+
* renderer configuration, rather than one TypeScript Program per module.
|
|
5
|
+
*/
|
|
6
|
+
// Rspack loads the plugin from its application's module graph and the loader
|
|
7
|
+
// through its loader runner. Those can instantiate this ESM module separately
|
|
8
|
+
// (for example under Vitest), even though both receive the same compiler.
|
|
9
|
+
// Keep the project on that compiler under a process-wide symbol instead of in
|
|
10
|
+
// module-local state. Typed builds use the main-thread loader.
|
|
11
|
+
const COMPILER_TEXT_TYPES = Symbol.for('@octanejs/rspack-plugin/text-types/v1');
|
|
12
|
+
|
|
13
|
+
function compilerState(compiler) {
|
|
14
|
+
return compiler?.[COMPILER_TEXT_TYPES];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function registerTextTypeCompiler(compiler, tsconfig, root) {
|
|
18
|
+
if (compilerState(compiler)) {
|
|
19
|
+
throw new Error('@octanejs/rspack-plugin: only one text type project may own a compiler.');
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(compiler, COMPILER_TEXT_TYPES, {
|
|
22
|
+
value: { tsconfig, root, projects: new Map(), closed: false },
|
|
23
|
+
configurable: true,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function invalidateTextTypeCompiler(compiler) {
|
|
28
|
+
const state = compilerState(compiler);
|
|
29
|
+
if (!state || state.closed) return;
|
|
30
|
+
for (const project of state.projects.values()) project.invalidate();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function disposeTextTypeCompiler(compiler) {
|
|
34
|
+
const state = compilerState(compiler);
|
|
35
|
+
if (!state) return;
|
|
36
|
+
state.closed = true;
|
|
37
|
+
for (const project of state.projects.values()) project.dispose();
|
|
38
|
+
state.projects.clear();
|
|
39
|
+
delete compiler[COMPILER_TEXT_TYPES];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function textTypeFactsForLoader(compiler, tsconfig, renderers, filename, source) {
|
|
43
|
+
const state = compilerState(compiler);
|
|
44
|
+
if (!state || state.tsconfig !== tsconfig || state.closed) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
'@octanejs/rspack-plugin: `textTypes` requires the OctaneRspackPlugin on the same compiler.',
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
// The optional TypeScript peer and Volar adapter are loaded only by an opted-in
|
|
50
|
+
// production compiler. import() also shares its module initialization across
|
|
51
|
+
// concurrently built modules without retaining a checker in loader options.
|
|
52
|
+
const { createTextTypeProject } = await import('octane/compiler/typescript');
|
|
53
|
+
if (state.closed)
|
|
54
|
+
throw new Error('@octanejs/rspack-plugin: compiler closed during type analysis.');
|
|
55
|
+
const key = renderers?.signature ?? 'dom';
|
|
56
|
+
let project = state.projects.get(key);
|
|
57
|
+
if (!project) {
|
|
58
|
+
project = createTextTypeProject({ tsconfig, root: state.root, renderers });
|
|
59
|
+
state.projects.set(key, project);
|
|
60
|
+
}
|
|
61
|
+
return project.snapshot(filename, source);
|
|
62
|
+
}
|
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,8 +144,8 @@ export interface OctaneRspackLoaderOptions {
|
|
|
144
144
|
* @default false
|
|
145
145
|
*/
|
|
146
146
|
strong?: boolean;
|
|
147
|
-
/**
|
|
148
|
-
|
|
147
|
+
/** Fixed native-attribute shapes for trusted imported spread helpers. */
|
|
148
|
+
knownAttributeSpreads?: readonly KnownAttributeSpread[];
|
|
149
149
|
/**
|
|
150
150
|
* Path fragments excluded from the plain `.ts`/`.js` hook-slot pass. With
|
|
151
151
|
* `requireDirective`, excluded paths are exempt from Octane ownership
|
|
@@ -177,6 +177,19 @@ export interface OctaneRspackLoaderOptions {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
export interface OctaneRspackPluginOptions extends OctaneRspackLoaderOptions {
|
|
180
|
+
/** Build intent for SSR metadata; independent of optimization/HMR settings. */
|
|
181
|
+
clientBuildMode?: 'production' | 'development';
|
|
182
|
+
/**
|
|
183
|
+
* @experimental Prove primitive DOM text children from the TypeScript project
|
|
184
|
+
* in one-shot production builds. Relative paths resolve from the plugin root.
|
|
185
|
+
* Requires the optional TypeScript peer. Uses one main-thread checker per
|
|
186
|
+
* compiler, and typed modules bypass Rspack's persistent module cache so
|
|
187
|
+
* imported type edits are observed on the next build. Watch/HMR and
|
|
188
|
+
* development builds retain syntax-only classification. Configure the same
|
|
189
|
+
* tsconfig and renderers for browser and server compilation.
|
|
190
|
+
* @default undefined
|
|
191
|
+
*/
|
|
192
|
+
textTypes?: { tsconfig: string };
|
|
180
193
|
/**
|
|
181
194
|
* @experimental Fold proven CSS-module strings in one-shot production builds.
|
|
182
195
|
* `true` accepts only pure, initialized named ESM string exports. A provider
|
|
@@ -217,8 +230,25 @@ export interface OctaneRspackPluginOptions extends OctaneRspackLoaderOptions {
|
|
|
217
230
|
|
|
218
231
|
export interface OctaneRspackBuildInfo {
|
|
219
232
|
canonicalId: string;
|
|
233
|
+
/** Resource query retained separately from the canonical source identity. */
|
|
234
|
+
resourceQuery?: string;
|
|
220
235
|
transformKind: 'compile' | 'slots' | 'client-only-stub';
|
|
236
|
+
streamedSignals?: true;
|
|
221
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
|
+
}[];
|
|
222
252
|
/** Universal host runtime/thread identity, when this module was specialized. */
|
|
223
253
|
universalRuntime?: OctaneUniversalRuntimeOptions;
|
|
224
254
|
/** Stable identity shared by the client compile and its inert server stub. */
|