Every reference to the Driver in internal/ is reworded the same way as in library/: the reason stays, the speaker and the quote go, an open decision reads "provisional, pending a product decision", and agent names and decision- sheet rows are dropped. Where a gate printed the word, its message now names the reviewer or the ruling instead. Three spots were code, not comments, and changed with their callers: - the element census's allowlist field `driver` is now `ruling`, in the gate and both presets (same validation: match, ruling, date and card required); - check:i18n-never-translated's DRIVER-GATED marker is DECISION-PENDING, in the entries and in the regex that counts them (its output is otherwise byte-identical); - the package.json description of the census says "ruling". public-hygiene-check keeps its two patterns for the word: they are what keep it out of the served folder.
102 lines
5.3 KiB
JavaScript
102 lines
5.3 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* check-provide-shadowing — a nested custom element keeps its OWN pinia, i18n and profileModules, and
|
|
* says so deliberately instead of tripping Vue's overwrite warning 24 times.
|
|
*
|
|
* THE DEFECT (seen in a live console, 2026-09-28): 24 Vue warnings —
|
|
* 'App already provides property with key "profileModules" / "appI18n" / "Symbol(pinia)" inherited
|
|
* from its parent element. It will be overwritten with the new value.'
|
|
* eight of each, from a composite mounting child custom elements.
|
|
*
|
|
* ★ THE OVERWRITE IS THE POINT, WHICH IS WHY SILENCING IT WOULD HAVE BEEN WRONG AND FIXING IT BY NOT
|
|
* PROVIDING WOULD HAVE BEEN WORSE. `profileModules` is the plugin's own .vue glob — a child rendering
|
|
* its parent's components is a different bug; pinia is per-instance so two embeds never bleed state;
|
|
* and the i18n instance is the one ProfileLoader drives from THIS element's profile-config, which is
|
|
* the whole of the permanently-English fix landed the same day. Inheriting any of the three would be
|
|
* the regression.
|
|
*
|
|
* So this asserts BOTH halves: the child still ends up with its OWN value (the fix is not undone), and
|
|
* the inherited chain is left intact afterwards (the parent's OTHER values still resolve).
|
|
*
|
|
* Exercised against the REAL exported helpers, not a copy — a copied helper would pass while the
|
|
* shipped one rotted. Exit 0 pass · 1 fail.
|
|
*/
|
|
import { resolve, dirname } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
|
const { provideOwn, withoutInheritedProvides } =
|
|
await import(resolve(ROOT, 'library/elements/provide-own.js'))
|
|
|
|
const fails = []
|
|
const ok = (what, cond, d = '') => { if (!cond) fails.push(`${what}${d ? `\n ${d}` : ''}`) }
|
|
|
|
// A Vue-shaped app: provides inherits from the parent ELEMENT's provides, and app.provide() warns
|
|
// exactly as runtime-core does when the key is already reachable.
|
|
const makeApp = (parentProvides = {}) => {
|
|
const provides = Object.create(parentProvides)
|
|
const warnings = []
|
|
return {
|
|
warnings,
|
|
_context: { provides },
|
|
provide(key, value) {
|
|
if (key in provides) warnings.push(String(key))
|
|
provides[key] = value
|
|
},
|
|
}
|
|
}
|
|
|
|
// ── provideOwn: an inherited key is shadowed WITHOUT a warning ───────────────────────────────────
|
|
{
|
|
const parent = { appI18n: 'PARENT-I18N', somethingElse: 'keep-me' }
|
|
const app = makeApp(parent)
|
|
provideOwn(app, 'appI18n', 'MY-I18N')
|
|
ok('the child ends up with its OWN i18n', app._context.provides.appI18n === 'MY-I18N')
|
|
ok('...as an OWN property, not the parent\'s', Object.hasOwn(app._context.provides, 'appI18n'))
|
|
ok('...without a warning, because the shadow is deliberate', app.warnings.length === 0,
|
|
`warned about: ${app.warnings.join(', ')}`)
|
|
ok('the parent\'s OTHER values still resolve', app._context.provides.somethingElse === 'keep-me')
|
|
ok('and the parent is NOT mutated', parent.appI18n === 'PARENT-I18N')
|
|
}
|
|
// ── provideOwn: an ABSENT key takes the ordinary public path ─────────────────────────────────────
|
|
{
|
|
const app = makeApp({})
|
|
provideOwn(app, 'profileModules', { a: 1 })
|
|
ok('a key nobody provided is set through the public API', app._context.provides.profileModules.a === 1)
|
|
ok('...and still does not warn, because there was nothing to overwrite', app.warnings.length === 0)
|
|
}
|
|
// ── withoutInheritedProvides: for a key we cannot name (pinia's symbol) ──────────────────────────
|
|
{
|
|
const SYM = Symbol('pinia')
|
|
const parent = { [SYM]: 'PARENT-PINIA', other: 'x' }
|
|
const app = makeApp(parent)
|
|
withoutInheritedProvides(app, () => app.provide(SYM, 'MY-PINIA'))
|
|
ok('the child ends up with its own pinia', app._context.provides[SYM] === 'MY-PINIA')
|
|
ok('...with no warning', app.warnings.length === 0, `warned about: ${app.warnings.map(String).join(', ')}`)
|
|
ok('★ the inherited chain is RESTORED — the parent\'s other values resolve again',
|
|
app._context.provides.other === 'x')
|
|
ok('the parent is not mutated', parent[SYM] === 'PARENT-PINIA')
|
|
}
|
|
// ── and it restores the chain even when the callback throws ──────────────────────────────────────
|
|
{
|
|
const parent = { other: 'x' }
|
|
const app = makeApp(parent)
|
|
try { withoutInheritedProvides(app, () => { throw new Error('install blew up') }) } catch { /* expected */ }
|
|
ok('a throwing install still leaves the element able to see its parent',
|
|
app._context.provides.other === 'x')
|
|
}
|
|
// ── the control: the naive call MUST warn, or these assertions prove nothing ─────────────────────
|
|
{
|
|
const app = makeApp({ appI18n: 'PARENT' })
|
|
app.provide('appI18n', 'MINE')
|
|
ok('a plain app.provide() over an inherited key DOES warn (the behaviour being avoided)',
|
|
app.warnings.length === 1)
|
|
}
|
|
|
|
if (fails.length) {
|
|
console.error('PROVIDE-SHADOWING: FAIL')
|
|
for (const f of fails) console.error(` ✗ ${f}`)
|
|
process.exit(1)
|
|
}
|
|
console.log('PROVIDE-SHADOWING: PASS — a nested element keeps its own pinia, i18n and profileModules with no '
|
|
+ 'overwrite warning, the parent\'s other provides still resolve, and the chain is restored even if install throws.')
|