@archie/devtools 0.0.23 → 0.0.25
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/inspector.standalone.js +215 -0
- package/package.json +1 -1
|
@@ -274,6 +274,185 @@
|
|
|
274
274
|
return null
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
+
// ── ARCH-883 F2 — usage chain + instance identity ───────────────────
|
|
278
|
+
// Vanilla twins of collectEditorMetaChain (fiber-bridge.ts) and
|
|
279
|
+
// resolveInstanceIdentity (instance-identity.ts). Those files carry the
|
|
280
|
+
// full rationale; keep the three in step.
|
|
281
|
+
var MAX_META_CHAIN = 24
|
|
282
|
+
|
|
283
|
+
// Every __editorMeta on the fiber return chain, innermost first. The host
|
|
284
|
+
// needs the FULL metas (staticProps/propBindings/propOwner), not the
|
|
285
|
+
// narrowed inspectorSource shape: routing a kit-internal node means
|
|
286
|
+
// finding the USAGE above it and reading the prop value AT that usage.
|
|
287
|
+
function collectEditorMetaChain(el) {
|
|
288
|
+
var chain = []
|
|
289
|
+
var fiber = getFiberFromElement(el)
|
|
290
|
+
while (fiber && chain.length < MAX_META_CHAIN) {
|
|
291
|
+
if (fiber.memoizedProps && fiber.memoizedProps.__editorMeta) {
|
|
292
|
+
var meta = resolveEditorMetaValue(fiber.memoizedProps.__editorMeta)
|
|
293
|
+
if (meta) chain.push(meta)
|
|
294
|
+
}
|
|
295
|
+
fiber = fiber["return"]
|
|
296
|
+
}
|
|
297
|
+
return chain
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
var MAX_ROW_ROOT_DEPTH = 12
|
|
301
|
+
var MAX_KEY_WALK = 40
|
|
302
|
+
|
|
303
|
+
// The fiber that OWNS the nearest __editorMeta for `el`. Vanilla twin of
|
|
304
|
+
// getEditorMetaOwnerFiber (fiber-bridge.ts).
|
|
305
|
+
function getEditorMetaOwnerFiberFromElement(el) {
|
|
306
|
+
var fiber = getFiberFromElement(el)
|
|
307
|
+
while (fiber) {
|
|
308
|
+
if (fiber.memoizedProps && fiber.memoizedProps.__editorMeta) {
|
|
309
|
+
return fiber
|
|
310
|
+
}
|
|
311
|
+
fiber = fiber["return"]
|
|
312
|
+
}
|
|
313
|
+
return null
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// The SINGLE host element `owner` renders, or null when it renders zero
|
|
317
|
+
// or several, or crosses a HostPortal (tag 4). Vanilla twin of
|
|
318
|
+
// getSingleHostElement (fiber-bridge.ts) — conservative by design.
|
|
319
|
+
function getSingleHostElementFromFiber(owner) {
|
|
320
|
+
var hosts = []
|
|
321
|
+
var stack = owner && owner.child ? [owner.child] : []
|
|
322
|
+
while (stack.length > 0) {
|
|
323
|
+
var fiber = stack.pop()
|
|
324
|
+
if (!fiber) continue
|
|
325
|
+
if (fiber.tag === 4) return null
|
|
326
|
+
if (
|
|
327
|
+
typeof fiber.type === "string" &&
|
|
328
|
+
fiber.stateNode &&
|
|
329
|
+
fiber.stateNode.nodeType === 1
|
|
330
|
+
) {
|
|
331
|
+
hosts.push(fiber.stateNode)
|
|
332
|
+
if (hosts.length > 1) return null
|
|
333
|
+
} else if (fiber.child) {
|
|
334
|
+
stack.push(fiber.child)
|
|
335
|
+
}
|
|
336
|
+
if (fiber.sibling) stack.push(fiber.sibling)
|
|
337
|
+
}
|
|
338
|
+
return hosts.length === 1 ? hosts[0] : null
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Vanilla twin of projectUsageMeta (useElementScanner.ts): the usage meta
|
|
342
|
+
// when `el` is the SINGLE host root a component usage renders and that
|
|
343
|
+
// component destructured its props, so the host fiber carries no meta.
|
|
344
|
+
function projectUsageMetaFromElement(el) {
|
|
345
|
+
if (getDirectEditorMetaFromElement(el)) return null
|
|
346
|
+
var owner = getEditorMetaOwnerFiberFromElement(el)
|
|
347
|
+
if (!owner) return null
|
|
348
|
+
if (getSingleHostElementFromFiber(owner) !== el) return null
|
|
349
|
+
return resolveEditorMetaValue(owner.memoizedProps.__editorMeta)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// The nodeId this element carries AS ITS OWN — direct fiber meta, or the
|
|
353
|
+
// single-host projection. NEVER an inherited ancestor nodeId: walking the
|
|
354
|
+
// fiber chain here made every UNSTAMPED subtree (any two siblings
|
|
355
|
+
// rendered by a component the plugin never transformed — anything from
|
|
356
|
+
// node_modules, and here SVG internals too, since this twin accepts any
|
|
357
|
+
// element node) look like a repeated collection. Meanwhile a
|
|
358
|
+
// direct-meta-ONLY rule would make every kit component that destructures
|
|
359
|
+
// its props look like a singleton — which is the fail-OPEN mistake, and
|
|
360
|
+
// would write a literal into a mapped usage, changing every row.
|
|
361
|
+
// See instance-identity.ts for the full rationale.
|
|
362
|
+
function ownMetaNodeId(el) {
|
|
363
|
+
if (!el || el.nodeType !== 1) return null
|
|
364
|
+
var direct = getDirectEditorMetaFromElement(el)
|
|
365
|
+
if (direct && direct.nodeId) return direct.nodeId
|
|
366
|
+
var projected = projectUsageMetaFromElement(el)
|
|
367
|
+
return projected && projected.nodeId ? projected.nodeId : null
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// The repeated-row boundary above `el`, or null. INNERMOST repetition
|
|
371
|
+
// wins (a tag inside a card inside a list is identified by the tag's key).
|
|
372
|
+
function findCollectionWindow(el) {
|
|
373
|
+
var node = el
|
|
374
|
+
for (var depth = 0; depth < MAX_ROW_ROOT_DEPTH; depth++) {
|
|
375
|
+
var parent = node.parentElement
|
|
376
|
+
if (!parent) return null
|
|
377
|
+
|
|
378
|
+
var nodeId = ownMetaNodeId(node)
|
|
379
|
+
if (nodeId !== null) {
|
|
380
|
+
var twins = []
|
|
381
|
+
for (var i = 0; i < parent.children.length; i++) {
|
|
382
|
+
var child = parent.children[i]
|
|
383
|
+
if (ownMetaNodeId(child) === nodeId) twins.push(child)
|
|
384
|
+
}
|
|
385
|
+
if (twins.length >= 2) {
|
|
386
|
+
return {
|
|
387
|
+
rowRoot: node,
|
|
388
|
+
container: parent,
|
|
389
|
+
ordinal: twins.indexOf(node),
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
node = parent
|
|
395
|
+
}
|
|
396
|
+
return null
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Nearest React key BETWEEN the row root and the collection container.
|
|
400
|
+
// Stopping at the container is the point: a keyed ancestor above it
|
|
401
|
+
// identifies a page, not a row.
|
|
402
|
+
function keyWithinWindow(rowRoot, container) {
|
|
403
|
+
var fiber = getFiberFromElement(rowRoot)
|
|
404
|
+
for (var steps = 0; fiber && steps < MAX_KEY_WALK; steps++) {
|
|
405
|
+
if (fiber.stateNode === container) return null
|
|
406
|
+
var key = fiber.key
|
|
407
|
+
if (typeof key === "string" && key.length > 0) return key
|
|
408
|
+
if (typeof key === "number") return String(key)
|
|
409
|
+
fiber = fiber["return"]
|
|
410
|
+
}
|
|
411
|
+
return null
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// WHICH instance of a possibly-repeated node this element is.
|
|
415
|
+
// `scanOrdinal` is telemetry/UI only — the host must REJECT an intent
|
|
416
|
+
// with inCollection && fiberKey === null, never fall back to it.
|
|
417
|
+
function resolveInstanceIdentity(el) {
|
|
418
|
+
var win = findCollectionWindow(el)
|
|
419
|
+
if (!win) return { fiberKey: null, scanOrdinal: 0, inCollection: false }
|
|
420
|
+
return {
|
|
421
|
+
fiberKey: keyWithinWindow(win.rowRoot, win.container),
|
|
422
|
+
scanOrdinal: win.ordinal,
|
|
423
|
+
inCollection: true,
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// ARCH-906 — the DURABLE `data-agent-id` anchors on the ANCESTOR chain,
|
|
428
|
+
// innermost first. This is a DOM-attribute walk, not a fiber walk (no twin
|
|
429
|
+
// in fiber-bridge.ts to mirror): it reads the semantic anchors the render
|
|
430
|
+
// stamps (`row:<id>`, `data:<Entity>`, `screen:<slug>`, `job:<id>`) and
|
|
431
|
+
// forwards them so the host can resolve a slice DATA cell.
|
|
432
|
+
//
|
|
433
|
+
// WHY THE ANCESTOR CHAIN, and why it is not `editorInstance`. Clicking a
|
|
434
|
+
// table cell resolves the INNERMOST collection — the `<td key={c.key}>` map
|
|
435
|
+
// — so `editorInstance.fiberKey` already carries the FIELD. The ROW it
|
|
436
|
+
// belongs to lives one level up on `<tr data-agent-id="row:<id>">`, and the
|
|
437
|
+
// ENTITY on a container above that (`data-agent-id="data:<Entity>"`).
|
|
438
|
+
// Neither can be the innermost collection key, so the host cannot recover
|
|
439
|
+
// them from `editorInstance` — it needs the ancestor anchors verbatim.
|
|
440
|
+
// Strict ancestors only (the selected node's own anchor is already in
|
|
441
|
+
// `attributes`); the host picks the nearest `row:`/`data:` by namespace.
|
|
442
|
+
var MAX_ANCHOR_CHAIN = 24
|
|
443
|
+
function collectAncestorAnchors(el) {
|
|
444
|
+
var anchors = []
|
|
445
|
+
var node = el && el.parentElement ? el.parentElement : null
|
|
446
|
+
for (var depth = 0; node && depth < MAX_ANCHOR_CHAIN; depth++) {
|
|
447
|
+
if (node.nodeType === 1 && typeof node.getAttribute === "function") {
|
|
448
|
+
var id = node.getAttribute("data-agent-id")
|
|
449
|
+
if (typeof id === "string" && id !== "") anchors.push(id)
|
|
450
|
+
}
|
|
451
|
+
node = node.parentElement
|
|
452
|
+
}
|
|
453
|
+
return anchors
|
|
454
|
+
}
|
|
455
|
+
|
|
277
456
|
if (window._inspectorSharedTargetObserver) {
|
|
278
457
|
try {
|
|
279
458
|
window._inspectorSharedTargetObserver.disconnect()
|
|
@@ -2061,6 +2240,42 @@
|
|
|
2061
2240
|
// this script's version. The slot string is opaque here; validating it
|
|
2062
2241
|
// against kit-runtime's `slot-vocabulary` is the host's job.
|
|
2063
2242
|
editorMeta: editorMeta ? editorMeta.meta : null,
|
|
2243
|
+
// ARCH-883 F2 — the two things the host cannot derive from
|
|
2244
|
+
// `editorMeta` alone (SDD §2.9):
|
|
2245
|
+
//
|
|
2246
|
+
// editorMetaChain: routing a kit-internal node needs the USAGE
|
|
2247
|
+
// (`<Kit.AuthFrame headline="…"/>` in screens/<slug>.jsx), which
|
|
2248
|
+
// is NOT the nearest meta — the nearest meta is the <h1> inside
|
|
2249
|
+
// AuthFrame's own template. The host locates the usage by
|
|
2250
|
+
// matching `propOwner` against a chain entry's componentName and
|
|
2251
|
+
// applies the usage-value law to that entry's staticProps. Both
|
|
2252
|
+
// fields live only on the full meta.
|
|
2253
|
+
//
|
|
2254
|
+
// editorInstance: WHICH row of a repeated node was clicked. The
|
|
2255
|
+
// nodeId is a source position and collides across instances; the
|
|
2256
|
+
// only identity that survives an insert above the edited row is
|
|
2257
|
+
// React's `key`, which exists on the fiber and nowhere else.
|
|
2258
|
+
//
|
|
2259
|
+
// Both are plain data, so an already-published copy of this script
|
|
2260
|
+
// forwards them through structured clone unchanged.
|
|
2261
|
+
//
|
|
2262
|
+
// The chain starts at the element the meta was FOUND on (the same
|
|
2263
|
+
// element `editorMeta` above describes) — a clicked node with no
|
|
2264
|
+
// fiber of its own would otherwise yield an empty chain while
|
|
2265
|
+
// reporting a meta resolved from its parent. The instance walk starts
|
|
2266
|
+
// at the CLICKED element, so an inner collection wins over an outer
|
|
2267
|
+
// one (a tag inside a card inside a list).
|
|
2268
|
+
editorMetaChain: collectEditorMetaChain(
|
|
2269
|
+
editorMeta ? editorMeta.element : element
|
|
2270
|
+
),
|
|
2271
|
+
editorInstance: resolveInstanceIdentity(element),
|
|
2272
|
+
// ARCH-906 — the ancestor `data-agent-id` chain (innermost first). A
|
|
2273
|
+
// slice DATA cell needs the ROW id (`row:<id>` on the `<tr>`) and the
|
|
2274
|
+
// ENTITY (`data:<Entity>` above it), neither of which is the innermost
|
|
2275
|
+
// collection key `editorInstance` carries. Plain string data, so an
|
|
2276
|
+
// already-published copy of this script forwards it unchanged through
|
|
2277
|
+
// structured clone; a host that does not read it is unaffected.
|
|
2278
|
+
ancestorAnchors: collectAncestorAnchors(element),
|
|
2064
2279
|
computedStyles: {
|
|
2065
2280
|
display: computed.display,
|
|
2066
2281
|
position: computed.position,
|