octane 0.1.9 → 0.1.11
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/dist/compiler/bundler.js +27 -1
- package/dist/compiler/compile-renderer-boundaries.js +130 -1
- package/dist/compiler/compile-universal.js +847 -0
- package/dist/compiler/compile.js +96 -23
- package/dist/compiler/renderers.js +116 -11
- package/dist/compiler/slot-hooks.js +2 -2
- package/dist/compiler/universal-runtime.js +46 -0
- package/dist/compiler/vite.d.ts +13 -0
- package/dist/compiler/volar.js +68 -5
- package/dist/hydration/event-capture.d.ts +30 -0
- package/dist/hydration/event-capture.js +152 -0
- package/dist/hydration/index.d.ts +1 -0
- package/dist/hydration/index.js +2 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +8 -0
- package/dist/react/index.d.ts +15 -6
- package/dist/react/index.js +2 -2
- package/dist/react/server.d.ts +3 -2
- package/dist/react/server.js +6 -5
- package/dist/react/shared.d.ts +45 -0
- package/dist/react/shared.js +34 -7
- package/dist/runtime.d.ts +49 -4
- package/dist/runtime.js +77 -145
- package/dist/runtime.server.d.ts +60 -6
- package/dist/runtime.server.js +186 -15
- package/dist/server/index.d.ts +1 -1
- package/dist/tsrx-iterable.d.ts +10 -0
- package/dist/tsrx-iterable.js +4 -0
- package/dist/tsrx-spread.d.ts +13 -0
- package/dist/tsrx-spread.js +10 -0
- package/dist/universal-core.d.ts +584 -0
- package/dist/universal-core.js +5417 -0
- package/dist/universal-dom-boundary.d.ts +14 -0
- package/dist/universal-dom-boundary.js +155 -0
- package/dist/universal-native.d.ts +19 -0
- package/dist/universal-native.js +19 -0
- package/dist/universal.d.ts +7 -571
- package/dist/universal.js +4 -5528
- package/package.json +10 -11
package/dist/compiler/bundler.js
CHANGED
|
@@ -12,13 +12,18 @@ import { createRequire } from 'node:module';
|
|
|
12
12
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
13
13
|
import { parseModule } from '@tsrx/core';
|
|
14
14
|
import { compile, hasOnlyLowerableNullishExits, isVoidJsxCodeBlockFunction } from './compile.js';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
addSourceMapNeedles,
|
|
17
|
+
composeSourceMaps,
|
|
18
|
+
validateRendererModuleSource,
|
|
19
|
+
} from './compile-universal.js';
|
|
16
20
|
import {
|
|
17
21
|
hydrateBoundaryPathFromId,
|
|
18
22
|
prepareHydrateBoundaries,
|
|
19
23
|
prepareServerHydrateBoundaries,
|
|
20
24
|
} from './hydrate-boundaries.js';
|
|
21
25
|
import { normalizeRendererConfig, resolveRendererForFile } from './renderers.js';
|
|
26
|
+
import { normalizeUniversalRuntime } from './universal-runtime.js';
|
|
22
27
|
import {
|
|
23
28
|
analyzeNativeChangeDiagnostics,
|
|
24
29
|
formatCompileDiagnostic,
|
|
@@ -370,6 +375,7 @@ class OctaneBundlerCompiler {
|
|
|
370
375
|
hmr: normalizeHmrDialect(options.hmr),
|
|
371
376
|
dev: options.dev,
|
|
372
377
|
profile: options.profile === true,
|
|
378
|
+
universalRuntime: normalizeUniversalRuntime(options.universalRuntime),
|
|
373
379
|
};
|
|
374
380
|
this.renderers = normalizeRendererConfig(options.renderers);
|
|
375
381
|
// Ownership gate for mixed-toolchain projects (e.g. a React app hosting
|
|
@@ -830,6 +836,9 @@ class OctaneBundlerCompiler {
|
|
|
830
836
|
// of both HMR and dev hydration diagnostics. Server transforms stay byte-for-
|
|
831
837
|
// byte identical even when a shared client/server bundler configuration opts in.
|
|
832
838
|
const profile = environment === 'client' && (options.profile ?? this.defaults.profile) === true;
|
|
839
|
+
const universalRuntime = normalizeUniversalRuntime(
|
|
840
|
+
options.universalRuntime ?? this.defaults.universalRuntime,
|
|
841
|
+
);
|
|
833
842
|
const filename = this._canonicalModuleId(file);
|
|
834
843
|
const clientOnlyImports =
|
|
835
844
|
environment === 'server' && Array.isArray(options.clientOnlyImports)
|
|
@@ -854,6 +863,21 @@ class OctaneBundlerCompiler {
|
|
|
854
863
|
// The directive is a build-time ownership signal only — never ship it.
|
|
855
864
|
// Blanking (not deleting) keeps positions stable for source maps.
|
|
856
865
|
const source = directive === null ? code : stripDirective(code, directive);
|
|
866
|
+
const plainHelperSource =
|
|
867
|
+
(file.endsWith('.ts') || file.endsWith('.js')) && !file.endsWith('.d.ts');
|
|
868
|
+
if (
|
|
869
|
+
plainHelperSource &&
|
|
870
|
+
renderer.target === 'universal' &&
|
|
871
|
+
renderer.validation !== undefined &&
|
|
872
|
+
this._isProjectOwnedSource(file) &&
|
|
873
|
+
!this.exclude.some((path) => file.includes(path)) &&
|
|
874
|
+
!hostOwned
|
|
875
|
+
) {
|
|
876
|
+
// Renderer rules also own the runtime assumptions of their project-local
|
|
877
|
+
// helper modules. Validate those assumptions without claiming their output:
|
|
878
|
+
// the existing hook-slot/pass-through branch below remains authoritative.
|
|
879
|
+
validateRendererModuleSource(source, filename, renderer);
|
|
880
|
+
}
|
|
857
881
|
if (fullCompile) {
|
|
858
882
|
const profileFilename = profile ? this._profileModuleId(file, collected) : undefined;
|
|
859
883
|
const clientReference =
|
|
@@ -908,6 +932,7 @@ class OctaneBundlerCompiler {
|
|
|
908
932
|
dev,
|
|
909
933
|
profile,
|
|
910
934
|
profileFilename,
|
|
935
|
+
...(universalRuntime === undefined ? null : { universalRuntime }),
|
|
911
936
|
// Keep the established DOM compiler call byte-for-byte equivalent. A
|
|
912
937
|
// renderer descriptor is an orthogonal compiler input only for the
|
|
913
938
|
// universal branch selected at this template boundary.
|
|
@@ -934,6 +959,7 @@ class OctaneBundlerCompiler {
|
|
|
934
959
|
diagnostics: out.diagnostics,
|
|
935
960
|
kind: 'compile',
|
|
936
961
|
renderer,
|
|
962
|
+
...(out.universalRuntime === undefined ? null : { universalRuntime: out.universalRuntime }),
|
|
937
963
|
...(clientReference === null ? null : { clientReference }),
|
|
938
964
|
...(environment === 'client' && options.collectVoidComponentExports === true
|
|
939
965
|
? { voidComponentExports: findVoidComponentExports(compileSource, filename) }
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
lowerUniversalRendererRegion,
|
|
8
8
|
originsFromSourceMap,
|
|
9
|
+
rendererValidationImportReferences,
|
|
9
10
|
sourceMapFromOrigins,
|
|
10
11
|
} from './compile-universal.js';
|
|
11
12
|
import { parseModule } from '@tsrx/core';
|
|
@@ -499,6 +500,7 @@ function collectRuntimeCallNames(node, runtime) {
|
|
|
499
500
|
function collectLocalSpecializationInfo(source, filename) {
|
|
500
501
|
const ast = parseModule(source, filename);
|
|
501
502
|
const components = new Map();
|
|
503
|
+
const exported = new Set();
|
|
502
504
|
const runtime = { direct: new Map(), namespaces: new Set(), moduleBindings: new Set() };
|
|
503
505
|
for (const statement of ast.body ?? []) {
|
|
504
506
|
if (statement.type === 'ImportDeclaration') {
|
|
@@ -529,8 +531,93 @@ function collectLocalSpecializationInfo(source, filename) {
|
|
|
529
531
|
for (const statement of ast.body ?? []) {
|
|
530
532
|
const component = localComponentDeclaration(statement, runtime);
|
|
531
533
|
if (component !== null) components.set(component.name, component);
|
|
534
|
+
if (statement.type === 'ExportNamedDeclaration' && statement.source == null) {
|
|
535
|
+
if (component !== null) exported.add(component.name);
|
|
536
|
+
for (const specifier of statement.specifiers ?? []) {
|
|
537
|
+
if (specifier.local?.name) exported.add(specifier.local.name);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if (statement.type === 'ExportDefaultDeclaration') {
|
|
541
|
+
if (component !== null) exported.add(component.name);
|
|
542
|
+
if (statement.declaration?.type === 'Identifier') exported.add(statement.declaration.name);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return { ast, components, exported, runtime };
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
function includedOriginalPredicate(origins, sourceLength) {
|
|
549
|
+
const included = new Uint8Array(sourceLength + 1);
|
|
550
|
+
for (const origin of origins) {
|
|
551
|
+
if (origin >= 0 && origin < sourceLength) included[origin] = 1;
|
|
552
|
+
}
|
|
553
|
+
const prefix = new Uint32Array(sourceLength + 1);
|
|
554
|
+
for (let index = 0; index < sourceLength; index++) {
|
|
555
|
+
prefix[index + 1] = prefix[index] + included[index];
|
|
556
|
+
}
|
|
557
|
+
return (node) => {
|
|
558
|
+
if (typeof node?.start !== 'number' || typeof node?.end !== 'number') return false;
|
|
559
|
+
const start = Math.max(0, Math.min(sourceLength, node.start));
|
|
560
|
+
const end = Math.max(start, Math.min(sourceLength, node.end));
|
|
561
|
+
return prefix[end] !== prefix[start];
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function owningComponentForReference(components, node) {
|
|
566
|
+
for (const component of components.values()) {
|
|
567
|
+
if (component.declaration.start <= node.start && node.end <= component.declaration.end) {
|
|
568
|
+
return component.name;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return null;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
function ownerReachableComponents(sourceLength, origins, localSpecializations) {
|
|
575
|
+
const localNames = new Set(localSpecializations.components.keys());
|
|
576
|
+
const isIncluded = includedOriginalPredicate(origins, sourceLength);
|
|
577
|
+
const dependencies = new Map();
|
|
578
|
+
const reachable = new Set(
|
|
579
|
+
[...localSpecializations.exported].filter((name) => localNames.has(name)),
|
|
580
|
+
);
|
|
581
|
+
const record = (node, name) => {
|
|
582
|
+
if (!localNames.has(name) || !isIncluded(node)) return;
|
|
583
|
+
const owner = owningComponentForReference(localSpecializations.components, node);
|
|
584
|
+
if (owner === null) {
|
|
585
|
+
reachable.add(name);
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
let references = dependencies.get(owner);
|
|
589
|
+
if (references === undefined) dependencies.set(owner, (references = new Set()));
|
|
590
|
+
references.add(name);
|
|
591
|
+
};
|
|
592
|
+
walkScopedReferences(localSpecializations.ast, {
|
|
593
|
+
call: record,
|
|
594
|
+
tag: record,
|
|
595
|
+
});
|
|
596
|
+
const queue = [...reachable];
|
|
597
|
+
while (queue.length > 0) {
|
|
598
|
+
for (const dependency of dependencies.get(queue.shift()) ?? []) {
|
|
599
|
+
if (reachable.has(dependency)) continue;
|
|
600
|
+
reachable.add(dependency);
|
|
601
|
+
queue.push(dependency);
|
|
602
|
+
}
|
|
532
603
|
}
|
|
533
|
-
return
|
|
604
|
+
return reachable;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function maskOriginalRanges(origins, sourceLength, ranges) {
|
|
608
|
+
if (ranges.length === 0) return origins;
|
|
609
|
+
const masked = new Uint8Array(sourceLength);
|
|
610
|
+
for (const range of ranges) {
|
|
611
|
+
const start = Math.max(0, Math.min(sourceLength, range.start));
|
|
612
|
+
const end = Math.max(start, Math.min(sourceLength, range.end));
|
|
613
|
+
masked.fill(1, start, end);
|
|
614
|
+
}
|
|
615
|
+
const output = new Int32Array(origins);
|
|
616
|
+
for (let index = 0; index < output.length; index++) {
|
|
617
|
+
const origin = output[index];
|
|
618
|
+
if (origin >= 0 && origin < sourceLength && masked[origin] === 1) output[index] = -1;
|
|
619
|
+
}
|
|
620
|
+
return output;
|
|
534
621
|
}
|
|
535
622
|
|
|
536
623
|
function remapText(code, relativeOrigins, input) {
|
|
@@ -683,6 +770,7 @@ function specializeLocalComponents(value, kind, index, state) {
|
|
|
683
770
|
queue.push(reference);
|
|
684
771
|
}
|
|
685
772
|
}
|
|
773
|
+
for (const name of selected) state.specializedLocalNames.add(name);
|
|
686
774
|
|
|
687
775
|
const prefix = `__octaneRendererRegion${index}`;
|
|
688
776
|
const cloneNames = new Map();
|
|
@@ -812,8 +900,12 @@ function lowerBoundaryNode(node, ownerRenderer, state) {
|
|
|
812
900
|
profileFilename: state.profileFilename,
|
|
813
901
|
regionOrigins: specialization.region.origins,
|
|
814
902
|
runtimeImports: specialization.runtimeImports,
|
|
903
|
+
universalRuntime: state.universalRuntime,
|
|
815
904
|
},
|
|
816
905
|
);
|
|
906
|
+
for (const reference of lowered.validationImportReferences) {
|
|
907
|
+
state.childValidationImportReferences.set(`${reference.start}:${reference.end}`, reference);
|
|
908
|
+
}
|
|
817
909
|
state.preludes.push({ code: lowered.prelude, origins: lowered.preludeOrigins });
|
|
818
910
|
state.universalUnits.push(lowered.metadata);
|
|
819
911
|
for (const mapping of lowered.mappings) {
|
|
@@ -859,6 +951,7 @@ export function prepareRendererBoundaryRegions(source, filename, ownerRenderer,
|
|
|
859
951
|
if (tree === null || tree.roots.length === 0) return null;
|
|
860
952
|
|
|
861
953
|
const state = {
|
|
954
|
+
childValidationImportReferences: new Map(),
|
|
862
955
|
domRegions: [],
|
|
863
956
|
filename,
|
|
864
957
|
hmr: options?.hmr === true ? 'vite' : options?.hmr || false,
|
|
@@ -870,6 +963,8 @@ export function prepareRendererBoundaryRegions(source, filename, ownerRenderer,
|
|
|
870
963
|
profileFilename: options?.profileFilename,
|
|
871
964
|
rendererRegistry,
|
|
872
965
|
source,
|
|
966
|
+
specializedLocalNames: new Set(),
|
|
967
|
+
universalRuntime: options?.universalRuntime,
|
|
873
968
|
universalUnits: [],
|
|
874
969
|
};
|
|
875
970
|
const replacements = [];
|
|
@@ -879,6 +974,7 @@ export function prepareRendererBoundaryRegions(source, filename, ownerRenderer,
|
|
|
879
974
|
}
|
|
880
975
|
|
|
881
976
|
let transformed = applySourceReplacements(source, 0, source.length, replacements);
|
|
977
|
+
const ownerSourceLength = transformed.code.length;
|
|
882
978
|
if (state.preludes.length > 0) {
|
|
883
979
|
transformed = concatMapped(
|
|
884
980
|
transformed,
|
|
@@ -892,6 +988,38 @@ export function prepareRendererBoundaryRegions(source, filename, ownerRenderer,
|
|
|
892
988
|
transformed = expandDomRendererRegionsMapped(transformed, state.domRegions);
|
|
893
989
|
state.domRegions = [];
|
|
894
990
|
}
|
|
991
|
+
let validationOrigins = transformed.origins;
|
|
992
|
+
if (ownerRenderer.validation !== undefined && state.preludes.length > 0) {
|
|
993
|
+
validationOrigins = new Int32Array(transformed.origins.length);
|
|
994
|
+
validationOrigins.fill(-1);
|
|
995
|
+
validationOrigins.set(transformed.origins.subarray(0, ownerSourceLength));
|
|
996
|
+
}
|
|
997
|
+
if (ownerRenderer.validation !== undefined && state.specializedLocalNames.size > 0) {
|
|
998
|
+
const reachable = ownerReachableComponents(
|
|
999
|
+
source.length,
|
|
1000
|
+
validationOrigins,
|
|
1001
|
+
state.localSpecializations,
|
|
1002
|
+
);
|
|
1003
|
+
const childOnlyDeclarations = [...state.specializedLocalNames]
|
|
1004
|
+
.filter((name) => !reachable.has(name))
|
|
1005
|
+
.map((name) => state.localSpecializations.components.get(name)?.declaration)
|
|
1006
|
+
.filter(Boolean);
|
|
1007
|
+
validationOrigins = maskOriginalRanges(validationOrigins, source.length, childOnlyDeclarations);
|
|
1008
|
+
}
|
|
1009
|
+
if (
|
|
1010
|
+
(ownerRenderer.validation?.forbiddenImports?.length ?? 0) > 0 &&
|
|
1011
|
+
state.childValidationImportReferences.size > 0
|
|
1012
|
+
) {
|
|
1013
|
+
const ownerReferences = new Set(
|
|
1014
|
+
rendererValidationImportReferences(source, filename, validationOrigins).map(
|
|
1015
|
+
(reference) => `${reference.start}:${reference.end}`,
|
|
1016
|
+
),
|
|
1017
|
+
);
|
|
1018
|
+
const childOnlyImports = [...state.childValidationImportReferences]
|
|
1019
|
+
.filter(([key]) => !ownerReferences.has(key))
|
|
1020
|
+
.map(([, reference]) => reference);
|
|
1021
|
+
validationOrigins = maskOriginalRanges(validationOrigins, source.length, childOnlyImports);
|
|
1022
|
+
}
|
|
895
1023
|
return Object.freeze({
|
|
896
1024
|
analysis: tree.analysis,
|
|
897
1025
|
domRegions: Object.freeze(state.domRegions),
|
|
@@ -901,6 +1029,7 @@ export function prepareRendererBoundaryRegions(source, filename, ownerRenderer,
|
|
|
901
1029
|
// scoped-style hashes after a region must be restamped from authored
|
|
902
1030
|
// coordinates (compile.js).
|
|
903
1031
|
origins: transformed.origins,
|
|
1032
|
+
...(ownerRenderer.validation === undefined ? {} : { validationOrigins }),
|
|
904
1033
|
source: transformed.code,
|
|
905
1034
|
universalUnits: Object.freeze(state.universalUnits),
|
|
906
1035
|
});
|