taggedjs
Version:
tagged template reactive html
136 lines • 5.05 kB
JavaScript
import { getSupportInCycle } from '../getSupportInCycle.function.js';
import { deepCompareDepth } from '../hasSupportChanged.function.js';
import { isArray, isStaticTag } from '../../isInstance.js';
import { BasicTypes } from '../ValueTypes.enum.js';
import { setUseMemory } from '../../state/index.js';
import { safeRenderSupport } from './safeRenderSupport.function.js';
export function castProps(props, newSupport, depth) {
return props.map(function eachCastProp(prop) {
return alterProp(prop, newSupport.ownerSupport, newSupport, depth);
});
}
/* Used to rewrite props that are functions. When they are called it should cause parent rendering */
function alterProp(prop, ownerSupport, newSupport, depth) {
if (isStaticTag(prop) || !prop) {
return prop;
}
if (!ownerSupport) {
return prop; // no one above me
}
return checkProp(prop, ownerSupport, newSupport, depth);
}
export function checkProp(value, ownerSupport, newSupport, depth, owner) {
if (!value) {
return value;
}
if (value.tagJsType) {
return value;
}
if (typeof (value) === BasicTypes.function) {
if (depth <= 1) {
// only wrap function at depth 0 and 1
return getPropWrap(value, owner, ownerSupport);
}
return value;
}
if (depth === deepCompareDepth) {
return value;
}
const skip = isSkipPropValue(value);
if (skip) {
return value; // no children to crawl through
}
if (isArray(value)) {
return checkArrayProp(value, newSupport, ownerSupport, depth);
}
return checkObjectProp(value, newSupport, ownerSupport, depth);
}
function checkArrayProp(value, newSupport, ownerSupport, depth) {
for (let index = value.length - 1; index >= 0; --index) {
const subValue = value[index];
value[index] = checkProp(subValue, ownerSupport, newSupport, depth + 1, value);
if (typeof (subValue) === BasicTypes.function) {
if (subValue.mem) {
continue;
}
afterCheckProp(depth + 1, index, subValue, value, newSupport);
}
}
return value;
}
function checkObjectProp(value, newSupport, ownerSupport, depth) {
const keys = Object.keys(value);
for (const name of keys) {
const subValue = value[name];
const result = checkProp(subValue, ownerSupport, newSupport, depth + 1, value);
const newSubValue = value[name];
if (newSubValue === result) {
continue;
}
const getset = Object.getOwnPropertyDescriptor(value, name);
const hasSetter = getset?.get || getset?.set;
if (hasSetter) {
continue;
}
value[name] = result;
if (typeof (result) === BasicTypes.function) {
if (subValue.mem) {
continue;
}
afterCheckProp(depth + 1, name, subValue, value, newSupport);
}
}
return value;
}
function afterCheckProp(depth, index, originalValue, newProp, newSupport) {
// restore object to have original function on destroy
if (depth > 0) {
const global = newSupport.context.global;
newProp[index].subscription = global.destroy$.toCallback(function alterCheckProcessor() {
newProp[index] = originalValue;
});
}
}
export function getPropWrap(value, owner, ownerSupport) {
const already = value.mem;
// already previously converted by a parent?
if (already) {
return value;
}
const wrap = function wrapRunner(...args) {
return callbackPropOwner(wrap.mem, owner, args, ownerSupport);
}; // what gets called can switch over parent state changes
wrap.original = value;
wrap.mem = value;
// copy data properties that maybe on source function
Object.assign(wrap, value);
return wrap;
}
/** Function shared by alterProps() and updateExistingTagComponent... TODO: May want to have to functions to reduce cycle checking? */
export function callbackPropOwner(toCall, // original function
owner, callWith, ownerSupport) {
const global = ownerSupport.context.global;
const newest = global?.newest || ownerSupport;
const supportInCycle = getSupportInCycle();
const noCycle = supportInCycle === undefined;
// actual function call to original method
const callbackResult = toCall.apply(owner, callWith);
const run = function propCallbackProcessor() {
const subject = newest.context;
const global = subject.global;
if (!global || subject.locked === true) {
return callbackResult; // currently in the middle of rendering
}
safeRenderSupport(newest);
return callbackResult;
};
if (noCycle) {
return run();
}
setUseMemory.tagClosed$.toCallback(run);
return callbackResult;
}
export function isSkipPropValue(value) {
return typeof (value) !== BasicTypes.object || !value || value.tagJsType;
}
//# sourceMappingURL=alterProp.function.js.map