octane 0.4.0 → 0.4.2
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/host-property-diagnostics.cjs +18 -0
- package/dist/cjs/runtime.cjs +87 -30
- package/dist/cjs/signals/client.cjs +6 -1
- package/dist/cjs/signals/diagnostic-local-hook.cjs +37 -0
- package/dist/cjs/signals/engine.cjs +12 -1
- package/dist/cjs/version.cjs +1 -1
- package/dist/compiler/compile.js +94 -15
- package/dist/host-property-diagnostics.js +18 -0
- package/dist/runtime.d.ts +4 -1
- package/dist/runtime.js +91 -31
- package/dist/signals/client.js +8 -3
- package/dist/signals/diagnostic-local-hook.d.ts +8 -0
- package/dist/signals/diagnostic-local-hook.js +12 -0
- package/dist/signals/engine.d.ts +2 -0
- package/dist/signals/engine.js +13 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -149,6 +149,21 @@ for (const name of [
|
|
|
149
149
|
]) {
|
|
150
150
|
KNOWN_SVG_PROPERTY_SPELLINGS.set(name.toLowerCase(), name);
|
|
151
151
|
}
|
|
152
|
+
const NON_NATIVE_LOWERCASE_PROPERTIES = /* @__PURE__ */ new Set([
|
|
153
|
+
"autoFocus",
|
|
154
|
+
"defaultValue",
|
|
155
|
+
"defaultChecked",
|
|
156
|
+
"dangerouslySetInnerHTML",
|
|
157
|
+
"className",
|
|
158
|
+
"suppressContentEditableWarning",
|
|
159
|
+
"suppressHydrationWarning",
|
|
160
|
+
"suppressNativeChangeWarning",
|
|
161
|
+
"__octaneNativeChangeDiagnostic",
|
|
162
|
+
"acceptCharset",
|
|
163
|
+
"htmlFor",
|
|
164
|
+
"httpEquiv",
|
|
165
|
+
"viewBox"
|
|
166
|
+
]);
|
|
152
167
|
function hostPropertyWarning(name, value, tag, isSvg = false) {
|
|
153
168
|
const lower = name.toLowerCase();
|
|
154
169
|
if (name === "for" && tag === "label") return null;
|
|
@@ -164,6 +179,9 @@ function hostPropertyWarning(name, value, tag, isSvg = false) {
|
|
|
164
179
|
if (name.startsWith("aria-") || /^aria[A-Z]/.test(name) || name.startsWith("data-")) return null;
|
|
165
180
|
const known = KNOWN_PROPERTY_SPELLINGS.get(lower) ?? (isSvg ? KNOWN_SVG_PROPERTY_SPELLINGS.get(lower) : void 0);
|
|
166
181
|
if (known !== void 0) {
|
|
182
|
+
if (!isSvg && name === lower && // Hyphenated/namespaced presentation aliases belong to SVG, not HTML.
|
|
183
|
+
!name.includes("-") && !name.includes(":") && !NON_NATIVE_LOWERCASE_PROPERTIES.has(known) && (import_constants.ATTRIBUTE_ALIASES.get(known) ?? lower) === lower)
|
|
184
|
+
return null;
|
|
167
185
|
if (isSvg && import_constants.ATTRIBUTE_ALIASES.get(known) === name) return null;
|
|
168
186
|
return name !== known ? `Invalid DOM property \`${name}\`. Did you mean \`${known}\`?` : null;
|
|
169
187
|
}
|
package/dist/cjs/runtime.cjs
CHANGED
|
@@ -158,6 +158,7 @@ __export(runtime_exports, {
|
|
|
158
158
|
isChildrenBlock: () => isChildrenBlock,
|
|
159
159
|
isHydratingStyle: () => isHydratingStyle,
|
|
160
160
|
isInActScope: () => isInActScope,
|
|
161
|
+
isNativeSignalDiagnosticProbe: () => isNativeSignalDiagnosticProbe,
|
|
161
162
|
isValidElement: () => isValidElement,
|
|
162
163
|
keyedForBlock: () => keyedForBlock,
|
|
163
164
|
lazy: () => lazy,
|
|
@@ -357,6 +358,7 @@ var import_transition_state = require("./signals/transition-state.cjs");
|
|
|
357
358
|
var import_transition_candidate = require("./signals/transition-candidate.cjs");
|
|
358
359
|
var import_read_protocol = require("./signals/read-protocol.cjs");
|
|
359
360
|
var import_native_read_events = require("./signals/native-read-events.cjs");
|
|
361
|
+
var import_diagnostic_local_hook = require("./signals/diagnostic-local-hook.cjs");
|
|
360
362
|
var import_native_read_seeds = require("./signals/native-read-seeds.cjs");
|
|
361
363
|
var import_owner_context = require("./signals/owner-context.cjs");
|
|
362
364
|
var import_document_owner = require("./signals/document-owner.cjs");
|
|
@@ -833,12 +835,12 @@ function nativePresentationBinding(owner, slotIndex, el, body, props) {
|
|
|
833
835
|
}
|
|
834
836
|
function enableNativeReadCollection(abi = 1) {
|
|
835
837
|
if (abi !== 1) throw new Error((0, import_error_codes_client_generated.formatClientError)(58));
|
|
838
|
+
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return;
|
|
836
839
|
ensureNativeReadDriver();
|
|
837
840
|
}
|
|
838
841
|
function beginNativeReadScope(scope, abi = 1) {
|
|
839
|
-
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null)
|
|
840
|
-
throw new PresentationAdoptionMiss(void 0, false);
|
|
841
842
|
if (abi !== 1) throw new Error((0, import_error_codes_client_generated.formatClientError)(58));
|
|
843
|
+
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return -1;
|
|
842
844
|
const block = CURRENT_BLOCK;
|
|
843
845
|
const owner = scope ?? CURRENT_SCOPE;
|
|
844
846
|
if (block === null || owner === null) return -1;
|
|
@@ -954,12 +956,14 @@ function endNativeReadScope(token, _completed) {
|
|
|
954
956
|
if (token >= 0) NATIVE_READ_DRIVER.endScope(token);
|
|
955
957
|
}
|
|
956
958
|
function beginNativeReadWitness(detached = false) {
|
|
959
|
+
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return -1;
|
|
957
960
|
return detached ? ensureNativeReadDriver().beginWitness(true) : NATIVE_READ_DRIVER?.beginWitness() ?? -1;
|
|
958
961
|
}
|
|
959
962
|
function finishNativeReadWitness(token, completed) {
|
|
960
963
|
return token < 0 ? null : NATIVE_READ_DRIVER.finishWitness(token, completed);
|
|
961
964
|
}
|
|
962
965
|
function replayNativeReadWitness(witness) {
|
|
966
|
+
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return;
|
|
963
967
|
NATIVE_READ_DRIVER?.replay(witness);
|
|
964
968
|
}
|
|
965
969
|
function retainNativeRetryReads(block, reads) {
|
|
@@ -6789,7 +6793,8 @@ function renderBlockInner(block) {
|
|
|
6789
6793
|
let profileThrown;
|
|
6790
6794
|
let renderCompleted = false;
|
|
6791
6795
|
let renderRetry = false;
|
|
6792
|
-
|
|
6796
|
+
if (process.env.NODE_ENV === "production" || hydrateAttributeProbe === null)
|
|
6797
|
+
NATIVE_READ_DRIVER?.beginRender(block);
|
|
6793
6798
|
NATIVE_BLOCK_RETRIES?.get(block)?.clear();
|
|
6794
6799
|
try {
|
|
6795
6800
|
if (urgentTransitionRender !== null)
|
|
@@ -6857,7 +6862,8 @@ function renderBlockInner(block) {
|
|
|
6857
6862
|
CURRENT_SCOPE = prevScope;
|
|
6858
6863
|
CURRENT_BLOCK = prevBlock;
|
|
6859
6864
|
try {
|
|
6860
|
-
|
|
6865
|
+
if (process.env.NODE_ENV === "production" || hydrateAttributeProbe === null)
|
|
6866
|
+
NATIVE_READ_DRIVER?.endRender(block, renderCompleted, isSuspenseException(profileThrown));
|
|
6861
6867
|
} finally {
|
|
6862
6868
|
if (urgentTransitionRender !== null)
|
|
6863
6869
|
urgentTransitionDriver.endUrgent(block, urgentTransitionRender);
|
|
@@ -7475,15 +7481,20 @@ function resolveSlot(slot) {
|
|
|
7475
7481
|
const resolved = (0, import_hook_slot_cache.resolveHookPath)(slotStack, slot, false);
|
|
7476
7482
|
return typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__ ? (0, import_profiling.__profileResolveHook)(resolved, typeof slot === "symbol" ? slot : void 0) : resolved;
|
|
7477
7483
|
}
|
|
7478
|
-
function
|
|
7479
|
-
|
|
7484
|
+
function isNativeSignalDiagnosticProbe() {
|
|
7485
|
+
return process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null;
|
|
7486
|
+
}
|
|
7487
|
+
function nativeLocalHook(name, initialize, dispose, slot, diagnosticInitialize) {
|
|
7488
|
+
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null && (name !== "useSignal$" || diagnosticInitialize === void 0 || !(0, import_diagnostic_local_hook.isNativeSignalDiagnosticInitializer)(diagnosticInitialize)))
|
|
7480
7489
|
throw new PresentationAdoptionMiss(void 0, false);
|
|
7481
7490
|
slot = resolveSlot(slot);
|
|
7482
7491
|
if (slot === void 0 || CURRENT_SCOPE === null) missingSlot(name);
|
|
7483
7492
|
const scope = CURRENT_SCOPE;
|
|
7484
7493
|
let cell = scope.hooks?.get(slot);
|
|
7485
7494
|
if (cell === void 0) {
|
|
7486
|
-
cell = {
|
|
7495
|
+
cell = {
|
|
7496
|
+
nativeValue: process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null ? diagnosticInitialize() : initialize()
|
|
7497
|
+
};
|
|
7487
7498
|
ensureHooks(scope).set(slot, cell);
|
|
7488
7499
|
const value = cell.nativeValue;
|
|
7489
7500
|
registerHookCleanup(scope, () => dispose(value));
|
|
@@ -8941,6 +8952,7 @@ function collectInitialHydrateAttributes(state, snapshot) {
|
|
|
8941
8952
|
if (state.seedRaw !== null) hydration.seeds = hydration.parseSeeds(state.seedRaw);
|
|
8942
8953
|
hydration.protectRootAnchor(end);
|
|
8943
8954
|
const capture = createOffscreenCapture();
|
|
8955
|
+
const diagnosticNative = state.nativeSeedRaw === void 0 ? void 0 : (0, import_native_read_seeds.createNativeAdoptionState)((0, import_native_read_seeds.parseNativeSignalManifest)(state.nativeSeedRaw));
|
|
8944
8956
|
const previousHydration = currentHydration;
|
|
8945
8957
|
const previousCapture = WIP_CAPTURE;
|
|
8946
8958
|
const previousProbe = hydrateAttributeProbe;
|
|
@@ -8960,7 +8972,10 @@ function collectInitialHydrateAttributes(state, snapshot) {
|
|
|
8960
8972
|
const previousSelectDefaultSyncs = SELECT_DEFAULT_SYNCS;
|
|
8961
8973
|
const previousFormChecks = DEV_FORM_CHECKS;
|
|
8962
8974
|
const previousAutofocus = AUTOFOCUS_QUEUE;
|
|
8963
|
-
const
|
|
8975
|
+
const diagnosticDriver = NATIVE_READ_DRIVER;
|
|
8976
|
+
const nativeProbeToken = diagnosticDriver?.pauseLifecycle() ?? -1;
|
|
8977
|
+
const previousWriteGuard = (0, import_read_protocol.beginNativeWriteGuard)();
|
|
8978
|
+
const previousNative = (0, import_read_protocol.setNativeAdoptionResolver)(diagnosticNative?.resolve ?? null);
|
|
8964
8979
|
const refDetachCheckpoint = refDetachQueue.length;
|
|
8965
8980
|
currentHydration = hydration;
|
|
8966
8981
|
WIP_CAPTURE = capture;
|
|
@@ -8990,27 +9005,36 @@ function collectInitialHydrateAttributes(state, snapshot) {
|
|
|
8990
9005
|
disposeWip({ block, start, end, capture, domParent: wrapper, refDetachCheckpoint });
|
|
8991
9006
|
drainHydrationRenderPhaseUpdates(block);
|
|
8992
9007
|
} finally {
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9008
|
+
try {
|
|
9009
|
+
diagnosticNative?.release();
|
|
9010
|
+
} finally {
|
|
9011
|
+
try {
|
|
9012
|
+
(0, import_read_protocol.setNativeAdoptionResolver)(previousNative);
|
|
9013
|
+
(0, import_read_protocol.endNativeWriteGuard)(previousWriteGuard);
|
|
9014
|
+
if (nativeProbeToken >= 0) diagnosticDriver.resumeLifecycle(nativeProbeToken);
|
|
9015
|
+
} finally {
|
|
9016
|
+
currentHydration = previousHydration;
|
|
9017
|
+
WIP_CAPTURE = previousCapture;
|
|
9018
|
+
hydrateAttributeProbe = previousProbe;
|
|
9019
|
+
ROOT_RENDER_TRANSACTION = previousTransaction;
|
|
9020
|
+
TRANSITION_JOURNAL = previousJournal;
|
|
9021
|
+
ACTIVE_TRANSITION_ATTEMPT = previousAttempt;
|
|
9022
|
+
SCOPED_READ_TRACKING = previousScopedReadTracking;
|
|
9023
|
+
SCOPED_READS = previousScopedReads;
|
|
9024
|
+
CURRENT_WARM = previousWarm;
|
|
9025
|
+
CURRENT_WARM_CLAIMS = previousWarmClaims;
|
|
9026
|
+
CURRENT_WARM_EPISODE = previousWarmEpisode;
|
|
9027
|
+
ACTIVE_WARM_PLANS.length = 0;
|
|
9028
|
+
ACTIVE_WARM_PLANS.push(...previousWarmPlans);
|
|
9029
|
+
STAGED_DOM = previousStagedDom;
|
|
9030
|
+
STAGED_COMMIT_CAPTURE = previousStagedCapture;
|
|
9031
|
+
PRESENTATION_HYDRATION = previousPresentation;
|
|
9032
|
+
SELECT_SYNCS = previousSelectSyncs;
|
|
9033
|
+
SELECT_DEFAULT_SYNCS = previousSelectDefaultSyncs;
|
|
9034
|
+
DEV_FORM_CHECKS = previousFormChecks;
|
|
9035
|
+
AUTOFOCUS_QUEUE = previousAutofocus;
|
|
9036
|
+
}
|
|
9037
|
+
}
|
|
9014
9038
|
}
|
|
9015
9039
|
}
|
|
9016
9040
|
return probe;
|
|
@@ -24550,12 +24574,43 @@ function preservesCommittedSuspense(block) {
|
|
|
24550
24574
|
}
|
|
24551
24575
|
return false;
|
|
24552
24576
|
}
|
|
24577
|
+
function markerlessBranchRoots(scope, domParent, after, end = null) {
|
|
24578
|
+
let roots = 0;
|
|
24579
|
+
const slots = scope._slots;
|
|
24580
|
+
if (slots !== null) {
|
|
24581
|
+
for (let i = 0; i < slots.length; i++) {
|
|
24582
|
+
const slot = slots[i];
|
|
24583
|
+
if (slot.anchor === after && (slot.__kind === "ifBlockSlot" || slot.__kind === "switchBlockSlot" || slot.__kind === "componentSlotSlot" && slot.block?.parentNode === domParent)) {
|
|
24584
|
+
roots++;
|
|
24585
|
+
if (end !== null) {
|
|
24586
|
+
journalRootProperty(slot, "anchor", slot.anchor);
|
|
24587
|
+
slot.anchor = end;
|
|
24588
|
+
}
|
|
24589
|
+
}
|
|
24590
|
+
}
|
|
24591
|
+
}
|
|
24592
|
+
const children = scope.children;
|
|
24593
|
+
if (children !== null) {
|
|
24594
|
+
for (let i = 0; i < children.length; i++) {
|
|
24595
|
+
const child2 = children[i].scope;
|
|
24596
|
+
const block = child2.block;
|
|
24597
|
+
if (block !== scope.block && block.parentNode === domParent && block.endMarker === after) {
|
|
24598
|
+
roots += markerlessBranchRoots(child2, domParent, after, end) || 1;
|
|
24599
|
+
if (end !== null) {
|
|
24600
|
+
journalRootProperty(block, "endMarker", block.endMarker);
|
|
24601
|
+
block.endMarker = end;
|
|
24602
|
+
}
|
|
24603
|
+
}
|
|
24604
|
+
}
|
|
24605
|
+
}
|
|
24606
|
+
return roots;
|
|
24607
|
+
}
|
|
24553
24608
|
function finalizeMarkerlessBranch(state, domParent, block, marker, before, after) {
|
|
24554
24609
|
state.markerlessBefore = void 0;
|
|
24555
24610
|
if (state.borrowed && state.start === null) return;
|
|
24556
24611
|
const first = before ? getNextSibling(before) : getFirstChild(domParent);
|
|
24557
24612
|
const last = after ? (STAGED_DOM?.view(after) ?? after).previousSibling : (STAGED_DOM?.view(domParent) ?? domParent).lastChild;
|
|
24558
|
-
if (last !== null && first === last && first.nodeType === 1) {
|
|
24613
|
+
if (last !== null && first === last && first.nodeType === 1 && markerlessBranchRoots(block, domParent, after) <= 1) {
|
|
24559
24614
|
block.startMarker = first;
|
|
24560
24615
|
block.endMarker = first;
|
|
24561
24616
|
state.end = first;
|
|
@@ -24569,6 +24624,7 @@ function finalizeMarkerlessBranch(state, domParent, block, marker, before, after
|
|
|
24569
24624
|
block.exclusiveMarkers = true;
|
|
24570
24625
|
state.start = start;
|
|
24571
24626
|
state.end = end;
|
|
24627
|
+
markerlessBranchRoots(block, domParent, after, end);
|
|
24572
24628
|
}
|
|
24573
24629
|
}
|
|
24574
24630
|
function replaceSharedBlockBoundary(parent, oldStart, oldEnd, newStart, newEnd) {
|
|
@@ -28703,6 +28759,7 @@ function scriptResource(attrs) {
|
|
|
28703
28759
|
isChildrenBlock,
|
|
28704
28760
|
isHydratingStyle,
|
|
28705
28761
|
isInActScope,
|
|
28762
|
+
isNativeSignalDiagnosticProbe,
|
|
28706
28763
|
isValidElement,
|
|
28707
28764
|
keyedForBlock,
|
|
28708
28765
|
lazy,
|
|
@@ -24,6 +24,7 @@ __export(client_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(client_exports);
|
|
25
25
|
__reExport(client_exports, require("./index.cjs"), module.exports);
|
|
26
26
|
var import_runtime = require("../runtime.cjs");
|
|
27
|
+
var import_diagnostic_local_hook = require("./diagnostic-local-hook.cjs");
|
|
27
28
|
var import_engine = require("./engine.cjs");
|
|
28
29
|
function disposeLocalSignal(cell) {
|
|
29
30
|
cell.scope.dispose();
|
|
@@ -37,7 +38,11 @@ function useSignal$(initial, slot) {
|
|
|
37
38
|
return { scope, signal$: scope.signal$("value", value) };
|
|
38
39
|
},
|
|
39
40
|
disposeLocalSignal,
|
|
40
|
-
slot
|
|
41
|
+
slot,
|
|
42
|
+
process.env.NODE_ENV === "production" || typeof initial === "function" || !(0, import_runtime.isNativeSignalDiagnosticProbe)() ? void 0 : (0, import_diagnostic_local_hook.createNativeSignalDiagnosticInitializer)(() => {
|
|
43
|
+
const scope = (0, import_engine.createDiagnosticLocalScope)("octane/useSignal$");
|
|
44
|
+
return { scope, signal$: scope.signal$("value", initial) };
|
|
45
|
+
})
|
|
41
46
|
);
|
|
42
47
|
return cell.signal$;
|
|
43
48
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var diagnostic_local_hook_exports = {};
|
|
20
|
+
__export(diagnostic_local_hook_exports, {
|
|
21
|
+
createNativeSignalDiagnosticInitializer: () => createNativeSignalDiagnosticInitializer,
|
|
22
|
+
isNativeSignalDiagnosticInitializer: () => isNativeSignalDiagnosticInitializer
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(diagnostic_local_hook_exports);
|
|
25
|
+
const DIAGNOSTIC_SIGNAL_INITIALIZERS = /* @__PURE__ */ new WeakSet();
|
|
26
|
+
function createNativeSignalDiagnosticInitializer(initialize) {
|
|
27
|
+
DIAGNOSTIC_SIGNAL_INITIALIZERS.add(initialize);
|
|
28
|
+
return initialize;
|
|
29
|
+
}
|
|
30
|
+
function isNativeSignalDiagnosticInitializer(value) {
|
|
31
|
+
return DIAGNOSTIC_SIGNAL_INITIALIZERS.has(value);
|
|
32
|
+
}
|
|
33
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
34
|
+
0 && (module.exports = {
|
|
35
|
+
createNativeSignalDiagnosticInitializer,
|
|
36
|
+
isNativeSignalDiagnosticInitializer
|
|
37
|
+
});
|
|
@@ -24,6 +24,7 @@ __export(engine_exports, {
|
|
|
24
24
|
bindScopeStreamedSelection: () => bindScopeStreamedSelection,
|
|
25
25
|
createDeclaredSignalCell: () => createDeclaredSignalCell,
|
|
26
26
|
createDerivedCellWith: () => createDerivedCellWith,
|
|
27
|
+
createDiagnosticLocalScope: () => createDiagnosticLocalScope,
|
|
27
28
|
createLocalScope: () => createLocalScope,
|
|
28
29
|
createResourceCellWith: () => createResourceCellWith,
|
|
29
30
|
createScope: () => createScope,
|
|
@@ -105,6 +106,7 @@ function decodeSeed(scopeKey, seed) {
|
|
|
105
106
|
}
|
|
106
107
|
return entries;
|
|
107
108
|
}
|
|
109
|
+
const DIAGNOSTIC_LOCAL_SCOPES = /* @__PURE__ */ new WeakSet();
|
|
108
110
|
class ScopeImpl {
|
|
109
111
|
constructor(key, options, seedable = true) {
|
|
110
112
|
this.key = key;
|
|
@@ -591,7 +593,8 @@ class ScopeImpl {
|
|
|
591
593
|
}
|
|
592
594
|
dispose() {
|
|
593
595
|
if (this.disposed) return;
|
|
594
|
-
(
|
|
596
|
+
if (process.env.NODE_ENV === "production" || !DIAGNOSTIC_LOCAL_SCOPES.has(this))
|
|
597
|
+
(0, import_graph.assertWritable)();
|
|
595
598
|
(0, import_graph.signalBatch)(() => {
|
|
596
599
|
this.disposed = true;
|
|
597
600
|
this.lifetime++;
|
|
@@ -734,6 +737,13 @@ function createScope(options) {
|
|
|
734
737
|
function createLocalScope(scopeKey) {
|
|
735
738
|
return new ScopeImpl(scopeKey, { scopeKey }, false);
|
|
736
739
|
}
|
|
740
|
+
function createDiagnosticLocalScope(scopeKey) {
|
|
741
|
+
if (process.env.NODE_ENV === "production" || !(0, import_read_protocol.isNativeWriteGuarded)() || (0, import_read_protocol.getNativeReadObserver)() !== null)
|
|
742
|
+
throw new import_errors.SignalFrameError("Diagnostic local scopes require an isolated historical read.");
|
|
743
|
+
const scope = new ScopeImpl(scopeKey, { scopeKey }, false);
|
|
744
|
+
DIAGNOSTIC_LOCAL_SCOPES.add(scope);
|
|
745
|
+
return scope;
|
|
746
|
+
}
|
|
737
747
|
function createDeclaredSignalCell(owner, key, initial, preferInitial = false) {
|
|
738
748
|
if (!(owner instanceof ScopeImpl)) throw new TypeError("A direct signal needs an Octane scope.");
|
|
739
749
|
return owner.createSignalDeclaration(key, initial, preferInitial);
|
|
@@ -776,6 +786,7 @@ function failScopeStreamedResult(owner, identity, error) {
|
|
|
776
786
|
bindScopeStreamedSelection,
|
|
777
787
|
createDeclaredSignalCell,
|
|
778
788
|
createDerivedCellWith,
|
|
789
|
+
createDiagnosticLocalScope,
|
|
779
790
|
createLocalScope,
|
|
780
791
|
createResourceCellWith,
|
|
781
792
|
createScope,
|
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.4.
|
|
24
|
+
const version = "0.4.2";
|
|
25
25
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
26
|
0 && (module.exports = {
|
|
27
27
|
version
|
package/dist/compiler/compile.js
CHANGED
|
@@ -14366,6 +14366,7 @@ function ssrEmitActivity(node, ctx, name, inlinedSubs, parentNs, cssHash, compon
|
|
|
14366
14366
|
|
|
14367
14367
|
function ssrEmitFor(node, ctx, name, inlinedSubs, parentNs, cssHash, componentNs) {
|
|
14368
14368
|
const bindingSite = node._octaneBindingSite;
|
|
14369
|
+
const itemBody = forItemTemplateBody(node, ctx);
|
|
14369
14370
|
// rewriteHookCalls: key any `use(thenable)` in the @for iterable expression.
|
|
14370
14371
|
const itemsExpr = rewriteHookCalls(node.right, ctx, name);
|
|
14371
14372
|
const mapCall = node.nativeArrayMap || null;
|
|
@@ -14373,7 +14374,7 @@ function ssrEmitFor(node, ctx, name, inlinedSubs, parentNs, cssHash, componentNs
|
|
|
14373
14374
|
const params = [itemId];
|
|
14374
14375
|
if (node.index) params.push(node.index);
|
|
14375
14376
|
const itemSub = ssrCompileSub(
|
|
14376
|
-
|
|
14377
|
+
itemBody,
|
|
14377
14378
|
ctx,
|
|
14378
14379
|
'__sitem',
|
|
14379
14380
|
params,
|
|
@@ -14461,8 +14462,8 @@ function ssrEmitFor(node, ctx, name, inlinedSubs, parentNs, cssHash, componentNs
|
|
|
14461
14462
|
// attribute serialization stay on the allocation-free path, matching the
|
|
14462
14463
|
// client forBlock's existing PURE-body proof.
|
|
14463
14464
|
const itemNeedsIdentity =
|
|
14464
|
-
containsComponentCallOrControlFlow(
|
|
14465
|
-
containsRenderCall(
|
|
14465
|
+
containsComponentCallOrControlFlow(itemBody) ||
|
|
14466
|
+
containsRenderCall(itemBody) ||
|
|
14466
14467
|
ssrAstCallsAny(itemSub.fn, ['_$ssrChild', '_$ssrComponent']);
|
|
14467
14468
|
const itemCall = ssrSubCall(
|
|
14468
14469
|
itemSub.fnName,
|
|
@@ -25141,6 +25142,7 @@ function planJsx(
|
|
|
25141
25142
|
b.deferred =
|
|
25142
25143
|
DEFERRABLE_MOUNT_KINDS.has(b.kind) &&
|
|
25143
25144
|
!sharesSpreadHost &&
|
|
25145
|
+
!b.beforeConnect &&
|
|
25144
25146
|
b.name !== 'dangerouslySetInnerHTML';
|
|
25145
25147
|
}
|
|
25146
25148
|
|
|
@@ -25213,7 +25215,9 @@ function planJsx(
|
|
|
25213
25215
|
// these text mounts and flush them AFTER every walk has been emitted, so all navigation
|
|
25214
25216
|
// happens on the intact template. (Regression: StoryRow's `.meta` interleaves text holes
|
|
25215
25217
|
// with `<Link>` components.)
|
|
25216
|
-
|
|
25218
|
+
// Connection-sensitive attributes also wait for every mount flag (including
|
|
25219
|
+
// suppressHydrationWarning) before writing, but still run before insertion.
|
|
25220
|
+
const postWalkMounts = [];
|
|
25217
25221
|
let nativeStyleSlots = 0;
|
|
25218
25222
|
// Emit per-binding mount code.
|
|
25219
25223
|
for (const b of elementBindings) {
|
|
@@ -25329,7 +25333,7 @@ function planJsx(
|
|
|
25329
25333
|
// `htextSwap` (sibling text hole) detaches its `<!>`; defer it past all walks (see above).
|
|
25330
25334
|
const mountEmit = emitBindingMount(b, elVar, bag);
|
|
25331
25335
|
if (mountEmit !== null) {
|
|
25332
|
-
const target = b.kind === 'text' ?
|
|
25336
|
+
const target = b.kind === 'text' || b.beforeConnect ? postWalkMounts : mountLines;
|
|
25333
25337
|
if (Array.isArray(mountEmit)) target.push(...mountEmit);
|
|
25334
25338
|
else target.push(mountEmit);
|
|
25335
25339
|
}
|
|
@@ -25395,9 +25399,9 @@ function planJsx(
|
|
|
25395
25399
|
anchorKey: 'portalAnchor',
|
|
25396
25400
|
stampLoc: false,
|
|
25397
25401
|
});
|
|
25398
|
-
//
|
|
25399
|
-
//
|
|
25400
|
-
for (const line of
|
|
25402
|
+
// Every element walk and mount flag is ready: text holes can replace their
|
|
25403
|
+
// placeholders and iframe sources can initialize before the root is inserted.
|
|
25404
|
+
for (const line of postWalkMounts) mountLines.push(line);
|
|
25401
25405
|
|
|
25402
25406
|
if (!noTemplate) {
|
|
25403
25407
|
// Allocate + insert + commit in ONE shared-factory call, LAST — see the
|
|
@@ -29349,6 +29353,9 @@ function emitElementHtml(
|
|
|
29349
29353
|
id: bindings.length,
|
|
29350
29354
|
kind: 'attr',
|
|
29351
29355
|
attributeHelper: writer?.helper,
|
|
29356
|
+
// Connecting an iframe without its source creates an initial
|
|
29357
|
+
// document before the intended navigation and sandbox checks.
|
|
29358
|
+
beforeConnect: tag === 'iframe' && attrName.toLowerCase() === 'src',
|
|
29352
29359
|
name:
|
|
29353
29360
|
ctx.dev && (rawAttrName === 'tabIndex' || rawAttrName === 'htmlFor')
|
|
29354
29361
|
? rawAttrName
|
|
@@ -31580,6 +31587,79 @@ function keyedSelectionDepIndex(itemName, keyBody, subStmts, runtimeDepNames, ct
|
|
|
31580
31587
|
return runtimeDepNames.indexOf(selected.name);
|
|
31581
31588
|
}
|
|
31582
31589
|
|
|
31590
|
+
// The first root's legacy key already owns the entire row through keyFn.
|
|
31591
|
+
// Avoid a second descriptor boundary for that same key. Only consume a host
|
|
31592
|
+
// key when the row cannot change a collected key before a later child reads it.
|
|
31593
|
+
// Opaque rendering, spreads and duplicate keys retain the existing boundary.
|
|
31594
|
+
// Component keys and nested host keys retain their own reconciliation ranges.
|
|
31595
|
+
function forItemTemplateBody(node, ctx) {
|
|
31596
|
+
const body = node.body.body;
|
|
31597
|
+
if (ctx._universalRuntimeUnit != null || body.length !== 1) return body;
|
|
31598
|
+
const root = body[0];
|
|
31599
|
+
if (!isPlainHostRoot(root) || isActivityLongForm(root, ctx) || isFragmentLongForm(root, ctx))
|
|
31600
|
+
return body;
|
|
31601
|
+
const attrs = root.attributes || root.openingElement?.attributes || [];
|
|
31602
|
+
let keyIndex = -1;
|
|
31603
|
+
for (let i = 0; i < attrs.length; i++) {
|
|
31604
|
+
const attr = attrs[i];
|
|
31605
|
+
if (attr.type === 'SpreadAttribute' || attr.type === 'JSXSpreadAttribute') return body;
|
|
31606
|
+
if (jsxAttrRawName(attr) !== 'key') continue;
|
|
31607
|
+
if (keyIndex !== -1 || attr.value == null) return body;
|
|
31608
|
+
keyIndex = i;
|
|
31609
|
+
}
|
|
31610
|
+
if (keyIndex === -1) return body;
|
|
31611
|
+
const value = attrs[keyIndex].value;
|
|
31612
|
+
const key = value.type === 'JSXExpressionContainer' ? value.expression : value;
|
|
31613
|
+
if (!isDeferralSafeBundleArg(key)) return body;
|
|
31614
|
+
// Destructuring must not invoke defaults, computed reads or an iterator.
|
|
31615
|
+
if (!isAutoMemoPropsParam(node.left.declarations[0].id)) return body;
|
|
31616
|
+
function stableHost(host) {
|
|
31617
|
+
if (!isPlainHostRoot(host) || isActivityLongForm(host, ctx) || isFragmentLongForm(host, ctx))
|
|
31618
|
+
return false;
|
|
31619
|
+
const tag = host.id?.name ?? host.openingElement?.name?.name;
|
|
31620
|
+
if (tag.includes('-') || tag === 'script') return false;
|
|
31621
|
+
const attributes = host.attributes || host.openingElement?.attributes || [];
|
|
31622
|
+
if (
|
|
31623
|
+
attributes.some(
|
|
31624
|
+
(attr) =>
|
|
31625
|
+
attr.type === 'SpreadAttribute' ||
|
|
31626
|
+
attr.type === 'JSXSpreadAttribute' ||
|
|
31627
|
+
jsxAttrRawName(attr) === 'is' ||
|
|
31628
|
+
jsxAttrRawName(attr) === 'children',
|
|
31629
|
+
)
|
|
31630
|
+
)
|
|
31631
|
+
return false;
|
|
31632
|
+
// Inspect values so deferred event/ref callbacks remain eligible.
|
|
31633
|
+
const values = attributes.map((attr) => attr.value);
|
|
31634
|
+
if (containsRenderCall(values) || containsAutoMemoUnsafeStructure(values)) return false;
|
|
31635
|
+
for (const child of host.children || []) {
|
|
31636
|
+
if (child.type === 'JSXText') continue;
|
|
31637
|
+
if (child.type === 'Text' || child.type === 'JSXExpressionContainer') {
|
|
31638
|
+
const expr = child.expression;
|
|
31639
|
+
if (!expr || expr.type === 'JSXEmptyExpression') continue;
|
|
31640
|
+
if (
|
|
31641
|
+
!isKnownTextChildExpression(expr) ||
|
|
31642
|
+
containsRenderCall([expr]) ||
|
|
31643
|
+
containsAutoMemoUnsafeStructure([expr])
|
|
31644
|
+
)
|
|
31645
|
+
return false;
|
|
31646
|
+
} else if (!stableHost(child)) return false;
|
|
31647
|
+
}
|
|
31648
|
+
return true;
|
|
31649
|
+
}
|
|
31650
|
+
if (!stableHost(root)) return body;
|
|
31651
|
+
const kept = attrs.filter((_, index) => index !== keyIndex);
|
|
31652
|
+
return [
|
|
31653
|
+
root.openingElement
|
|
31654
|
+
? {
|
|
31655
|
+
...root,
|
|
31656
|
+
...(root.attributes === undefined ? {} : { attributes: kept }),
|
|
31657
|
+
openingElement: { ...root.openingElement, attributes: kept },
|
|
31658
|
+
}
|
|
31659
|
+
: { ...root, attributes: kept },
|
|
31660
|
+
];
|
|
31661
|
+
}
|
|
31662
|
+
|
|
31583
31663
|
function makeForCall(node, ctx, inlinedSubs, parentNs = 'html', cssHash = null) {
|
|
31584
31664
|
// `@for await (...)` (async iteration) has no meaning for the runtime's
|
|
31585
31665
|
// synchronous keyed reconciler. The TSRX parser currently rejects the surface
|
|
@@ -31613,7 +31693,7 @@ function makeForCall(node, ctx, inlinedSubs, parentNs = 'html', cssHash = null)
|
|
|
31613
31693
|
// we synthesize a fresh name and emit the destructuring inside the body so
|
|
31614
31694
|
// the keyFn still gets the whole item and the body still sees the fields.
|
|
31615
31695
|
const itemName = isDestructured ? '_item' : leftDeclId.name;
|
|
31616
|
-
const subStmts = node
|
|
31696
|
+
const subStmts = forItemTemplateBody(node, ctx);
|
|
31617
31697
|
|
|
31618
31698
|
// Key resolution priority (matches @tsrx/core's build_hoisted_for_of_with_hooks):
|
|
31619
31699
|
// 1. `key={…}` attribute on the first Element child (legacy / explicit).
|
|
@@ -31638,7 +31718,7 @@ function makeForCall(node, ctx, inlinedSubs, parentNs = 'html', cssHash = null)
|
|
|
31638
31718
|
// body for the first Element and pull its `key=` attr if any. Accept both
|
|
31639
31719
|
// the old `Element` IR and the raw new `JSXElement` shape that's reached
|
|
31640
31720
|
// here when the body wasn't routed through normalizeChildren.
|
|
31641
|
-
const firstEl =
|
|
31721
|
+
const firstEl = node.body.body.find((n) => n.type === 'Element' || n.type === 'JSXElement');
|
|
31642
31722
|
if (firstEl) {
|
|
31643
31723
|
const keyAttr = (firstEl.attributes || firstEl.openingElement?.attributes || []).find(
|
|
31644
31724
|
(a) => (a.name?.name || a.name) === 'key',
|
|
@@ -31848,18 +31928,17 @@ function makeForCall(node, ctx, inlinedSubs, parentNs = 'html', cssHash = null)
|
|
|
31848
31928
|
const regionStmts = emptyStmts ? [...subStmts, ...emptyStmts] : subStmts;
|
|
31849
31929
|
const regionAst = b.block(regionStmts);
|
|
31850
31930
|
const regionFree = collectFreeIdentifiers(regionAst, bodyScope);
|
|
31851
|
-
|
|
31852
|
-
for (const name of collectFreeIdentifiers(node.key, bodyScope)) regionFree.add(name);
|
|
31853
|
-
}
|
|
31931
|
+
for (const name of collectFreeIdentifiers(keyBody, bodyScope)) regionFree.add(name);
|
|
31854
31932
|
let listSafe =
|
|
31855
31933
|
ctx.autoMemo === true &&
|
|
31856
31934
|
!hasPerItemEventClosure &&
|
|
31857
31935
|
isAutoMemoCalculationDependency(node.right) &&
|
|
31858
31936
|
!hasHook &&
|
|
31859
31937
|
!containsRenderCall(regionStmts, ctx) &&
|
|
31860
|
-
!containsRenderCall(
|
|
31938
|
+
!containsRenderCall([keyBody], ctx) &&
|
|
31861
31939
|
!containsAutoMemoUnsafeStructure(regionStmts, ctx) &&
|
|
31862
|
-
!containsAutoMemoUnsafeStructure(
|
|
31940
|
+
!containsAutoMemoUnsafeStructure([keyBody], ctx) &&
|
|
31941
|
+
!containsImportedMemberRead(keyBody, ctx.importedNames) &&
|
|
31863
31942
|
!containsImportedMemberRead(regionAst, ctx.importedNames);
|
|
31864
31943
|
const listDeps = new Set();
|
|
31865
31944
|
const witnesses = collectImportedComponentReferences(regionAst, ctx.importedNames);
|
|
@@ -122,6 +122,21 @@ for (const name of [
|
|
|
122
122
|
]) {
|
|
123
123
|
KNOWN_SVG_PROPERTY_SPELLINGS.set(name.toLowerCase(), name);
|
|
124
124
|
}
|
|
125
|
+
const NON_NATIVE_LOWERCASE_PROPERTIES = /* @__PURE__ */ new Set([
|
|
126
|
+
"autoFocus",
|
|
127
|
+
"defaultValue",
|
|
128
|
+
"defaultChecked",
|
|
129
|
+
"dangerouslySetInnerHTML",
|
|
130
|
+
"className",
|
|
131
|
+
"suppressContentEditableWarning",
|
|
132
|
+
"suppressHydrationWarning",
|
|
133
|
+
"suppressNativeChangeWarning",
|
|
134
|
+
"__octaneNativeChangeDiagnostic",
|
|
135
|
+
"acceptCharset",
|
|
136
|
+
"htmlFor",
|
|
137
|
+
"httpEquiv",
|
|
138
|
+
"viewBox"
|
|
139
|
+
]);
|
|
125
140
|
function hostPropertyWarning(name, value, tag, isSvg = false) {
|
|
126
141
|
const lower = name.toLowerCase();
|
|
127
142
|
if (name === "for" && tag === "label") return null;
|
|
@@ -137,6 +152,9 @@ function hostPropertyWarning(name, value, tag, isSvg = false) {
|
|
|
137
152
|
if (name.startsWith("aria-") || /^aria[A-Z]/.test(name) || name.startsWith("data-")) return null;
|
|
138
153
|
const known = KNOWN_PROPERTY_SPELLINGS.get(lower) ?? (isSvg ? KNOWN_SVG_PROPERTY_SPELLINGS.get(lower) : void 0);
|
|
139
154
|
if (known !== void 0) {
|
|
155
|
+
if (!isSvg && name === lower && // Hyphenated/namespaced presentation aliases belong to SVG, not HTML.
|
|
156
|
+
!name.includes("-") && !name.includes(":") && !NON_NATIVE_LOWERCASE_PROPERTIES.has(known) && (ATTRIBUTE_ALIASES.get(known) ?? lower) === lower)
|
|
157
|
+
return null;
|
|
140
158
|
if (isSvg && ATTRIBUTE_ALIASES.get(known) === name) return null;
|
|
141
159
|
return name !== known ? `Invalid DOM property \`${name}\`. Did you mean \`${known}\`?` : null;
|
|
142
160
|
}
|
package/dist/runtime.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { validateNativeReadWitness, type NativeReadWitness } from './signals/nat
|
|
|
24
24
|
import { type NativeReadRetry } from './signals/native-read-retry.js';
|
|
25
25
|
import type { SignalActionFrame } from './signals/transition-action.js';
|
|
26
26
|
import { setNativeAdoptionResolver } from './signals/read-protocol.js';
|
|
27
|
+
import { type DiagnosticSignalInitializer } from './signals/diagnostic-local-hook.js';
|
|
27
28
|
import { type NativeAdoptionState } from './signals/native-read-seeds.js';
|
|
28
29
|
export { documentSignalOwner, installStreamedSignalOwnerActivator, } from './signals/document-owner.js';
|
|
29
30
|
import { type SignalHandle, type SignalOwner, type SignalRendererOwnerIdentity } from './signals/types.js';
|
|
@@ -824,8 +825,10 @@ export declare function manualHook<F extends (...args: any[]) => any>(fn: F, nam
|
|
|
824
825
|
/** Invoke a cached optional-chain method without consulting its call/bind properties. */
|
|
825
826
|
export declare function callWithReceiver<T>(fn: (...args: any[]) => T, receiver: unknown, ...args: any[]): T;
|
|
826
827
|
export declare function withSlot<T>(sym: symbol, fn: (...a: any[]) => T, ...args: any[]): T;
|
|
828
|
+
/** @internal Built-in adapters are allocated only during historical comparison. */
|
|
829
|
+
export declare function isNativeSignalDiagnosticProbe(): boolean;
|
|
827
830
|
/** @internal Optional native hooks use the existing compiler slot and Scope lifetime. */
|
|
828
|
-
export declare function nativeLocalHook<T>(name: string, initialize: () => T, dispose: (value: T) => void, slot?: HookSlot): T;
|
|
831
|
+
export declare function nativeLocalHook<T>(name: string, initialize: () => T, dispose: (value: T) => void, slot?: HookSlot, diagnosticInitialize?: DiagnosticSignalInitializer<T>): T;
|
|
829
832
|
interface StateSlot<T> {
|
|
830
833
|
value: T;
|
|
831
834
|
setter: (next: T | ((prev: T) => T)) => void;
|
package/dist/runtime.js
CHANGED
|
@@ -180,9 +180,14 @@ import {
|
|
|
180
180
|
registerNativeActionResolver,
|
|
181
181
|
runNativeBatch,
|
|
182
182
|
setNativeCandidateResolver,
|
|
183
|
-
setNativeAdoptionResolver
|
|
183
|
+
setNativeAdoptionResolver,
|
|
184
|
+
beginNativeWriteGuard,
|
|
185
|
+
endNativeWriteGuard
|
|
184
186
|
} from "./signals/read-protocol.js";
|
|
185
187
|
import { beginNativeEventBatch, endNativeEventBatch } from "./signals/native-read-events.js";
|
|
188
|
+
import {
|
|
189
|
+
isNativeSignalDiagnosticInitializer
|
|
190
|
+
} from "./signals/diagnostic-local-hook.js";
|
|
186
191
|
import {
|
|
187
192
|
createNativeAdoptionState,
|
|
188
193
|
NATIVE_SIGNAL_SEED_ATTR,
|
|
@@ -686,12 +691,12 @@ function nativePresentationBinding(owner, slotIndex, el, body, props) {
|
|
|
686
691
|
}
|
|
687
692
|
function enableNativeReadCollection(abi = 1) {
|
|
688
693
|
if (abi !== 1) throw new Error(formatClientError(58));
|
|
694
|
+
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return;
|
|
689
695
|
ensureNativeReadDriver();
|
|
690
696
|
}
|
|
691
697
|
function beginNativeReadScope(scope, abi = 1) {
|
|
692
|
-
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null)
|
|
693
|
-
throw new PresentationAdoptionMiss(void 0, false);
|
|
694
698
|
if (abi !== 1) throw new Error(formatClientError(58));
|
|
699
|
+
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return -1;
|
|
695
700
|
const block = CURRENT_BLOCK;
|
|
696
701
|
const owner = scope ?? CURRENT_SCOPE;
|
|
697
702
|
if (block === null || owner === null) return -1;
|
|
@@ -807,12 +812,14 @@ function endNativeReadScope(token, _completed) {
|
|
|
807
812
|
if (token >= 0) NATIVE_READ_DRIVER.endScope(token);
|
|
808
813
|
}
|
|
809
814
|
function beginNativeReadWitness(detached = false) {
|
|
815
|
+
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return -1;
|
|
810
816
|
return detached ? ensureNativeReadDriver().beginWitness(true) : NATIVE_READ_DRIVER?.beginWitness() ?? -1;
|
|
811
817
|
}
|
|
812
818
|
function finishNativeReadWitness(token, completed) {
|
|
813
819
|
return token < 0 ? null : NATIVE_READ_DRIVER.finishWitness(token, completed);
|
|
814
820
|
}
|
|
815
821
|
function replayNativeReadWitness(witness) {
|
|
822
|
+
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return;
|
|
816
823
|
NATIVE_READ_DRIVER?.replay(witness);
|
|
817
824
|
}
|
|
818
825
|
function retainNativeRetryReads(block, reads) {
|
|
@@ -6642,7 +6649,8 @@ function renderBlockInner(block) {
|
|
|
6642
6649
|
let profileThrown;
|
|
6643
6650
|
let renderCompleted = false;
|
|
6644
6651
|
let renderRetry = false;
|
|
6645
|
-
|
|
6652
|
+
if (process.env.NODE_ENV === "production" || hydrateAttributeProbe === null)
|
|
6653
|
+
NATIVE_READ_DRIVER?.beginRender(block);
|
|
6646
6654
|
NATIVE_BLOCK_RETRIES?.get(block)?.clear();
|
|
6647
6655
|
try {
|
|
6648
6656
|
if (urgentTransitionRender !== null)
|
|
@@ -6710,7 +6718,8 @@ function renderBlockInner(block) {
|
|
|
6710
6718
|
CURRENT_SCOPE = prevScope;
|
|
6711
6719
|
CURRENT_BLOCK = prevBlock;
|
|
6712
6720
|
try {
|
|
6713
|
-
|
|
6721
|
+
if (process.env.NODE_ENV === "production" || hydrateAttributeProbe === null)
|
|
6722
|
+
NATIVE_READ_DRIVER?.endRender(block, renderCompleted, isSuspenseException(profileThrown));
|
|
6714
6723
|
} finally {
|
|
6715
6724
|
if (urgentTransitionRender !== null)
|
|
6716
6725
|
urgentTransitionDriver.endUrgent(block, urgentTransitionRender);
|
|
@@ -7328,15 +7337,20 @@ function resolveSlot(slot) {
|
|
|
7328
7337
|
const resolved = resolveHookPath(slotStack, slot, false);
|
|
7329
7338
|
return typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__ ? __profileResolveHook(resolved, typeof slot === "symbol" ? slot : void 0) : resolved;
|
|
7330
7339
|
}
|
|
7331
|
-
function
|
|
7332
|
-
|
|
7340
|
+
function isNativeSignalDiagnosticProbe() {
|
|
7341
|
+
return process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null;
|
|
7342
|
+
}
|
|
7343
|
+
function nativeLocalHook(name, initialize, dispose, slot, diagnosticInitialize) {
|
|
7344
|
+
if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null && (name !== "useSignal$" || diagnosticInitialize === void 0 || !isNativeSignalDiagnosticInitializer(diagnosticInitialize)))
|
|
7333
7345
|
throw new PresentationAdoptionMiss(void 0, false);
|
|
7334
7346
|
slot = resolveSlot(slot);
|
|
7335
7347
|
if (slot === void 0 || CURRENT_SCOPE === null) missingSlot(name);
|
|
7336
7348
|
const scope = CURRENT_SCOPE;
|
|
7337
7349
|
let cell = scope.hooks?.get(slot);
|
|
7338
7350
|
if (cell === void 0) {
|
|
7339
|
-
cell = {
|
|
7351
|
+
cell = {
|
|
7352
|
+
nativeValue: process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null ? diagnosticInitialize() : initialize()
|
|
7353
|
+
};
|
|
7340
7354
|
ensureHooks(scope).set(slot, cell);
|
|
7341
7355
|
const value = cell.nativeValue;
|
|
7342
7356
|
registerHookCleanup(scope, () => dispose(value));
|
|
@@ -8794,6 +8808,7 @@ function collectInitialHydrateAttributes(state, snapshot) {
|
|
|
8794
8808
|
if (state.seedRaw !== null) hydration.seeds = hydration.parseSeeds(state.seedRaw);
|
|
8795
8809
|
hydration.protectRootAnchor(end);
|
|
8796
8810
|
const capture = createOffscreenCapture();
|
|
8811
|
+
const diagnosticNative = state.nativeSeedRaw === void 0 ? void 0 : createNativeAdoptionState(parseNativeSignalManifest(state.nativeSeedRaw));
|
|
8797
8812
|
const previousHydration = currentHydration;
|
|
8798
8813
|
const previousCapture = WIP_CAPTURE;
|
|
8799
8814
|
const previousProbe = hydrateAttributeProbe;
|
|
@@ -8813,7 +8828,10 @@ function collectInitialHydrateAttributes(state, snapshot) {
|
|
|
8813
8828
|
const previousSelectDefaultSyncs = SELECT_DEFAULT_SYNCS;
|
|
8814
8829
|
const previousFormChecks = DEV_FORM_CHECKS;
|
|
8815
8830
|
const previousAutofocus = AUTOFOCUS_QUEUE;
|
|
8816
|
-
const
|
|
8831
|
+
const diagnosticDriver = NATIVE_READ_DRIVER;
|
|
8832
|
+
const nativeProbeToken = diagnosticDriver?.pauseLifecycle() ?? -1;
|
|
8833
|
+
const previousWriteGuard = beginNativeWriteGuard();
|
|
8834
|
+
const previousNative = setNativeAdoptionResolver(diagnosticNative?.resolve ?? null);
|
|
8817
8835
|
const refDetachCheckpoint = refDetachQueue.length;
|
|
8818
8836
|
currentHydration = hydration;
|
|
8819
8837
|
WIP_CAPTURE = capture;
|
|
@@ -8843,27 +8861,36 @@ function collectInitialHydrateAttributes(state, snapshot) {
|
|
|
8843
8861
|
disposeWip({ block, start, end, capture, domParent: wrapper, refDetachCheckpoint });
|
|
8844
8862
|
drainHydrationRenderPhaseUpdates(block);
|
|
8845
8863
|
} finally {
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
|
|
8861
|
-
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8864
|
+
try {
|
|
8865
|
+
diagnosticNative?.release();
|
|
8866
|
+
} finally {
|
|
8867
|
+
try {
|
|
8868
|
+
setNativeAdoptionResolver(previousNative);
|
|
8869
|
+
endNativeWriteGuard(previousWriteGuard);
|
|
8870
|
+
if (nativeProbeToken >= 0) diagnosticDriver.resumeLifecycle(nativeProbeToken);
|
|
8871
|
+
} finally {
|
|
8872
|
+
currentHydration = previousHydration;
|
|
8873
|
+
WIP_CAPTURE = previousCapture;
|
|
8874
|
+
hydrateAttributeProbe = previousProbe;
|
|
8875
|
+
ROOT_RENDER_TRANSACTION = previousTransaction;
|
|
8876
|
+
TRANSITION_JOURNAL = previousJournal;
|
|
8877
|
+
ACTIVE_TRANSITION_ATTEMPT = previousAttempt;
|
|
8878
|
+
SCOPED_READ_TRACKING = previousScopedReadTracking;
|
|
8879
|
+
SCOPED_READS = previousScopedReads;
|
|
8880
|
+
CURRENT_WARM = previousWarm;
|
|
8881
|
+
CURRENT_WARM_CLAIMS = previousWarmClaims;
|
|
8882
|
+
CURRENT_WARM_EPISODE = previousWarmEpisode;
|
|
8883
|
+
ACTIVE_WARM_PLANS.length = 0;
|
|
8884
|
+
ACTIVE_WARM_PLANS.push(...previousWarmPlans);
|
|
8885
|
+
STAGED_DOM = previousStagedDom;
|
|
8886
|
+
STAGED_COMMIT_CAPTURE = previousStagedCapture;
|
|
8887
|
+
PRESENTATION_HYDRATION = previousPresentation;
|
|
8888
|
+
SELECT_SYNCS = previousSelectSyncs;
|
|
8889
|
+
SELECT_DEFAULT_SYNCS = previousSelectDefaultSyncs;
|
|
8890
|
+
DEV_FORM_CHECKS = previousFormChecks;
|
|
8891
|
+
AUTOFOCUS_QUEUE = previousAutofocus;
|
|
8892
|
+
}
|
|
8893
|
+
}
|
|
8867
8894
|
}
|
|
8868
8895
|
}
|
|
8869
8896
|
return probe;
|
|
@@ -24412,12 +24439,43 @@ function preservesCommittedSuspense(block) {
|
|
|
24412
24439
|
}
|
|
24413
24440
|
return false;
|
|
24414
24441
|
}
|
|
24442
|
+
function markerlessBranchRoots(scope, domParent, after, end = null) {
|
|
24443
|
+
let roots = 0;
|
|
24444
|
+
const slots = scope._slots;
|
|
24445
|
+
if (slots !== null) {
|
|
24446
|
+
for (let i = 0; i < slots.length; i++) {
|
|
24447
|
+
const slot = slots[i];
|
|
24448
|
+
if (slot.anchor === after && (slot.__kind === "ifBlockSlot" || slot.__kind === "switchBlockSlot" || slot.__kind === "componentSlotSlot" && slot.block?.parentNode === domParent)) {
|
|
24449
|
+
roots++;
|
|
24450
|
+
if (end !== null) {
|
|
24451
|
+
journalRootProperty(slot, "anchor", slot.anchor);
|
|
24452
|
+
slot.anchor = end;
|
|
24453
|
+
}
|
|
24454
|
+
}
|
|
24455
|
+
}
|
|
24456
|
+
}
|
|
24457
|
+
const children = scope.children;
|
|
24458
|
+
if (children !== null) {
|
|
24459
|
+
for (let i = 0; i < children.length; i++) {
|
|
24460
|
+
const child2 = children[i].scope;
|
|
24461
|
+
const block = child2.block;
|
|
24462
|
+
if (block !== scope.block && block.parentNode === domParent && block.endMarker === after) {
|
|
24463
|
+
roots += markerlessBranchRoots(child2, domParent, after, end) || 1;
|
|
24464
|
+
if (end !== null) {
|
|
24465
|
+
journalRootProperty(block, "endMarker", block.endMarker);
|
|
24466
|
+
block.endMarker = end;
|
|
24467
|
+
}
|
|
24468
|
+
}
|
|
24469
|
+
}
|
|
24470
|
+
}
|
|
24471
|
+
return roots;
|
|
24472
|
+
}
|
|
24415
24473
|
function finalizeMarkerlessBranch(state, domParent, block, marker, before, after) {
|
|
24416
24474
|
state.markerlessBefore = void 0;
|
|
24417
24475
|
if (state.borrowed && state.start === null) return;
|
|
24418
24476
|
const first = before ? getNextSibling(before) : getFirstChild(domParent);
|
|
24419
24477
|
const last = after ? (STAGED_DOM?.view(after) ?? after).previousSibling : (STAGED_DOM?.view(domParent) ?? domParent).lastChild;
|
|
24420
|
-
if (last !== null && first === last && first.nodeType === 1) {
|
|
24478
|
+
if (last !== null && first === last && first.nodeType === 1 && markerlessBranchRoots(block, domParent, after) <= 1) {
|
|
24421
24479
|
block.startMarker = first;
|
|
24422
24480
|
block.endMarker = first;
|
|
24423
24481
|
state.end = first;
|
|
@@ -24431,6 +24489,7 @@ function finalizeMarkerlessBranch(state, domParent, block, marker, before, after
|
|
|
24431
24489
|
block.exclusiveMarkers = true;
|
|
24432
24490
|
state.start = start;
|
|
24433
24491
|
state.end = end;
|
|
24492
|
+
markerlessBranchRoots(block, domParent, after, end);
|
|
24434
24493
|
}
|
|
24435
24494
|
}
|
|
24436
24495
|
function replaceSharedBlockBoundary(parent, oldStart, oldEnd, newStart, newEnd) {
|
|
@@ -28564,6 +28623,7 @@ export {
|
|
|
28564
28623
|
isChildrenBlock,
|
|
28565
28624
|
isHydratingStyle,
|
|
28566
28625
|
isInActScope,
|
|
28626
|
+
isNativeSignalDiagnosticProbe,
|
|
28567
28627
|
isValidElement,
|
|
28568
28628
|
keyedForBlock,
|
|
28569
28629
|
lazy,
|
package/dist/signals/client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./index.js";
|
|
2
|
-
import { nativeLocalHook } from "../runtime.js";
|
|
3
|
-
import {
|
|
2
|
+
import { isNativeSignalDiagnosticProbe, nativeLocalHook } from "../runtime.js";
|
|
3
|
+
import { createNativeSignalDiagnosticInitializer } from "./diagnostic-local-hook.js";
|
|
4
|
+
import { createDiagnosticLocalScope, createLocalScope } from "./engine.js";
|
|
4
5
|
function disposeLocalSignal(cell) {
|
|
5
6
|
cell.scope.dispose();
|
|
6
7
|
}
|
|
@@ -13,7 +14,11 @@ function useSignal$(initial, slot) {
|
|
|
13
14
|
return { scope, signal$: scope.signal$("value", value) };
|
|
14
15
|
},
|
|
15
16
|
disposeLocalSignal,
|
|
16
|
-
slot
|
|
17
|
+
slot,
|
|
18
|
+
process.env.NODE_ENV === "production" || typeof initial === "function" || !isNativeSignalDiagnosticProbe() ? void 0 : createNativeSignalDiagnosticInitializer(() => {
|
|
19
|
+
const scope = createDiagnosticLocalScope("octane/useSignal$");
|
|
20
|
+
return { scope, signal$: scope.signal$("value", initial) };
|
|
21
|
+
})
|
|
17
22
|
);
|
|
18
23
|
return cell.signal$;
|
|
19
24
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare const DIAGNOSTIC_SIGNAL_INITIALIZER: unique symbol;
|
|
2
|
+
export type DiagnosticSignalInitializer<T> = (() => T) & {
|
|
3
|
+
readonly [DIAGNOSTIC_SIGNAL_INITIALIZER]: true;
|
|
4
|
+
};
|
|
5
|
+
/** @internal Private built-in useSignal$ adapter; not a public native-hook resource factory. */
|
|
6
|
+
export declare function createNativeSignalDiagnosticInitializer<T>(initialize: () => T): DiagnosticSignalInitializer<T>;
|
|
7
|
+
export declare function isNativeSignalDiagnosticInitializer(value: () => unknown): boolean;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const DIAGNOSTIC_SIGNAL_INITIALIZERS = /* @__PURE__ */ new WeakSet();
|
|
2
|
+
function createNativeSignalDiagnosticInitializer(initialize) {
|
|
3
|
+
DIAGNOSTIC_SIGNAL_INITIALIZERS.add(initialize);
|
|
4
|
+
return initialize;
|
|
5
|
+
}
|
|
6
|
+
function isNativeSignalDiagnosticInitializer(value) {
|
|
7
|
+
return DIAGNOSTIC_SIGNAL_INITIALIZERS.has(value);
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
createNativeSignalDiagnosticInitializer,
|
|
11
|
+
isNativeSignalDiagnosticInitializer
|
|
12
|
+
};
|
package/dist/signals/engine.d.ts
CHANGED
|
@@ -105,6 +105,8 @@ declare class AdoptionFrameImpl implements AdoptionFrame {
|
|
|
105
105
|
export declare function createScope(options: ScopeOptions): Scope;
|
|
106
106
|
/** Only the native hook adapter may create a component-owned, non-serializable scope. */
|
|
107
107
|
export declare function createLocalScope(scopeKey: string): Scope;
|
|
108
|
+
/** @internal Isolated historical useSignal$ state, never a live presentation cell. */
|
|
109
|
+
export declare function createDiagnosticLocalScope(scopeKey: string): Scope;
|
|
108
110
|
export declare function createDeclaredSignalCell<T>(owner: Scope, key: string, initial: T, preferInitial?: boolean): WritableSignal<T>;
|
|
109
111
|
export declare function createDerivedCellWith<T>(owner: Scope, key: string, compute: DerivedCompute<T>, options: DerivedOptions | undefined, Binding: DerivedBindingFactory<T>): DerivedSignal<T>;
|
|
110
112
|
export declare function createResourceCellWith<T>(owner: Scope, key: string, describe: () => QueryRequest<T> | typeof skip, initialize: typeof initializeResource, unique?: boolean): Resource<T>;
|
package/dist/signals/engine.js
CHANGED
|
@@ -30,6 +30,8 @@ import {
|
|
|
30
30
|
beginNativeWriteGuard,
|
|
31
31
|
endNativeWriteGuard,
|
|
32
32
|
getNativeAdoptionResolver,
|
|
33
|
+
getNativeReadObserver,
|
|
34
|
+
isNativeWriteGuarded,
|
|
33
35
|
registerNativeBatchHooks,
|
|
34
36
|
reportNativeRead
|
|
35
37
|
} from "./read-protocol.js";
|
|
@@ -99,6 +101,7 @@ function decodeSeed(scopeKey, seed) {
|
|
|
99
101
|
}
|
|
100
102
|
return entries;
|
|
101
103
|
}
|
|
104
|
+
const DIAGNOSTIC_LOCAL_SCOPES = /* @__PURE__ */ new WeakSet();
|
|
102
105
|
class ScopeImpl {
|
|
103
106
|
constructor(key, options, seedable = true) {
|
|
104
107
|
this.key = key;
|
|
@@ -585,7 +588,8 @@ class ScopeImpl {
|
|
|
585
588
|
}
|
|
586
589
|
dispose() {
|
|
587
590
|
if (this.disposed) return;
|
|
588
|
-
|
|
591
|
+
if (process.env.NODE_ENV === "production" || !DIAGNOSTIC_LOCAL_SCOPES.has(this))
|
|
592
|
+
assertWritable();
|
|
589
593
|
signalBatch(() => {
|
|
590
594
|
this.disposed = true;
|
|
591
595
|
this.lifetime++;
|
|
@@ -728,6 +732,13 @@ function createScope(options) {
|
|
|
728
732
|
function createLocalScope(scopeKey) {
|
|
729
733
|
return new ScopeImpl(scopeKey, { scopeKey }, false);
|
|
730
734
|
}
|
|
735
|
+
function createDiagnosticLocalScope(scopeKey) {
|
|
736
|
+
if (process.env.NODE_ENV === "production" || !isNativeWriteGuarded() || getNativeReadObserver() !== null)
|
|
737
|
+
throw new SignalFrameError("Diagnostic local scopes require an isolated historical read.");
|
|
738
|
+
const scope = new ScopeImpl(scopeKey, { scopeKey }, false);
|
|
739
|
+
DIAGNOSTIC_LOCAL_SCOPES.add(scope);
|
|
740
|
+
return scope;
|
|
741
|
+
}
|
|
731
742
|
function createDeclaredSignalCell(owner, key, initial, preferInitial = false) {
|
|
732
743
|
if (!(owner instanceof ScopeImpl)) throw new TypeError("A direct signal needs an Octane scope.");
|
|
733
744
|
return owner.createSignalDeclaration(key, initial, preferInitial);
|
|
@@ -769,6 +780,7 @@ export {
|
|
|
769
780
|
bindScopeStreamedSelection,
|
|
770
781
|
createDeclaredSignalCell,
|
|
771
782
|
createDerivedCellWith,
|
|
783
|
+
createDiagnosticLocalScope,
|
|
772
784
|
createLocalScope,
|
|
773
785
|
createResourceCellWith,
|
|
774
786
|
createScope,
|
package/dist/version.js
CHANGED