@v4fire/client
Version:
V4Fire client core library
264 lines (208 loc) • 5.26 kB
text/typescript
/*!
* V4Fire Client Core
* https://github.com/V4Fire/Client
*
* Released under the MIT license
* https://github.com/V4Fire/Client/blob/master/LICENSE
*/
import { metaPointers, PARENT } from 'core/component/const';
import type { ComponentMeta, StrictModDeclVal } from 'core/component/interface';
/**
* Inherits the specified meta object from another meta object.
* The function modifies the original object and returns it.
*
* @param meta
* @param parentMeta
*/
export function inheritMeta(
meta: ComponentMeta,
parentMeta: ComponentMeta
): ComponentMeta {
const
metaPointer = metaPointers[meta.componentName];
const {
params: pParams,
props: pProps,
mods: pMods,
fields: pFields,
tiedFields: pTiedFields,
computedFields: pComputedFields,
systemFields: pSystemFields,
accessors: pAccessors,
methods: pMethods,
watchDependencies: pWatchDependencies
} = parentMeta;
// Component parameters inheritance
meta.params = {
...pParams,
...meta.params,
name: meta.params.name,
model: (meta.params.model || pParams.model) && {...pParams.model, ...meta.params.model},
deprecatedProps: {...pParams.deprecatedProps, ...meta.params.deprecatedProps}
};
// Watcher dependencies inheritance
if (meta.watchDependencies.size > 0) {
for (let o = pWatchDependencies.entries(), el = o.next(); !el.done; el = o.next()) {
const [key, pVal] = el.value;
meta.watchDependencies.set(key, (meta.watchDependencies.get(key) ?? []).concat(pVal));
}
} else {
meta.watchDependencies = new Map(pWatchDependencies.entries());
}
// Props/fields inheritance
{
const list = [
[meta.props, pProps],
[meta.fields, pFields],
[meta.systemFields, pSystemFields]
];
for (let i = 0; i < list.length; i++) {
const
[o, parentObj] = list[i];
for (let keys = Object.keys(parentObj), i = 0; i < keys.length; i++) {
const
key = keys[i],
parent = parentObj[key];
if (!parent) {
continue;
}
if (!metaPointer || !metaPointer[key]) {
o[key] = parent;
continue;
}
let
after,
watchers;
if (parent.watchers) {
for (let w = parent.watchers.values(), el = w.next(); !el.done; el = w.next()) {
const val = el.value;
watchers ??= new Map();
watchers.set(val.handler, {...el.value});
}
}
if ('after' in parent && parent.after) {
for (let a = parent.after.values(), el = a.next(); !el.done; el = a.next()) {
after ??= new Set();
after.add(el.value);
}
}
o[key] = {...parent, after, watchers};
}
}
}
// Tied fields inheritance
Object.assign(meta.tiedFields, pTiedFields);
// Accessors inheritance
{
const list = [
[meta.computedFields, pComputedFields],
[meta.accessors, pAccessors]
];
for (let i = 0; i < list.length; i++) {
const
[o, parentObj] = list[i];
for (let keys = Object.keys(parentObj), i = 0; i < keys.length; i++) {
const key = keys[i];
o[key] = {...parentObj[key]!};
}
}
}
// Methods inheritance
for (let o = meta.methods, keys = Object.keys(pMethods), i = 0; i < keys.length; i++) {
const
key = keys[i],
parent = pMethods[key];
if (!parent) {
continue;
}
if (!metaPointer || !metaPointer[key]) {
o[key] = {...parent};
continue;
}
const
watchers = {},
hooks = {};
if (parent.watchers) {
const
o = parent.watchers,
w = Object.keys(o);
for (let i = 0; i < w.length; i++) {
const key = w[i];
watchers[key] = {...o[key]};
}
}
if (parent.hooks) {
const
o = parent.hooks,
w = Object.keys(o);
for (let i = 0; i < w.length; i++) {
const
key = w[i],
el = o[key];
hooks[key] = {
...el,
after: Object.size(el.after) > 0 ? new Set(el.after) : undefined
};
}
}
o[key] = {...parent, watchers, hooks};
}
// Modifiers inheritance
for (let o = meta.mods, keys = Object.keys(pMods), i = 0; i < keys.length; i++) {
const
key = keys[i],
current = o[key],
parent = (pMods[key] ?? []).slice();
if (current) {
const
values = Object.createDict<StrictModDeclVal>();
for (let o = current.slice(), i = 0; i < o.length; i++) {
const
el = o[i];
if (el !== PARENT) {
if (Object.isArray(el) || !(<string>el in values)) {
values[String(el)] = <StrictModDeclVal>el;
}
continue;
}
let
hasDefault = false;
for (let i = 0; i < o.length; i++) {
const
el = o[i];
if (Object.isArray(el)) {
hasDefault = true;
break;
}
}
let
parentDef = !hasDefault;
for (let i = 0; i < parent.length; i++) {
const
el = parent[i];
if (!(<string>el in values)) {
values[String(el)] = <StrictModDeclVal>el;
}
if (!parentDef && Object.isArray(el)) {
parent[i] = el[0];
parentDef = true;
}
}
current.splice(i, 1, ...parent);
}
const
valuesList = <StrictModDeclVal[]>[];
for (let keys = Object.keys(values), i = 0; i < keys.length; i++) {
const
el = values[keys[i]];
if (el !== undefined) {
valuesList.push(el);
}
}
o[key] = valuesList;
} else if (!(key in o)) {
o[key] = parent;
}
}
return meta;
}