36 lines
2.3 KiB
TypeScript
36 lines
2.3 KiB
TypeScript
/**
|
|
* 元素数据的捕获来源与内置 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<object>();
|
|
/** 已由本模块捕获的记录直接复用;外部记录重新复制冻结,再标记新记录身份。 */
|
|
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<Function>(),dataProofs=new WeakMap<object,ComponentDefinition['validate']>();
|
|
/** 标记框架内置、仅依赖输入的纯校验器;不要用它包装依赖外部可变状态的校验器。 */
|
|
export function builtinDataValidator<T extends ComponentDefinition['validate']>(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;
|
|
}
|