##// END OF EJS Templates
corrected tear down logic handling in observables. Added support for observable query results
corrected tear down logic handling in observables. Added support for observable query results

File last commit:

r109:4a375b9c654a default
r110:1a190b3a757d v1.4.0 default
Show More
declare.ts
255 lines | 10.0 KiB | video/mp2t | TypeScriptLexer
cin
Converted to subproject djx, removed dojo-typings
r65 import declare = require("dojo/_base/declare");
import { each } from "@implab/core-amd/safe";
import { Constructor } from "@implab/core-amd/interfaces";
// declare const declare: any;
type DeclareConstructor<T> = dojo._base.DeclareConstructor<T>;
cin
Working on WatchForRendition
r107 export interface AbstractConstructor<T = object> {
cin
Converted to subproject djx, removed dojo-typings
r65 prototype: T;
}
cin
Working on WatchForRendition
r107 interface DjMockConstructor<T = object> {
new(...args: unknown[]): T;
cin
Converted to subproject djx, removed dojo-typings
r65 mock: boolean;
bases: AbstractConstructor[];
}
cin
Working on WatchForRendition
r107 export function djbase<T>(): DeclareConstructor<T>;
cin
Converted to subproject djx, removed dojo-typings
r65 export function djbase<T>(
cin
Working on WatchForRendition
r107 b0: AbstractConstructor<T>
cin
Converted to subproject djx, removed dojo-typings
r65 ): DeclareConstructor<T>;
export function djbase<T0, T1>(
b0: AbstractConstructor<T0>,
b1: AbstractConstructor<T1>
): DeclareConstructor<T0 & T1>;
export function djbase<T0, T1, T2>(
b0: AbstractConstructor<T0>,
b1: AbstractConstructor<T1>,
b2: AbstractConstructor<T2>
): DeclareConstructor<T0 & T1 & T2>;
export function djbase<T0, T1, T2, T3>(
b0: AbstractConstructor<T0>,
b1: AbstractConstructor<T1>,
b2: AbstractConstructor<T2>,
b3: AbstractConstructor<T3>
): DeclareConstructor<T0 & T1 & T2 & T3>;
export function djbase<T0, T1, T2, T3, T4>(
b0: AbstractConstructor<T0>,
b1: AbstractConstructor<T1>,
b2: AbstractConstructor<T2>,
b3: AbstractConstructor<T3>,
b4: AbstractConstructor<T4>
): DeclareConstructor<T0 & T1 & T2 & T3 & T4>;
export function djbase<T0, T1, T2, T3, T4, T5>(
b0: AbstractConstructor<T0>,
b1: AbstractConstructor<T1>,
b2: AbstractConstructor<T2>,
b3: AbstractConstructor<T3>,
b4: AbstractConstructor<T4>,
b5: AbstractConstructor<T5>
): DeclareConstructor<T0 & T1 & T2 & T3 & T4 & T5>;
export function djbase<T0, T1, T2, T3, T4, T5, T6>(
b0: AbstractConstructor<T0>,
b1: AbstractConstructor<T1>,
b2: AbstractConstructor<T2>,
b3: AbstractConstructor<T3>,
b4: AbstractConstructor<T4>,
b5: AbstractConstructor<T5>,
b6: AbstractConstructor<T6>
): DeclareConstructor<T0 & T1 & T2 & T3 & T4 & T5 & T6>;
export function djbase<T0, T1, T2, T3, T4, T5, T6, T7>(
b0: AbstractConstructor<T0>,
b1: AbstractConstructor<T1>,
b2: AbstractConstructor<T2>,
b3: AbstractConstructor<T3>,
b4: AbstractConstructor<T4>,
b5: AbstractConstructor<T5>,
b6: AbstractConstructor<T6>,
b7: AbstractConstructor<T7>
): DeclareConstructor<T0 & T1 & T2 & T3 & T4 & T5 & T6 & T7>;
/** Создает конструктор-заглушку из списка базовых классов, используется
* для объявления классов при помощи `dojo/_base/declare`.
*
* Создает пустой конструктор, с пустым стандартным прототипом, это нужно,
* поскольку в унаследованном классе конструктор обязательно должен вызвать
* `super(...)`, таким образом он вызовет пустую функцию.
*
* Созданный конструктор хранит в себе список базовых классов, который будет
* использован декоратором `djclass`, который вернет класс, объявленный при
* помощи `dojo/_base/declare`.
*
* @param bases список базовых классов, от которых требуется унаследовать
* новый класс.
*
*/
cin
Working on WatchForRendition
r107 export function djbase(...bases: AbstractConstructor[]): Constructor {
cin
Converted to subproject djx, removed dojo-typings
r65
const t = class {
static mock: boolean;
static bases: AbstractConstructor[];
};
t.mock = true;
t.bases = bases;
cin
Working on WatchForRendition
r107 return t as Constructor;
cin
Converted to subproject djx, removed dojo-typings
r65 }
cin
Working on WatchForRendition
r107 function isMockConstructor<T extends object>(v: AbstractConstructor<T>): v is DjMockConstructor<T> {
cin
Converted to subproject djx, removed dojo-typings
r65 return v && "mock" in v;
}
/** Создает класс при помощи `dojo/_base/declare`. Для этого исходный класс
* должен быть унаследован от `djbase(...)`.
*
* @param target Класс, который нужно объявить при помощи `dojo/_base/declare`
*/
export function djclass<T extends AbstractConstructor>(target: T): T {
// получаем базовый конструктор и его прототип
cin
Working on WatchForRendition
r107 const bp = target && !!target.prototype && Object.getPrototypeOf(target.prototype) as object;
cin
Converted to subproject djx, removed dojo-typings
r65 const bc = bp && bp.constructor;
// проверка того, что класс унаследован от специальной заглушки
if (isMockConstructor(bc)) {
cin
fixed tslint errors, added support for private methods to @on() decorator
r79 // bc.bases - базовый класс, объявленный при помощи dojo/_base/declare
cin
Working on WatchForRendition
r107 const cls = declare(bc.bases, target.prototype) as unknown as T;
cin
Converted to subproject djx, removed dojo-typings
r65
// bc - базовый класс, bc.prototype используется как super
// при вызове базовых методов. Нужно создать bc.prototype
// таким образом, чтобы он вызывал this.inherited().
cin
Working on WatchForRendition
r107 // создаем новый прототип, он не в цепочке прототипов у текущего
cin
Converted to subproject djx, removed dojo-typings
r65 // класса, но super.some_method будет использовать именно его.
// в этом объекте будут размещены прокси для переопределенных
// методов.
cin
Working on WatchForRendition
r107 const nbp = bc.prototype = Object.create(cls.prototype) as Record<string, unknown>;
nbp.constructor = bc;
cin
Converted to subproject djx, removed dojo-typings
r65
// proxy - фабрика для создания прокси-методов, которые внутри
// себя вызовут this.inherited с правильными параметрами.
cin
linting
r109 const proxy = (m: (...args: unknown[]) => unknown) => function (this: dojo._base.DeclareCreatedObject) {
const f = this.getInherited({ callee: m } as unknown as IArguments);
// eslint-disable-next-line prefer-rest-params
return f ? f.apply(this, arguments) as unknown : undefined;
cin
Converted to subproject djx, removed dojo-typings
r65
// так сделать можно только dojo 1.15+
// return this.inherited(m, arguments);
};
// у текущего класса прототип содержит методы, объявленные в этом
// классе и его конструктор. Нужно пройти по всем методам и
// создать для них прокси.
// При этом только те, методы, которые есть в базовых классах
// могут быть переопределены.
cin
Working on WatchForRendition
r107 each(target.prototype, (m: unknown, p: string) => {
cin
Converted to subproject djx, removed dojo-typings
r65 if (typeof m === "function" &&
p !== "constructor" &&
cin
linting
r109 Object.prototype.hasOwnProperty.call(target.prototype, p)
cin
Converted to subproject djx, removed dojo-typings
r65 ) {
cin
Working on WatchForRendition
r107 nbp[p] = proxy(m as (...args: unknown[]) => unknown);
cin
Converted to subproject djx, removed dojo-typings
r65 }
});
// TODO mixin static members
cin
Working on WatchForRendition
r107 return cls;
cin
Converted to subproject djx, removed dojo-typings
r65 } else {
cin
Working on WatchForRendition
r107 return target;
cin
Converted to subproject djx, removed dojo-typings
r65 }
}
function makeSetterName(prop: string) {
return [
"_set",
prop.replace(/^./, x => x.toUpperCase()),
"Attr"
].join("");
}
function makeGetterName(prop: string) {
return [
"_get",
prop.replace(/^./, x => x.toUpperCase()),
"Attr"
].join("");
}
interface NodeBindSpec {
node: string;
type: "attribute" | "innerText" | "textContent" | "innerHTML" | "class" | "toggleClass";
attribute?: string;
className?: string;
}
/**
* Описание привязки свойства виджета к свойству внутреннего объекта.
*/
interface MemberBindSpec {
/**
* Имя свойства со ссылкой на объект, к которому .
*/
member: string;
/**
* Свойство объекта к которому нужно осуществить привязку.
*/
property: string;
/**
* Привязка осуществляется не только на запись но и на чтение свойства.
*/
getter?: boolean;
}
cin
Working on WatchForRendition
r107 function isNodeBindSpec(v: object): v is NodeBindSpec {
cin
Converted to subproject djx, removed dojo-typings
r65 return "node" in v;
}
/** Декорирует свойства виджета для привязки их к внутренним членам, либо DOM
* элементам, либо свойству внутреннего объекта.
*
* @param {NodeBindSpec | MemberBindSpec} params Параметры связывания.
*/
export function bind(params: NodeBindSpec | MemberBindSpec) {
if (isNodeBindSpec(params)) {
cin
linting
r108 return <K extends string>(target: Record<K, unknown>, name: K) => {
target[makeSetterName(name) as K /** hack to not go insane) */] = params;
cin
Converted to subproject djx, removed dojo-typings
r65 };
} else {
cin
linting
r109 return <K extends string>(target: Record<K | "_set", unknown>, name: K) => {
target[name] = undefined;
target[makeSetterName(name) as K] = function (this: typeof target, v: unknown) {
(this._set as (n: K, v: unknown) => void)(name, v);
const inner = this[params.member as K] as Record<string, unknown>;
cin
linting
r108 if (typeof inner.set === "function")
cin
Working on WatchForRendition
r107 inner.set(params.property, v);
cin
linting
r109 };
cin
Converted to subproject djx, removed dojo-typings
r65 if (params.getter)
cin
linting
r109 target[makeGetterName(name) as K] = function (this: typeof target) {
const inner = this[params.member as K] as Record<string, unknown>;
cin
linting
r108 if (typeof inner.get === "function")
cin
Working on WatchForRendition
r107 return inner.get(params.property) as unknown;
cin
Converted to subproject djx, removed dojo-typings
r65 };
};
}
}
/** Создает в прототипе свойство с указанным значением.
* @param value Значение, которое будет указано в прототипе
*/
export function prototype<T>(value: T): <P extends { [m in K]: T }, K extends keyof P>(p: P, name: K) => void;
export function prototype<T>(value?: T) {
cin
linting
r108 return (p: { [m in string]: T | undefined }, name: string) => {
p[name] = value;
cin
Converted to subproject djx, removed dojo-typings
r65 };
}