tav-media
Version:
Cross platform media editing framework
203 lines (202 loc) • 6.86 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/* eslint-disable prefer-rest-params */
import { tav } from '../tav';
export class TAVObject {
constructor(id = uuid()) {
this.prepared = false;
this.type = 'TAVObject';
this.nativeInvalidated = false;
this.id = id;
}
static parse(source) {
const it = parseTAVObject(source, this.classes, this.instances);
return it;
}
static declareType(name, class_) {
this.classes[name] = class_;
}
static getType(name) {
return this.classes[name];
}
prepare() {
return __awaiter(this, void 0, void 0, function* () {
yield this.doPrepare();
this.prepared = true;
});
}
release() { }
doPrepare() {
return __awaiter(this, void 0, void 0, function* () { });
}
invalidated() {
this.nativeInvalidated = true;
}
}
TAVObject.classes = {};
TAVObject.instances = {};
export function isTAVObject(source, classes) {
if (!source || typeof source !== 'object') {
return false;
}
if ('id' in source && Object.keys(source).length === 1) {
return true;
}
if ('type' in source) {
if (source.type in classes) {
return true;
}
console.error(`[ isTAVObject ] type not declared: ${source.type}`);
return false;
}
return false;
}
export class ObjectPlaceholder extends TAVObject {
constructor() {
super(...arguments);
this.refs = [];
}
resolve(realValue) {
this.refs.forEach((ref) => {
// eslint-disable-next-line no-param-reassign
ref.target[ref.prop] = realValue;
});
this.refs.length = 0;
}
}
export function parseTAVObject(source, classes, instances) {
if (!isTAVObject(source, classes))
return undefined;
if (source.id && Object.keys(source).length === 1) {
if (instances[source.id]) {
return instances[source.id];
}
const placeholder = new ObjectPlaceholder(source.id);
// eslint-disable-next-line no-param-reassign
instances[source.id] = placeholder;
return placeholder;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
const TargetClass = classes[source.type];
// tav object 被多次引用的时,可能被多次 parse 的情况
const existingInstance = instances[source.id];
if (existingInstance instanceof TargetClass) {
return existingInstance;
}
const target = new TargetClass();
target.id = source.id || target.id;
// 解决对象初始化之前的引用
const existing = instances[target.id];
if (existing) {
if (existing instanceof ObjectPlaceholder) {
existing.resolve(target);
}
else {
throw new Error(`[ Parse error ] id 重复: ${JSON.stringify(source)}`);
}
}
// eslint-disable-next-line no-param-reassign
instances[target.id] = target;
assignProperties(source, target, classes, instances);
return target;
}
function assignProperty(source, context, key, classes, instances) {
var _a;
const val = source[key];
if (typeof val !== 'object' && typeof val !== 'function') {
context[key] = val;
return;
}
if (val instanceof Array) {
context[key] = (_a = context[key]) !== null && _a !== void 0 ? _a : [];
val.forEach((_, index) => {
assignProperty(val, context[key], index, classes, instances);
});
return;
}
if (isTAVObject(val, classes)) {
const tavObject = parseTAVObject(val, classes, instances);
if (tavObject instanceof ObjectPlaceholder) {
tavObject.refs.push({ target: context, prop: key });
}
context[key] = tavObject;
return;
}
context[key] = {};
assignProperties(val, context[key], classes, instances);
}
function assignProperties(source, context, classes, instances) {
const keys = Object.keys(source);
keys.forEach((key) => {
assignProperty(source, context, key, classes, instances);
});
}
export function uuid(len = 16) {
const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
const uuid = [];
let i;
const localRadix = chars.length;
for (i = 0; i < len; i++)
uuid[i] = chars[0 | Math.random() * localRadix];
return uuid.join('');
}
export function updateNative(_target, name, descriptor) {
const func = descriptor.set;
// eslint-disable-next-line no-param-reassign
descriptor.set = function (val) {
if (this[name] !== val) {
this.invalidated();
;
}
return func.apply(this, [val]);
};
}
export function updateNativeIfEffect(_target, name, descriptor) {
const func = descriptor.value;
// eslint-disable-next-line no-param-reassign
descriptor.value = function () {
this.invalidated();
;
return func.apply(this, arguments);
};
}
export function allowCallNativeAnytime(_target, name, descriptor) {
['value', 'set', 'get'].forEach((method) => {
const func = descriptor[method];
if (!func)
return;
// eslint-disable-next-line no-param-reassign
descriptor[method] = function () {
if (tav.Asyncify.currData !== null) {
const { currData } = tav.Asyncify;
tav.Asyncify.currData = null;
const ret = func.apply(this, arguments);
tav.Asyncify.currData = currData;
return ret;
}
return func.apply(this, arguments);
};
});
}
export function updateNativeOrMakeInvalidate(_target, name, descriptor) {
['value', 'set', 'get'].forEach((method) => {
const func = descriptor[method];
if (!func)
return;
// eslint-disable-next-line no-param-reassign
descriptor[method] = function () {
if (!this._nativeObject) {
this.invalidated();
return;
}
return func.apply(this, arguments);
};
});
}