octane 0.16.6 → 0.16.7
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/cjs/runtime/engine.cjs +36 -0
- package/dist/cjs/runtime/hooks.cjs +5 -1
- package/dist/cjs/runtime/portals.cjs +12 -11
- package/dist/cjs/version.cjs +1 -1
- package/dist/compiler/bundler.d.ts +306 -0
- package/dist/compiler/bundler.js +68 -12
- package/dist/compiler/compile.js +90 -8
- package/dist/compiler/renderers.d.ts +109 -0
- package/dist/compiler/slot-hooks.d.ts +2 -0
- package/dist/compiler/slot-hooks.js +4 -2
- package/dist/compiler/vite.d.ts +8 -58
- package/dist/compiler/vite.js +74 -5
- package/dist/compiler/volar.js +53 -44
- package/dist/jsx-runtime-strong.d.ts +2 -2
- package/dist/jsx-runtime.d.ts +7 -7
- package/dist/node/reducer-dispatch.js +0 -0
- package/dist/node/runtime/engine.js +36 -0
- package/dist/node/runtime/hooks.js +5 -1
- package/dist/node/runtime/portals.js +13 -12
- package/dist/node/version.js +1 -1
- package/dist/react/react-compat-shared.d.ts +1 -1
- package/dist/reducer-dispatch.d.ts +1 -0
- package/dist/reducer-dispatch.js +0 -0
- package/dist/runtime/activity.d.ts +1 -1
- package/dist/runtime/elements.d.ts +2 -2
- package/dist/runtime/engine.js +36 -0
- package/dist/runtime/hooks.d.ts +2 -1
- package/dist/runtime/hooks.js +5 -1
- package/dist/runtime/portals.js +13 -12
- package/dist/runtime/suspense.d.ts +1 -1
- package/dist/runtime/types.d.ts +17 -16
- package/dist/runtime.server.d.ts +14 -13
- package/dist/strong.d.ts +2 -2
- package/dist/universal-core.d.ts +2 -1
- package/dist/version.js +1 -1
- package/package.json +9 -3
|
@@ -2293,9 +2293,45 @@ function flushSync(fn) {
|
|
|
2293
2293
|
if (import_drivers.CONTROLLED_RESTORE_DRIVER) import_drivers.CONTROLLED_RESTORE_DRIVER.restore();
|
|
2294
2294
|
return result;
|
|
2295
2295
|
}
|
|
2296
|
+
const DETACHES_BY_TARGET = /* @__PURE__ */ new Map();
|
|
2297
|
+
function dropUncommittedRefPairs(detaches) {
|
|
2298
|
+
const byTarget = DETACHES_BY_TARGET;
|
|
2299
|
+
for (let i = 0; i < detaches.length; i += 4) {
|
|
2300
|
+
const queued = byTarget.get(detaches[i + 1]);
|
|
2301
|
+
if (queued === void 0) byTarget.set(detaches[i + 1], i);
|
|
2302
|
+
else if (typeof queued === "number") byTarget.set(detaches[i + 1], [queued, i]);
|
|
2303
|
+
else queued.push(i);
|
|
2304
|
+
}
|
|
2305
|
+
let write = 0;
|
|
2306
|
+
for (let read = 0; read < refAttachQueue.length; read++) {
|
|
2307
|
+
const entry = refAttachQueue[read];
|
|
2308
|
+
const queued = byTarget.get(entry.el);
|
|
2309
|
+
if (queued !== void 0) {
|
|
2310
|
+
const live = entry.ref === attachLiveFragmentRef && (import_drivers.activityRefState ? import_drivers.activityRefState.get(entry.el)?.connected : null) == null;
|
|
2311
|
+
if (typeof queued === "number") {
|
|
2312
|
+
if (live || detaches[queued] === entry.ref) {
|
|
2313
|
+
detaches[queued] = null;
|
|
2314
|
+
byTarget.delete(entry.el);
|
|
2315
|
+
continue;
|
|
2316
|
+
}
|
|
2317
|
+
} else {
|
|
2318
|
+
const k = live ? 0 : queued.findIndex((i) => detaches[i] === entry.ref);
|
|
2319
|
+
if (k !== -1 && k < queued.length) {
|
|
2320
|
+
detaches[queued[k]] = null;
|
|
2321
|
+
queued.splice(k, 1);
|
|
2322
|
+
continue;
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
refAttachQueue[write++] = entry;
|
|
2327
|
+
}
|
|
2328
|
+
refAttachQueue.length = write;
|
|
2329
|
+
byTarget.clear();
|
|
2330
|
+
}
|
|
2296
2331
|
function drainQueuedRefDetaches() {
|
|
2297
2332
|
if (import_refs.refDetachQueue.length === 0) return;
|
|
2298
2333
|
const q = import_refs.refDetachQueue.splice(0);
|
|
2334
|
+
if (refAttachQueue.length !== 0) dropUncommittedRefPairs(q);
|
|
2299
2335
|
for (let i = 0; i < q.length; i += 4) {
|
|
2300
2336
|
try {
|
|
2301
2337
|
REF_CALLBACK_DEPTH++;
|
|
@@ -507,7 +507,11 @@ function readReducerHook(reducer, initialArg, initOrSlot, slot) {
|
|
|
507
507
|
function __useReducerWithGetter(reducer, initialArg, initOrSlot, slot) {
|
|
508
508
|
const s = readReducerHook(reducer, initialArg, initOrSlot, slot);
|
|
509
509
|
const getter = s.getter ??= () => latestHookValue(s, s.reducer);
|
|
510
|
-
return [
|
|
510
|
+
return [
|
|
511
|
+
s.queue === null ? s.value : foldHookQueue(s, reducer),
|
|
512
|
+
s.dispatch,
|
|
513
|
+
getter
|
|
514
|
+
];
|
|
511
515
|
}
|
|
512
516
|
function depsChanged(prev, next, hook = false) {
|
|
513
517
|
if (prev === void 0 || next === void 0) return true;
|
|
@@ -330,18 +330,19 @@ function renderPortalState(prev, parentBlock, target, rawBody, rawProps, host, e
|
|
|
330
330
|
state.start.$$portalParent = host;
|
|
331
331
|
}
|
|
332
332
|
state.host = host;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
(0, import_engine.journalRootProperty)(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
333
|
+
const block = state.block;
|
|
334
|
+
if (!(import_drivers.MEMO_BAIL && block.body === norm.body && (0, import_drivers.MEMO_BAIL)(block, norm.body, norm.props))) {
|
|
335
|
+
if (block.body !== norm.body) (0, import_engine.journalRootProperty)(block, "body", block.body);
|
|
336
|
+
if (block.props !== norm.props) (0, import_engine.journalRootProperty)(block, "props", block.props);
|
|
337
|
+
if (block.extra !== env) (0, import_engine.journalRootProperty)(block, "extra", block.extra);
|
|
338
|
+
block.body = norm.body;
|
|
339
|
+
block.props = norm.props;
|
|
340
|
+
block.extra = env;
|
|
341
|
+
if (typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__) {
|
|
342
|
+
(0, import_profiling.__profileTrackComponent)(block, (0, import_profile_probes.profilePortalComponent)(rawBody, norm.body));
|
|
343
|
+
}
|
|
344
|
+
(0, import_signal_owners.renderBlock)(block);
|
|
343
345
|
}
|
|
344
|
-
(0, import_signal_owners.renderBlock)(state.block);
|
|
345
346
|
}
|
|
346
347
|
let n = (0, import_templates.getNextSibling)(state.start);
|
|
347
348
|
if (state.interleavedFragment === void 0) {
|
package/dist/cjs/version.cjs
CHANGED
|
@@ -21,7 +21,7 @@ __export(version_exports, {
|
|
|
21
21
|
version: () => version
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(version_exports);
|
|
24
|
-
const version = "0.16.
|
|
24
|
+
const version = "0.16.7";
|
|
25
25
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
26
|
0 && (module.exports = {
|
|
27
27
|
version
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CompileDiagnostic,
|
|
3
|
+
CompileOptions,
|
|
4
|
+
CompileResult,
|
|
5
|
+
CompilerProgram,
|
|
6
|
+
CompileSourceMap,
|
|
7
|
+
OctaneCssModuleConstants,
|
|
8
|
+
} from './index.js';
|
|
9
|
+
import type {
|
|
10
|
+
OctaneRendererConfigOptions,
|
|
11
|
+
OctaneResolvedRenderer,
|
|
12
|
+
OctaneResolvedRendererConfig,
|
|
13
|
+
} from './renderers.js';
|
|
14
|
+
|
|
15
|
+
export { DOM_BINDING_COMPILER_ABI_VERSION } from './index.js';
|
|
16
|
+
export {
|
|
17
|
+
DOM_RENDERER_ID,
|
|
18
|
+
DOM_RENDERER_MODULE,
|
|
19
|
+
RENDERER_CONFIG_VERSION,
|
|
20
|
+
normalizeRendererConfig,
|
|
21
|
+
resolveRendererForFile,
|
|
22
|
+
} from './renderers.js';
|
|
23
|
+
export type {
|
|
24
|
+
OctaneRendererConfigOptions,
|
|
25
|
+
OctaneResolvedRenderer,
|
|
26
|
+
OctaneResolvedRendererConfig,
|
|
27
|
+
} from './renderers.js';
|
|
28
|
+
export { findVoidComponentImports, findVoidRootImports } from './slot-hooks.js';
|
|
29
|
+
export type { VoidComponentImport } from './slot-hooks.js';
|
|
30
|
+
|
|
31
|
+
export type OctaneEnvironment = 'client' | 'server';
|
|
32
|
+
|
|
33
|
+
/** Options for one compiler instance; `transform` may override the per-module ones. */
|
|
34
|
+
export interface OctaneCompilerOptions extends Pick<
|
|
35
|
+
CompileOptions,
|
|
36
|
+
'knownAttributeSpreads' | 'domBindingFixedProps' | 'opaqueSignalHandles' | 'universalRuntime'
|
|
37
|
+
> {
|
|
38
|
+
/** Project root for canonical module IDs and package-manifest discovery. @default process.cwd() */
|
|
39
|
+
root?: string;
|
|
40
|
+
/** @default 'client' */
|
|
41
|
+
environment?: OctaneEnvironment;
|
|
42
|
+
/** Opt into a typed compiler intermediate. The host emits JavaScript and composes maps. */
|
|
43
|
+
output?: 'js' | 'ts';
|
|
44
|
+
/** HMR code generation dialect; `true` means `'vite'`. Server transforms never emit HMR. */
|
|
45
|
+
hmr?: boolean | 'vite' | 'webpack';
|
|
46
|
+
/** Client development metadata. Defaults on whenever client HMR is on. */
|
|
47
|
+
dev?: boolean;
|
|
48
|
+
/** Component profiling metadata in client transforms. */
|
|
49
|
+
profile?: boolean;
|
|
50
|
+
/** @default true */
|
|
51
|
+
inlineHookMemo?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Assert pure immutable-snapshot renders in application-owned modules.
|
|
54
|
+
* Individual modules can opt in with a top-level `"use strong"` directive.
|
|
55
|
+
* @default false
|
|
56
|
+
*/
|
|
57
|
+
strong?: boolean;
|
|
58
|
+
/** Path fragments excluded from Octane's plain `.ts`/`.js` hook-slot pass. */
|
|
59
|
+
exclude?: readonly string[];
|
|
60
|
+
/**
|
|
61
|
+
* Mixed-toolchain ownership gate: a project `.tsx`, `.ts`, or `.js` module is
|
|
62
|
+
* Octane's only with a leading `@jsxImportSource octane` pragma.
|
|
63
|
+
* @default false
|
|
64
|
+
*/
|
|
65
|
+
requireDirective?: boolean;
|
|
66
|
+
/** @experimental Declarative renderer selection for this compiler instance. */
|
|
67
|
+
renderers?: OctaneRendererConfigOptions | OctaneResolvedRendererConfig;
|
|
68
|
+
/** Receives ownership warnings and nonfatal compiler diagnostics, once per watch generation. */
|
|
69
|
+
warn?: (message: string) => void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface OctaneTransformOptions
|
|
73
|
+
extends
|
|
74
|
+
Pick<
|
|
75
|
+
OctaneCompilerOptions,
|
|
76
|
+
| 'environment'
|
|
77
|
+
| 'output'
|
|
78
|
+
| 'hmr'
|
|
79
|
+
| 'dev'
|
|
80
|
+
| 'profile'
|
|
81
|
+
| 'inlineHookMemo'
|
|
82
|
+
| 'strong'
|
|
83
|
+
| 'knownAttributeSpreads'
|
|
84
|
+
| 'domBindingFixedProps'
|
|
85
|
+
| 'opaqueSignalHandles'
|
|
86
|
+
| 'universalRuntime'
|
|
87
|
+
>,
|
|
88
|
+
Pick<
|
|
89
|
+
CompileOptions,
|
|
90
|
+
| 'textTypeFacts'
|
|
91
|
+
| 'clientOnlyImports'
|
|
92
|
+
| 'resolveCssModuleConstant'
|
|
93
|
+
| 'preserveCssModuleReferences'
|
|
94
|
+
| 'isVoidComponentImport'
|
|
95
|
+
| 'isCompilerMemoImport'
|
|
96
|
+
| 'isLiteComponentImport'
|
|
97
|
+
| 'isStrongLiteComponentImport'
|
|
98
|
+
| 'isAnchorlessComponentImport'
|
|
99
|
+
| 'isDescriptorChildrenImport'
|
|
100
|
+
> {
|
|
101
|
+
/** Rewrite server runtime requests (`octane` to `octane/server`) in the output. */
|
|
102
|
+
explicitRuntimeRequests?: boolean;
|
|
103
|
+
/** Report `voidComponentExports` for a compiled client module. */
|
|
104
|
+
collectVoidComponentExports?: boolean;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Manifests that decided a result; a host registers them as watch dependencies. */
|
|
108
|
+
export interface OctaneWatchDependencies {
|
|
109
|
+
dependencies: string[];
|
|
110
|
+
missingDependencies: string[];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Server-graph identity of a module owned by a client-only renderer. */
|
|
114
|
+
export interface OctaneClientReference {
|
|
115
|
+
readonly id: string;
|
|
116
|
+
readonly moduleId: string;
|
|
117
|
+
readonly renderer: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface OctaneTransformResult
|
|
121
|
+
extends
|
|
122
|
+
OctaneWatchDependencies,
|
|
123
|
+
Pick<
|
|
124
|
+
CompileResult,
|
|
125
|
+
'lang' | 'streamedSignals' | 'universalRuntime' | 'compilerMemoExports' | 'bindingConstants'
|
|
126
|
+
> {
|
|
127
|
+
code: string;
|
|
128
|
+
map: CompileSourceMap | null;
|
|
129
|
+
/**
|
|
130
|
+
* `compile`: full Octane compilation. `slots`: hook slotting of a plain
|
|
131
|
+
* module. `client-only-stub`: an export-preserving server stub.
|
|
132
|
+
* `runtime-requests`: only runtime requests were rewritten. `none`: the
|
|
133
|
+
* source is unchanged and returned only to report watch dependencies.
|
|
134
|
+
*/
|
|
135
|
+
kind: 'compile' | 'slots' | 'client-only-stub' | 'runtime-requests' | 'none';
|
|
136
|
+
diagnostics?: readonly CompileDiagnostic[];
|
|
137
|
+
renderer?: OctaneResolvedRenderer;
|
|
138
|
+
clientReference?: OctaneClientReference;
|
|
139
|
+
/** Export names of a client-only server stub. */
|
|
140
|
+
clientOnlyExports?: readonly string[];
|
|
141
|
+
/** The printed client-only server stub. */
|
|
142
|
+
ast?: CompilerProgram;
|
|
143
|
+
// Build-time metadata adapters publish to importers of this module.
|
|
144
|
+
descriptorChildrenExports?: readonly string[];
|
|
145
|
+
voidComponentExports?: readonly string[];
|
|
146
|
+
liteComponentExports?: readonly string[];
|
|
147
|
+
strongLiteComponentExports?: readonly string[];
|
|
148
|
+
anchorlessComponentExports?: readonly string[];
|
|
149
|
+
cssModuleConstantImports?: readonly unknown[];
|
|
150
|
+
independentWidgets?: readonly unknown[];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface OctaneSourceDependencies extends OctaneWatchDependencies {
|
|
154
|
+
/** Installed packages that ship Octane source, following their runtime dependencies. */
|
|
155
|
+
packages: string[];
|
|
156
|
+
/** Package IDs those packages ask Vite not to pre-bundle. */
|
|
157
|
+
viteOptimizeDepsExclusions: string[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** The bundler-neutral compiler that every Octane bundler adapter drives. */
|
|
161
|
+
export interface OctaneCompiler {
|
|
162
|
+
/**
|
|
163
|
+
* Compile or hook-slot one module, or return `null` when it passes through
|
|
164
|
+
* unchanged with no watch dependencies.
|
|
165
|
+
*/
|
|
166
|
+
transform(
|
|
167
|
+
code: string,
|
|
168
|
+
id: string,
|
|
169
|
+
options?: OctaneTransformOptions,
|
|
170
|
+
): OctaneTransformResult | null;
|
|
171
|
+
/** Clear cached manifest decisions after a watched path changes, or all of them. */
|
|
172
|
+
invalidate(path?: string | null): void;
|
|
173
|
+
discoverSourceDependencies(): OctaneSourceDependencies;
|
|
174
|
+
/** The privacy-safe source identity used by profiling metadata. */
|
|
175
|
+
resolveProfileModuleId(id: string): OctaneWatchDependencies & { id: string };
|
|
176
|
+
resolveRuntimeRequest(request: string, environment?: OctaneEnvironment): string | null;
|
|
177
|
+
/** Static requests an adapter resolves before a server transform. */
|
|
178
|
+
findServerImportRequests(code: string, id: string): string[];
|
|
179
|
+
/** CSS-module requests the host may prove constant, behind the same ownership gate. */
|
|
180
|
+
findCssModuleImportRequests(
|
|
181
|
+
code: string,
|
|
182
|
+
id: string,
|
|
183
|
+
environment?: OctaneEnvironment,
|
|
184
|
+
parsedAst?: CompilerProgram | null,
|
|
185
|
+
): string[];
|
|
186
|
+
/** Classify a bundler-resolved module without loading or evaluating it. */
|
|
187
|
+
clientReferenceForFile(id: string): OctaneClientReference | null;
|
|
188
|
+
/** How Strong mode reaches a module: its own directive, the `strong` option, or neither. */
|
|
189
|
+
strongModuleStatus(
|
|
190
|
+
code: string,
|
|
191
|
+
id: string,
|
|
192
|
+
): {
|
|
193
|
+
strong: boolean;
|
|
194
|
+
directive: boolean;
|
|
195
|
+
config: boolean;
|
|
196
|
+
};
|
|
197
|
+
/** The package owning a module by its nearest manifest, and whether `transform` may change it. */
|
|
198
|
+
modulePackage(
|
|
199
|
+
code: string,
|
|
200
|
+
id: string,
|
|
201
|
+
): {
|
|
202
|
+
name: string | null;
|
|
203
|
+
root: string | null;
|
|
204
|
+
compiled: boolean;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function createOctaneCompiler(options?: OctaneCompilerOptions): OctaneCompiler;
|
|
209
|
+
|
|
210
|
+
/** Discover raw-source Octane dependencies from the nearest owning package manifest. */
|
|
211
|
+
export function discoverOctaneSourceDependencies(projectRoot: string): string[];
|
|
212
|
+
|
|
213
|
+
export const OCTANE_RUNTIME_REQUESTS: Readonly<{ client: 'octane'; server: 'octane/server' }>;
|
|
214
|
+
|
|
215
|
+
/** The server or client runtime request for an Octane runtime import, or `null` for any other. */
|
|
216
|
+
export function resolveOctaneRuntimeRequest(
|
|
217
|
+
request: string,
|
|
218
|
+
environment: OctaneEnvironment,
|
|
219
|
+
): string | null;
|
|
220
|
+
|
|
221
|
+
/** Strip bundler query/hash suffixes without changing the underlying path. */
|
|
222
|
+
export function cleanModuleId(id: string): string;
|
|
223
|
+
|
|
224
|
+
/** The stable module ID embedded in compiler output: root-relative POSIX inside the root. */
|
|
225
|
+
export function canonicalModuleId(id: string, projectRoot?: string): string;
|
|
226
|
+
|
|
227
|
+
/** Whether an installed package reaches, through non-Octane packages, one Vite serves as CommonJS. */
|
|
228
|
+
export function packageReachesCommonJs(root: string): boolean;
|
|
229
|
+
|
|
230
|
+
/** Read the module specifier of a leading `@jsxImportSource` pragma. */
|
|
231
|
+
export function findLeadingJsxImportSourcePragma(code: string): string | null;
|
|
232
|
+
|
|
233
|
+
export const HYDRATE_QUERY_PARAM: 'octane-hydrate';
|
|
234
|
+
export const INDEPENDENT_HYDRATION_MANIFEST_FILENAME: 'octane-independent-hydration.json';
|
|
235
|
+
|
|
236
|
+
/** Direct function exports whose authored body never returns a renderable value. */
|
|
237
|
+
export function findVoidComponentExports(source: string | CompilerProgram, id: string): string[];
|
|
238
|
+
|
|
239
|
+
/** Facts about a module's final JavaScript after every bundler transform, or `null` if it does not parse. */
|
|
240
|
+
export function analyzeCompiledModule(
|
|
241
|
+
source: string,
|
|
242
|
+
id: string,
|
|
243
|
+
): {
|
|
244
|
+
voidComponentExports: string[];
|
|
245
|
+
/** `imported` is `default` or `*` for those import forms. */
|
|
246
|
+
importBindings: { local: string; request: string; imported: string }[];
|
|
247
|
+
} | null;
|
|
248
|
+
|
|
249
|
+
export function findDescriptorChildrenExports(
|
|
250
|
+
source: string | CompilerProgram,
|
|
251
|
+
id: string,
|
|
252
|
+
): string[];
|
|
253
|
+
|
|
254
|
+
/** Imported components rendered as JSX or re-exported, as descriptor-children candidates. */
|
|
255
|
+
export function findDescriptorChildrenImports(
|
|
256
|
+
source: string | CompilerProgram,
|
|
257
|
+
id: string,
|
|
258
|
+
): { request: string; imported: string; local?: string; exported?: string }[];
|
|
259
|
+
|
|
260
|
+
export function isPlainCssModuleId(id: string): boolean;
|
|
261
|
+
|
|
262
|
+
/** A CSS provider's literal string exports, read without running it. */
|
|
263
|
+
export interface OctaneCssModuleExports {
|
|
264
|
+
named: Map<string, string>;
|
|
265
|
+
default: Map<string, string> | null;
|
|
266
|
+
pure: boolean;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function readCssModuleExports(
|
|
270
|
+
source: string,
|
|
271
|
+
options?: { allowPureVar?: boolean },
|
|
272
|
+
): OctaneCssModuleExports | null;
|
|
273
|
+
|
|
274
|
+
/** Validate a host assertion against the exact module it describes; throws when it does not hold. */
|
|
275
|
+
export function validateCssModuleConstants(
|
|
276
|
+
provided: OctaneCssModuleConstants | null | undefined,
|
|
277
|
+
exports: OctaneCssModuleExports | null,
|
|
278
|
+
id: string,
|
|
279
|
+
diagnosticOwner?: string,
|
|
280
|
+
): { named: Map<string, string>; default: Map<string, string> } | null;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Fail-closed check of a `hydrate: 'islands'` shell: constructs that need
|
|
284
|
+
* client work, and the imported components to check the same way.
|
|
285
|
+
*/
|
|
286
|
+
export function analyzeIslandsShell(
|
|
287
|
+
source: string,
|
|
288
|
+
filename: string,
|
|
289
|
+
exports?: readonly string[] | null,
|
|
290
|
+
options?: { values?: boolean },
|
|
291
|
+
): {
|
|
292
|
+
problems: { message: string; line: number; column: number }[];
|
|
293
|
+
components: { source: string; exportName: string; value?: true }[];
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
export const CLIENT_REFERENCE_MANIFEST_FILENAME: 'octane-client-references.json';
|
|
297
|
+
export const CLIENT_REFERENCE_MANIFEST_VERSION: 1;
|
|
298
|
+
|
|
299
|
+
/** Merge the chunks each adapter found for client references into one deterministic manifest. */
|
|
300
|
+
export function createClientReferenceManifest(
|
|
301
|
+
entries:
|
|
302
|
+
Iterable<{ reference: OctaneClientReference; chunks?: Iterable<string> }> | null | undefined,
|
|
303
|
+
): {
|
|
304
|
+
version: typeof CLIENT_REFERENCE_MANIFEST_VERSION;
|
|
305
|
+
references: Record<string, { moduleId: string; renderer: string; chunks: string[] }>;
|
|
306
|
+
};
|
package/dist/compiler/bundler.js
CHANGED
|
@@ -265,6 +265,57 @@ function realPathOrSelf(dir) {
|
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
+
/**
|
|
269
|
+
* Whether Vite would serve this package as CommonJS: its entry is a `.js` or
|
|
270
|
+
* `.cjs` file outside a `"type": "module"` scope, and neither a `module` field
|
|
271
|
+
* nor an `import` condition offers ESM.
|
|
272
|
+
*/
|
|
273
|
+
function servesCommonJs(pkg) {
|
|
274
|
+
if (pkg.type === 'module' || typeof pkg.module === 'string') return false;
|
|
275
|
+
const exports = JSON.stringify(pkg.exports ?? null);
|
|
276
|
+
if (/"(?:import|module)":|\.mjs"/.test(exports)) return false;
|
|
277
|
+
return (
|
|
278
|
+
/\.c?js"/.test(exports) ||
|
|
279
|
+
(typeof pkg.main === 'string' && /(?:^|\/)[^./]+$|\.c?js$/.test(pkg.main))
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Whether the installed package at `root` depends, through packages other than
|
|
285
|
+
* Octane source packages, on one Vite would serve as CommonJS. Reads manifests
|
|
286
|
+
* only: the package's dependencies and peers, then their dependencies.
|
|
287
|
+
*/
|
|
288
|
+
export function packageReachesCommonJs(root) {
|
|
289
|
+
const unwatched = { dependencies: new Set(), missingDependencies: new Set() };
|
|
290
|
+
const seen = new Set();
|
|
291
|
+
const pending = [root];
|
|
292
|
+
while (pending.length > 0) {
|
|
293
|
+
const dir = pending.pop();
|
|
294
|
+
if (seen.has(dir)) continue;
|
|
295
|
+
seen.add(dir);
|
|
296
|
+
let pkg;
|
|
297
|
+
try {
|
|
298
|
+
pkg = JSON.parse(nodeFs.readFileSync(nodePath.join(dir, 'package.json'), 'utf8'));
|
|
299
|
+
} catch {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
if (dir !== root) {
|
|
303
|
+
if (packageUsesOctane(pkg, dir)) continue;
|
|
304
|
+
if (servesCommonJs(pkg)) return true;
|
|
305
|
+
}
|
|
306
|
+
for (const name of Object.keys({
|
|
307
|
+
...(dir === root ? pkg.peerDependencies : null),
|
|
308
|
+
...pkg.dependencies,
|
|
309
|
+
...pkg.optionalDependencies,
|
|
310
|
+
})) {
|
|
311
|
+
if (name.startsWith('@types/')) continue;
|
|
312
|
+
const manifest = resolveInstalledPackageManifest(name, dir, unwatched);
|
|
313
|
+
if (manifest !== null) pending.push(realPathOrSelf(nodePath.dirname(manifest)));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
|
|
268
319
|
function metadata(dependencies = [], missingDependencies = []) {
|
|
269
320
|
return { dependencies, missingDependencies };
|
|
270
321
|
}
|
|
@@ -998,7 +1049,7 @@ class OctaneBundlerCompiler {
|
|
|
998
1049
|
return isPathInside(this.root, absoluteFile) || isPathInside(this.realRoot, absoluteFile);
|
|
999
1050
|
}
|
|
1000
1051
|
|
|
1001
|
-
|
|
1052
|
+
_isApplicationSource(file, collected) {
|
|
1002
1053
|
if (!this._isProjectOwnedSource(file)) return false;
|
|
1003
1054
|
const absoluteFile = nodePath.isAbsolute(file)
|
|
1004
1055
|
? nodePath.resolve(file)
|
|
@@ -1031,7 +1082,7 @@ class OctaneBundlerCompiler {
|
|
|
1031
1082
|
const file = cleanModuleId(id);
|
|
1032
1083
|
const config =
|
|
1033
1084
|
this.defaults.strong === true &&
|
|
1034
|
-
this.
|
|
1085
|
+
this._isApplicationSource(file, {
|
|
1035
1086
|
dependencies: new Set(),
|
|
1036
1087
|
missingDependencies: new Set(),
|
|
1037
1088
|
});
|
|
@@ -1567,7 +1618,7 @@ class OctaneBundlerCompiler {
|
|
|
1567
1618
|
// directive, which the authored-source compiler resolves separately.
|
|
1568
1619
|
const strong =
|
|
1569
1620
|
(options.strong ?? this.defaults.strong) === true &&
|
|
1570
|
-
this.
|
|
1621
|
+
this._isApplicationSource(file, collected);
|
|
1571
1622
|
const universalRuntime = normalizeUniversalRuntime(
|
|
1572
1623
|
options.universalRuntime ?? this.defaults.universalRuntime,
|
|
1573
1624
|
);
|
|
@@ -1816,7 +1867,6 @@ class OctaneBundlerCompiler {
|
|
|
1816
1867
|
}
|
|
1817
1868
|
return passThrough();
|
|
1818
1869
|
}
|
|
1819
|
-
const hasHookRuntimeImport = importsHookRuntime(code);
|
|
1820
1870
|
// Hook slotting is an Octane-ownership rewrite, so the ownership
|
|
1821
1871
|
// gate applies to it exactly as to full compilation: an unmarked
|
|
1822
1872
|
// project module stays with the host pipeline (with the forgotten-
|
|
@@ -1826,13 +1876,19 @@ class OctaneBundlerCompiler {
|
|
|
1826
1876
|
return passThrough();
|
|
1827
1877
|
}
|
|
1828
1878
|
const manualSlots = this._hasManualHookSlots(file, collected);
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1879
|
+
// The application's own modules are Octane's, as its `.tsx` are, so they
|
|
1880
|
+
// slot custom-hook calls without importing Octane: a hook composed only
|
|
1881
|
+
// of other hooks keeps one instance per call. A package, installed or
|
|
1882
|
+
// nested in the root, still needs the import or pragma, since its plain
|
|
1883
|
+
// modules may implement hooks with authored slots, as Octane's runtime does.
|
|
1884
|
+
// A leading pragma decides for itself: one naming `react` hands the
|
|
1885
|
+
// module to that toolchain.
|
|
1886
|
+
const pragma = findLeadingJsxImportSourcePragma(code);
|
|
1887
|
+
const owned =
|
|
1888
|
+
pragma === null
|
|
1889
|
+
? this._isApplicationSource(file, collected)
|
|
1890
|
+
: this.pragmaOwnedModules.has(pragma);
|
|
1891
|
+
if (!importsHookRuntime(code) && !manualSlots && !owned) return passThrough();
|
|
1836
1892
|
if (output === 'ts' && !manualSlots) {
|
|
1837
1893
|
// The cheap ownership regex also matches documentation examples. A
|
|
1838
1894
|
// full compile needs a real import (or an explicit ownership pragma).
|
|
@@ -1878,7 +1934,7 @@ class OctaneBundlerCompiler {
|
|
|
1878
1934
|
profile,
|
|
1879
1935
|
profileFilename,
|
|
1880
1936
|
inlineHookMemo: inlinePlainMemo,
|
|
1881
|
-
...(manualSlots ? { manualSlots: true } : null),
|
|
1937
|
+
...(manualSlots ? { manualSlots: true } : owned ? { owned: true } : null),
|
|
1882
1938
|
...(strong ? { strong: true } : null),
|
|
1883
1939
|
renderer,
|
|
1884
1940
|
...(specializeVoidRoot
|
package/dist/compiler/compile.js
CHANGED
|
@@ -10434,6 +10434,82 @@ function dropTypeOnlyStatements(body) {
|
|
|
10434
10434
|
return typeNames.size === 0 ? result : dropTypeOnlyExports(result, typeNames);
|
|
10435
10435
|
}
|
|
10436
10436
|
|
|
10437
|
+
const TYPESCRIPT_SOURCE = /\.(?:tsrx|[cm]?tsx?)$/;
|
|
10438
|
+
|
|
10439
|
+
// The runtime emit erases what tsc does. Without `verbatimModuleSyntax` that
|
|
10440
|
+
// includes an import specifier written without `type` when the module refers
|
|
10441
|
+
// to it only in type positions, and a declaration left with none. Such a
|
|
10442
|
+
// specifier usually names only a type, so keeping it imports an export that
|
|
10443
|
+
// does not exist, which Rolldown rejects. A specifier nothing refers to stays,
|
|
10444
|
+
// as in JavaScript: a pass before this one may have added an import whose reads
|
|
10445
|
+
// it emits later (renderer regions).
|
|
10446
|
+
function dropTypeOnlyCode(body, filename) {
|
|
10447
|
+
const runtime = dropTypeOnlyStatements(body);
|
|
10448
|
+
if (!TYPESCRIPT_SOURCE.test(cleanCompileFilename(filename))) return runtime;
|
|
10449
|
+
const reads = collectFreeIdentifiers(
|
|
10450
|
+
runtime.filter((statement) => statement.type !== 'ImportDeclaration'),
|
|
10451
|
+
[],
|
|
10452
|
+
);
|
|
10453
|
+
const unread = (specifier) => !reads.has(specifier.local.name);
|
|
10454
|
+
if (
|
|
10455
|
+
!runtime.some(
|
|
10456
|
+
(statement) => statement.type === 'ImportDeclaration' && statement.specifiers.some(unread),
|
|
10457
|
+
)
|
|
10458
|
+
) {
|
|
10459
|
+
return runtime;
|
|
10460
|
+
}
|
|
10461
|
+
// Erased declarations refer to types too, as in `interface Props { icon: Icon }`.
|
|
10462
|
+
const types = collectTypeReferenceNames(body, new Set());
|
|
10463
|
+
const result = [];
|
|
10464
|
+
for (const statement of runtime) {
|
|
10465
|
+
if (statement.type !== 'ImportDeclaration') {
|
|
10466
|
+
result.push(statement);
|
|
10467
|
+
continue;
|
|
10468
|
+
}
|
|
10469
|
+
const specifiers = statement.specifiers.filter(
|
|
10470
|
+
(specifier) => !unread(specifier) || !types.has(specifier.local.name),
|
|
10471
|
+
);
|
|
10472
|
+
if (specifiers.length === statement.specifiers.length) result.push(statement);
|
|
10473
|
+
else if (specifiers.length > 0) result.push({ ...statement, specifiers });
|
|
10474
|
+
}
|
|
10475
|
+
return result;
|
|
10476
|
+
}
|
|
10477
|
+
|
|
10478
|
+
// The root name of every type reference: `T`, `ns.T`, `typeof value`, the
|
|
10479
|
+
// heritage of `implements` and interface `extends`, and a local exported with
|
|
10480
|
+
// `export type { T }` or `export { type T }`.
|
|
10481
|
+
function collectTypeReferenceNames(node, names) {
|
|
10482
|
+
if (node === null || typeof node !== 'object') return names;
|
|
10483
|
+
if (Array.isArray(node)) {
|
|
10484
|
+
for (const child of node) collectTypeReferenceNames(child, names);
|
|
10485
|
+
return names;
|
|
10486
|
+
}
|
|
10487
|
+
let name =
|
|
10488
|
+
node.type === 'TSTypeReference'
|
|
10489
|
+
? node.typeName
|
|
10490
|
+
: node.type === 'TSTypeQuery'
|
|
10491
|
+
? node.exprName
|
|
10492
|
+
: node.type === 'TSClassImplements' ||
|
|
10493
|
+
node.type === 'TSInterfaceHeritage' ||
|
|
10494
|
+
node.type === 'TSExpressionWithTypeArguments'
|
|
10495
|
+
? node.expression
|
|
10496
|
+
: null;
|
|
10497
|
+
while (name?.type === 'TSQualifiedName') name = name.left;
|
|
10498
|
+
while (name?.type === 'MemberExpression') name = name.object;
|
|
10499
|
+
if (name?.type === 'Identifier') names.add(name.name);
|
|
10500
|
+
if (node.type === 'ExportNamedDeclaration' && node.source == null) {
|
|
10501
|
+
for (const specifier of node.specifiers) {
|
|
10502
|
+
if (node.exportKind === 'type' || specifier.exportKind === 'type') {
|
|
10503
|
+
names.add(specifier.local.name);
|
|
10504
|
+
}
|
|
10505
|
+
}
|
|
10506
|
+
}
|
|
10507
|
+
for (const key in node) {
|
|
10508
|
+
if (!AST_WALK_SKIP_KEYS.has(key)) collectTypeReferenceNames(node[key], names);
|
|
10509
|
+
}
|
|
10510
|
+
return names;
|
|
10511
|
+
}
|
|
10512
|
+
|
|
10437
10513
|
// Local names declared only by an erased statement or specifier.
|
|
10438
10514
|
function collectTypeOnlyNames(statement, names) {
|
|
10439
10515
|
const node = statement.type === 'ExportNamedDeclaration' ? statement.declaration : statement;
|
|
@@ -12549,9 +12625,9 @@ function compileInternal(
|
|
|
12549
12625
|
}
|
|
12550
12626
|
// Drop type-only statements (interface / type / declare / import-export type)
|
|
12551
12627
|
// and inline `type` specifiers before emit — they carry no runtime value and
|
|
12552
|
-
// would leak invalid TS into the .js (or crash the printer)
|
|
12553
|
-
// Volar keeps them.
|
|
12554
|
-
if (options?.output !== 'ts') ast = { ...ast, body:
|
|
12628
|
+
// would leak invalid TS into the .js (or crash the printer), then imports
|
|
12629
|
+
// used only as types, as tsc elides them. Runtime-only; Volar keeps them.
|
|
12630
|
+
if (options?.output !== 'ts') ast = { ...ast, body: dropTypeOnlyCode(ast.body, filename) };
|
|
12555
12631
|
const serverModuleInfo = analyzeServerModule(ast, filename);
|
|
12556
12632
|
// Normalize arrow-function components (`const X = () => @{…}`) to
|
|
12557
12633
|
// FunctionDeclaration form so the component pipeline recognizes them.
|
|
@@ -14341,9 +14417,9 @@ function compileServer(
|
|
|
14341
14417
|
// server codegen rewrites are copy-on-write over it.
|
|
14342
14418
|
let ast = parsedAst;
|
|
14343
14419
|
// Drop type-only statements and inline `type` specifiers before emit (see
|
|
14344
|
-
// isTypeOnlyStatement) — same as the client
|
|
14345
|
-
// output is plain JS too.
|
|
14346
|
-
if (options?.output !== 'ts') ast = { ...ast, body:
|
|
14420
|
+
// isTypeOnlyStatement), then imports used only as types — same as the client
|
|
14421
|
+
// path; the server HTML-string output is plain JS too.
|
|
14422
|
+
if (options?.output !== 'ts') ast = { ...ast, body: dropTypeOnlyCode(ast.body, filename) };
|
|
14347
14423
|
const serverModuleInfo = analyzeServerModule(ast, filename);
|
|
14348
14424
|
// Normalize arrow-function components (`const X = () => @{…}`) to
|
|
14349
14425
|
// FunctionDeclaration form so the component pipeline recognizes them.
|
|
@@ -17023,7 +17099,9 @@ function ssrEmitComponent(node, ctx, name, inlinedSubs, parentNs, cssHash, compo
|
|
|
17023
17099
|
let keyExpr = null;
|
|
17024
17100
|
for (const attr of attrs) {
|
|
17025
17101
|
if (attr.type === 'SpreadAttribute' || attr.type === 'JSXSpreadAttribute') {
|
|
17026
|
-
propNodes.push(
|
|
17102
|
+
propNodes.push(
|
|
17103
|
+
b.spread(tsrxExprNode(rewriteJsxValues(attr.argument, ctx), ctx, name, inlinedSubs)),
|
|
17104
|
+
);
|
|
17027
17105
|
continue;
|
|
17028
17106
|
}
|
|
17029
17107
|
if (attr.type !== 'Attribute' && attr.type !== 'JSXAttribute') continue;
|
|
@@ -36604,7 +36682,11 @@ function makeCompCall(
|
|
|
36604
36682
|
for (const attr of attrs) {
|
|
36605
36683
|
if (attr.type === 'SpreadAttribute' || attr.type === 'JSXSpreadAttribute') {
|
|
36606
36684
|
hasSpreadProp = true;
|
|
36607
|
-
propNodes.push(
|
|
36685
|
+
propNodes.push(
|
|
36686
|
+
b.spread(
|
|
36687
|
+
tsrxExprNode(rewriteJsxValues(attr.argument, ctx), ctx, componentName, inlinedSubs),
|
|
36688
|
+
),
|
|
36689
|
+
);
|
|
36608
36690
|
continue;
|
|
36609
36691
|
}
|
|
36610
36692
|
if (attr.type !== 'Attribute' && attr.type !== 'JSXAttribute') continue;
|