/** * 元素数据的捕获来源与内置 schema 校验缓存。 * 缓存是性能优化,只能用于框架掌控的不可变记录/纯校验器;自定义校验器每次仍调用。 */ import type {ElementRecord,ComponentDefinition} from './types.ts'; import {detachJsonData} from './json-data.ts'; // Provenance comes from detaching JSON data, never from an external freeze or // document envelope. This does not assert record validity or registry support. const owned=new WeakSet(); /** 已由本模块捕获的记录直接复用;外部记录重新按 JSON 语义复制冻结,再标记新记录身份。 * 此处不调用组件 schema;捕获成功与记录合法是两项独立事实。 */ export function detachElementData(record:ElementRecord):ElementRecord{ if(record&&typeof record==='object'&&owned.has(record))return record; const value=detachJsonData(record); if(value&&typeof value==='object')owned.add(value); return value; } /** 证明记录来自本模块捕获;不证明其 type、版本、结构或关联引用有效。 */ export const hasOwnedElementData=(record:ElementRecord)=>!!record&&typeof record==='object'&&owned.has(record); // Framework-owned validators depend only on detached immutable data. Custom // validators remain live, including their method receiver and external context. const builtinValidators=new WeakSet(),dataProofs=new WeakMap(); /** 标记框架内置、仅依赖输入的纯校验器;不要用它包装依赖外部可变状态的校验器。 * WeakSet 只记录这项声明,不能自动证明函数无副作用或不读取闭包状态。 */ export function builtinDataValidator(validate:T):T{builtinValidators.add(validate);return validate;} /** 检查组件 data,只有“owned 记录 + 内置 validator”组合才允许复用成功结果。 * 失败不缓存;更换 validator 后缓存也不命中;Reflect.apply 保留定义对象作为 this。 */ export function componentDataValid(record:ElementRecord,definition:ComponentDefinition):boolean{ // record 身份和具体 validator 函数同时匹配,才能跳过一次已成功的 schema 检查。 const validate=definition.validate,reusable=hasOwnedElementData(record)&&builtinValidators.has(validate); if(reusable&&dataProofs.get(record)===validate)return true; // 校验器抛错会直接传播给上层;这里只缓存正常返回且通过的结果,不吞错或缓存失败。 const valid=Reflect.apply(validate,definition,[record.data]); if(valid&&reusable)dataProofs.set(record,validate); return valid; }