vsn 0.1.26 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/vsn.js +1 -1
- package/dist/AST/ArithmeticAssignmentNode.d.ts +23 -0
- package/dist/AST/ArithmeticAssignmentNode.js +313 -0
- package/dist/AST/ArithmeticAssignmentNode.js.map +1 -0
- package/dist/AST/ArithmeticNode.d.ts +15 -0
- package/dist/AST/ArithmeticNode.js +114 -0
- package/dist/AST/ArithmeticNode.js.map +1 -0
- package/dist/AST/ArrayNode.d.ts +14 -0
- package/dist/AST/ArrayNode.js +114 -0
- package/dist/AST/ArrayNode.js.map +1 -0
- package/dist/AST/BlockNode.d.ts +11 -0
- package/dist/AST/BlockNode.js +98 -0
- package/dist/AST/BlockNode.js.map +1 -0
- package/dist/AST/BooleanLiteralNode.d.ts +5 -0
- package/dist/AST/BooleanLiteralNode.js +31 -0
- package/dist/AST/BooleanLiteralNode.js.map +1 -0
- package/dist/AST/ComparisonNode.d.ts +15 -0
- package/dist/AST/ComparisonNode.js +120 -0
- package/dist/AST/ComparisonNode.js.map +1 -0
- package/dist/AST/ConditionalNode.d.ts +13 -0
- package/dist/AST/ConditionalNode.js +95 -0
- package/dist/AST/ConditionalNode.js.map +1 -0
- package/dist/AST/ElementAttributeNode.d.ts +18 -0
- package/dist/AST/ElementAttributeNode.js +159 -0
- package/dist/AST/ElementAttributeNode.js.map +1 -0
- package/dist/AST/ElementQueryNode.d.ts +12 -0
- package/dist/AST/ElementQueryNode.js +111 -0
- package/dist/AST/ElementQueryNode.js.map +1 -0
- package/dist/AST/ElementStyleNode.d.ts +18 -0
- package/dist/AST/ElementStyleNode.js +159 -0
- package/dist/AST/ElementStyleNode.js.map +1 -0
- package/dist/AST/ForStatementNode.d.ts +17 -0
- package/dist/AST/ForStatementNode.js +121 -0
- package/dist/AST/ForStatementNode.js.map +1 -0
- package/dist/AST/FunctionArgumentNode.d.ts +11 -0
- package/dist/AST/FunctionArgumentNode.js +100 -0
- package/dist/AST/FunctionArgumentNode.js.map +1 -0
- package/dist/AST/FunctionCallNode.d.ts +13 -0
- package/dist/AST/FunctionCallNode.js +102 -0
- package/dist/AST/FunctionCallNode.js.map +1 -0
- package/dist/AST/IfStatementNode.d.ts +14 -0
- package/dist/AST/IfStatementNode.js +128 -0
- package/dist/AST/IfStatementNode.js.map +1 -0
- package/dist/AST/InNode.d.ts +15 -0
- package/dist/AST/InNode.js +107 -0
- package/dist/AST/InNode.js.map +1 -0
- package/dist/AST/IndexNode.d.ts +16 -0
- package/dist/AST/IndexNode.js +126 -0
- package/dist/AST/IndexNode.js.map +1 -0
- package/dist/AST/LiteralNode.d.ts +10 -0
- package/dist/AST/LiteralNode.js +74 -0
- package/dist/AST/LiteralNode.js.map +1 -0
- package/dist/AST/Node.d.ts +19 -0
- package/dist/AST/Node.js +117 -0
- package/dist/AST/Node.js.map +1 -0
- package/dist/AST/NotNode.d.ts +12 -0
- package/dist/AST/NotNode.js +103 -0
- package/dist/AST/NotNode.js.map +1 -0
- package/dist/AST/NumberLiteralNode.d.ts +5 -0
- package/dist/AST/NumberLiteralNode.js +36 -0
- package/dist/AST/NumberLiteralNode.js.map +1 -0
- package/dist/AST/ObjectNode.d.ts +14 -0
- package/dist/AST/ObjectNode.js +131 -0
- package/dist/AST/ObjectNode.js.map +1 -0
- package/dist/AST/RootScopeMemberNode.d.ts +11 -0
- package/dist/AST/RootScopeMemberNode.js +87 -0
- package/dist/AST/RootScopeMemberNode.js.map +1 -0
- package/dist/AST/ScopeMemberNode.d.ts +12 -0
- package/dist/AST/ScopeMemberNode.js +128 -0
- package/dist/AST/ScopeMemberNode.js.map +1 -0
- package/dist/AST/UnitLiteralNode.d.ts +15 -0
- package/dist/AST/UnitLiteralNode.js +72 -0
- package/dist/AST/UnitLiteralNode.js.map +1 -0
- package/dist/AST.d.ts +7 -60
- package/dist/AST.js +778 -0
- package/dist/AST.js.map +1 -0
- package/dist/Attribute.d.ts +1 -1
- package/dist/Attribute.js +187 -0
- package/dist/Attribute.js.map +1 -0
- package/dist/Bencmark.js +179 -0
- package/dist/Bencmark.js.map +1 -0
- package/dist/Configuration.d.ts +1 -1
- package/dist/Configuration.js +64 -0
- package/dist/Configuration.js.map +1 -0
- package/dist/Controller.d.ts +4 -2
- package/dist/Controller.js +62 -0
- package/dist/Controller.js.map +1 -0
- package/dist/DOM/DOMObject.d.ts +1 -1
- package/dist/DOM/DOMObject.js +47 -0
- package/dist/DOM/DOMObject.js.map +1 -0
- package/dist/DOM/WrappedDocument.js +34 -0
- package/dist/DOM/WrappedDocument.js.map +1 -0
- package/dist/DOM/WrappedWindow.js +45 -0
- package/dist/DOM/WrappedWindow.js.map +1 -0
- package/dist/DOM.d.ts +1 -1
- package/dist/DOM.js +547 -0
- package/dist/DOM.js.map +1 -0
- package/dist/EventDispatcher.d.ts +29 -0
- package/dist/EventDispatcher.js +132 -0
- package/dist/EventDispatcher.js.map +1 -0
- package/dist/Formats.js +44 -0
- package/dist/Formats.js.map +1 -0
- package/dist/MessageList.d.ts +15 -0
- package/dist/MessageList.js +96 -0
- package/dist/MessageList.js.map +1 -0
- package/dist/Model/Field.d.ts +8 -0
- package/dist/Model/Field.js +38 -0
- package/dist/Model/Field.js.map +1 -0
- package/dist/Model.d.ts +12 -0
- package/dist/Model.js +61 -0
- package/dist/Model.js.map +1 -0
- package/dist/Query.js +66 -0
- package/dist/Query.js.map +1 -0
- package/dist/Registry.d.ts +5 -2
- package/dist/Registry.js +139 -0
- package/dist/Registry.js.map +1 -0
- package/dist/Scope/DynamicScopeData.d.ts +6 -0
- package/dist/Scope/DynamicScopeData.js +54 -0
- package/dist/Scope/DynamicScopeData.js.map +1 -0
- package/dist/Scope/QueryReference.d.ts +10 -0
- package/dist/Scope/QueryReference.js +103 -0
- package/dist/Scope/QueryReference.js.map +1 -0
- package/dist/Scope/ScopeData.d.ts +4 -0
- package/dist/Scope/ScopeData.js +40 -0
- package/dist/Scope/ScopeData.js.map +1 -0
- package/dist/Scope/ScopeDataAbstract.d.ts +22 -0
- package/dist/Scope/ScopeDataAbstract.js +137 -0
- package/dist/Scope/ScopeDataAbstract.js.map +1 -0
- package/dist/Scope/ScopeReference.d.ts +10 -0
- package/dist/Scope/ScopeReference.js +73 -0
- package/dist/Scope/ScopeReference.js.map +1 -0
- package/dist/Scope/ScopedVariableType.d.ts +6 -0
- package/dist/Scope/ScopedVariableType.js +14 -0
- package/dist/Scope/ScopedVariableType.js.map +1 -0
- package/dist/Scope/WrappedArray.d.ts +16 -0
- package/dist/Scope/WrappedArray.js +121 -0
- package/dist/Scope/WrappedArray.js.map +1 -0
- package/dist/Scope/properties/Property.d.ts +18 -0
- package/dist/Scope/properties/Property.js +93 -0
- package/dist/Scope/properties/Property.js.map +1 -0
- package/dist/Scope.d.ts +4 -48
- package/dist/Scope.js +227 -0
- package/dist/Scope.js.map +1 -0
- package/dist/SimplePromise.d.ts +42 -0
- package/dist/SimplePromise.js +217 -0
- package/dist/SimplePromise.js.map +1 -0
- package/dist/Tag/List.js +85 -0
- package/dist/Tag/List.js.map +1 -0
- package/dist/Tag.js +770 -0
- package/dist/Tag.js.map +1 -0
- package/dist/Types.d.ts +1 -0
- package/dist/Types.js +54 -0
- package/dist/Types.js.map +1 -0
- package/dist/Validators.d.ts +7 -0
- package/dist/Validators.js +54 -0
- package/dist/Validators.js.map +1 -0
- package/dist/attributes/AddClassIf.js +93 -0
- package/dist/attributes/AddClassIf.js.map +1 -0
- package/dist/attributes/Bind.js +272 -0
- package/dist/attributes/Bind.js.map +1 -0
- package/dist/attributes/ClassConstructor.d.ts +1 -0
- package/dist/attributes/ClassConstructor.js +104 -0
- package/dist/attributes/ClassConstructor.js.map +1 -0
- package/dist/attributes/ClickRemoveClass.js +114 -0
- package/dist/attributes/ClickRemoveClass.js.map +1 -0
- package/dist/attributes/ClickToggleClass.js +114 -0
- package/dist/attributes/ClickToggleClass.js.map +1 -0
- package/dist/attributes/ControllerAttribute.js +28 -0
- package/dist/attributes/ControllerAttribute.js.map +1 -0
- package/dist/attributes/DisableIf.js +94 -0
- package/dist/attributes/DisableIf.js.map +1 -0
- package/dist/attributes/Exec.js +108 -0
- package/dist/attributes/Exec.js.map +1 -0
- package/dist/attributes/Format.js +99 -0
- package/dist/attributes/Format.js.map +1 -0
- package/dist/attributes/If.js +159 -0
- package/dist/attributes/If.js.map +1 -0
- package/dist/attributes/JSONAttribute.js +118 -0
- package/dist/attributes/JSONAttribute.js.map +1 -0
- package/dist/attributes/KeyAbstract.js +117 -0
- package/dist/attributes/KeyAbstract.js.map +1 -0
- package/dist/attributes/KeyDown.js +88 -0
- package/dist/attributes/KeyDown.js.map +1 -0
- package/dist/attributes/KeyUp.js +88 -0
- package/dist/attributes/KeyUp.js.map +1 -0
- package/dist/attributes/List.js +282 -0
- package/dist/attributes/List.js.map +1 -0
- package/dist/attributes/ListItem.js +138 -0
- package/dist/attributes/ListItem.js.map +1 -0
- package/dist/attributes/ListItemModel.js +39 -0
- package/dist/attributes/ListItemModel.js.map +1 -0
- package/dist/attributes/ModelAttribute.js +29 -0
- package/dist/attributes/ModelAttribute.js.map +1 -0
- package/dist/attributes/Name.js +88 -0
- package/dist/attributes/Name.js.map +1 -0
- package/dist/attributes/On.js +135 -0
- package/dist/attributes/On.js.map +1 -0
- package/dist/attributes/Radio.js +174 -0
- package/dist/attributes/Radio.js.map +1 -0
- package/dist/attributes/Referenced.js +38 -0
- package/dist/attributes/Referenced.js.map +1 -0
- package/dist/attributes/RootAttribute.js +91 -0
- package/dist/attributes/RootAttribute.js.map +1 -0
- package/dist/attributes/ScopeAttribute.js +40 -0
- package/dist/attributes/ScopeAttribute.js.map +1 -0
- package/dist/attributes/ScopeChange.js +130 -0
- package/dist/attributes/ScopeChange.js.map +1 -0
- package/dist/attributes/SetAttribute.js +133 -0
- package/dist/attributes/SetAttribute.js.map +1 -0
- package/dist/attributes/StandardAttribute.js +186 -0
- package/dist/attributes/StandardAttribute.js.map +1 -0
- package/dist/attributes/StyleAttribute.js +183 -0
- package/dist/attributes/StyleAttribute.js.map +1 -0
- package/dist/attributes/Template.js +39 -0
- package/dist/attributes/Template.js.map +1 -0
- package/dist/attributes/TypeAttribute.js +104 -0
- package/dist/attributes/TypeAttribute.js.map +1 -0
- package/dist/attributes/_imports.js +60 -0
- package/dist/attributes/_imports.js.map +1 -0
- package/dist/helpers/DOMHelper.js +81 -0
- package/dist/helpers/DOMHelper.js.map +1 -0
- package/dist/helpers/ElementHelper.js +25 -0
- package/dist/helpers/ElementHelper.js.map +1 -0
- package/dist/helpers/VisionHelper.js +71 -0
- package/dist/helpers/VisionHelper.js.map +1 -0
- package/dist/helpers/decorators.js +38 -0
- package/dist/helpers/decorators.js.map +1 -0
- package/dist/vsn.d.ts +11 -2
- package/dist/vsn.js +181 -0
- package/dist/vsn.js.map +1 -0
- package/package.json +2 -6
- package/src/AST/ArithmeticAssignmentNode.ts +236 -0
- package/src/AST/ArithmeticNode.ts +52 -0
- package/src/AST/ArrayNode.ts +39 -0
- package/src/AST/BlockNode.ts +25 -0
- package/src/AST/BooleanLiteralNode.ts +10 -0
- package/src/AST/ComparisonNode.ts +57 -0
- package/src/AST/ConditionalNode.ts +36 -0
- package/src/AST/ElementAttributeNode.ts +63 -0
- package/src/AST/ElementQueryNode.ts +25 -0
- package/src/AST/ElementStyleNode.ts +63 -0
- package/src/AST/ForStatementNode.ts +59 -0
- package/src/AST/FunctionArgumentNode.ts +27 -0
- package/src/AST/FunctionCallNode.ts +32 -0
- package/src/AST/IfStatementNode.ts +67 -0
- package/src/AST/InNode.ts +46 -0
- package/src/AST/IndexNode.ts +61 -0
- package/src/AST/LiteralNode.ts +17 -0
- package/src/AST/Node.ts +71 -0
- package/src/AST/NotNode.ts +41 -0
- package/src/AST/NumberLiteralNode.ts +14 -0
- package/src/AST/ObjectNode.ts +55 -0
- package/src/AST/RootScopeMemberNode.ts +25 -0
- package/src/AST/ScopeMemberNode.ts +53 -0
- package/src/AST/UnitLiteralNode.ts +51 -0
- package/src/AST.ts +34 -1094
- package/src/Attribute.ts +2 -2
- package/src/Configuration.ts +3 -3
- package/src/Controller.ts +10 -2
- package/src/DOM/DOMObject.ts +1 -1
- package/src/DOM.ts +3 -3
- package/src/EventDispatcher.ts +134 -0
- package/src/Formats.ts +2 -2
- package/src/MessageList.ts +85 -0
- package/src/Model/Field.ts +20 -0
- package/src/Model.ts +43 -0
- package/src/Registry.ts +13 -3
- package/src/Scope/DynamicScopeData.ts +29 -0
- package/src/Scope/QueryReference.ts +29 -0
- package/src/Scope/ScopeData.ts +21 -0
- package/src/Scope/ScopeDataAbstract.ts +126 -0
- package/src/Scope/ScopeReference.ts +30 -0
- package/src/Scope/ScopedVariableType.ts +7 -0
- package/src/Scope/WrappedArray.ts +88 -0
- package/src/Scope/properties/Property.ts +79 -0
- package/src/Scope.ts +31 -252
- package/src/SimplePromise.ts +219 -0
- package/src/Tag.ts +3 -3
- package/src/Types.ts +6 -1
- package/src/Validators.ts +45 -0
- package/src/attributes/Bind.ts +4 -4
- package/src/attributes/ClassConstructor.ts +2 -1
- package/src/attributes/JSONAttribute.ts +2 -1
- package/src/attributes/List.ts +4 -4
- package/src/attributes/Radio.ts +3 -2
- package/src/attributes/ScopeChange.ts +2 -2
- package/src/attributes/SetAttribute.ts +2 -1
- package/src/attributes/StandardAttribute.ts +1 -1
- package/src/attributes/StyleAttribute.ts +3 -2
- package/src/attributes/TypeAttribute.ts +1 -1
- package/src/vsn.ts +16 -5
- package/test/AST/ArithmeticAssignmentNode.spec.ts +47 -0
- package/test/AST.spec.ts +3 -2
- package/test/Controller.spec.ts +44 -0
- package/test/MessageList.spec.ts +101 -0
- package/test/Model/DataModel.spec.ts +0 -0
- package/test/Scope/DynamicScopeData.spec.ts +141 -0
- package/test/Scope.spec.ts +15 -3
- package/test/SimplePromise.spec.ts +271 -0
- package/test/Tag/TagList.spec.ts +1 -1
- package/test/attributes/Bind.spec.ts +5 -5
- package/test/attributes/ListItem.spec.ts +1 -1
- package/dist/vsn.min.js +0 -1
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import {EventDispatcher} from "./EventDispatcher";
|
|
2
|
+
|
|
3
|
+
export interface IDeferred<T> {
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
promise: SimplePromise<T>;
|
|
6
|
+
resolve(result?: T): void;
|
|
7
|
+
reject(reason: string): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type TResolve<T> = (result: T) => void;
|
|
11
|
+
export type TReject = (reason: string) => void;
|
|
12
|
+
export type TResult<T> = T | string | null;
|
|
13
|
+
|
|
14
|
+
export enum EPromiseStates {
|
|
15
|
+
PENDING,
|
|
16
|
+
FULFILLED,
|
|
17
|
+
REJECTED
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface IPromise<T> extends EventDispatcher {
|
|
21
|
+
state: EPromiseStates;
|
|
22
|
+
result: TResult<T>;
|
|
23
|
+
then<X = T>(success?: (result?: T) => X, error?: (reason?: string) => string): IPromise<X>;
|
|
24
|
+
catch(onRejected: (reason: string) => string): IPromise<string>;
|
|
25
|
+
finally<X = T>(finallyCallback: (result: T | string) => X | string): IPromise<X>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function noop<T = any>(result?: T): T { return result as T; }
|
|
29
|
+
|
|
30
|
+
export class SimplePromise<T> extends EventDispatcher implements IPromise<T> {
|
|
31
|
+
protected _state: EPromiseStates;
|
|
32
|
+
protected _result: TResult<T> = null;
|
|
33
|
+
private promiseClass: typeof SimplePromise;
|
|
34
|
+
|
|
35
|
+
constructor(executor: (resolve: TResolve<T>, reject: TReject) => void) {
|
|
36
|
+
super();
|
|
37
|
+
this._state = EPromiseStates.PENDING;
|
|
38
|
+
this.promiseClass = (Object.getPrototypeOf(this).constructor);
|
|
39
|
+
try {
|
|
40
|
+
executor(this._resolve.bind(this), this._reject.bind(this));
|
|
41
|
+
} catch (e) {
|
|
42
|
+
this._reject(e);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public get state(): EPromiseStates {
|
|
47
|
+
return this._state;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public get result(): TResult<T> {
|
|
51
|
+
return this._result;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public static defer<T>(): IDeferred<T> {
|
|
55
|
+
const promise: SimplePromise<T> = new SimplePromise<T>((res, rej) => {});
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
promise: promise,
|
|
59
|
+
resolve: promise._resolve.bind(promise),
|
|
60
|
+
reject: promise._reject.bind(promise)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/*
|
|
65
|
+
* Returns a Promise object that is resolved with the given value. If the value is a thenable (i.e. has a then
|
|
66
|
+
* method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise the returned
|
|
67
|
+
* promise will be fulfilled with the value. Generally, if you don't know if a value is a promise or not,
|
|
68
|
+
* Promise.resolve(value) it instead and work with the return value as a promise.
|
|
69
|
+
*/
|
|
70
|
+
public static resolve<T>(result?: T): IPromise<T> {
|
|
71
|
+
return new SimplePromise<T>((resolve: TResolve<T>): void => {
|
|
72
|
+
if (result instanceof SimplePromise) {
|
|
73
|
+
result.then((innerResult: T) => {
|
|
74
|
+
resolve(innerResult);
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
resolve(result);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/*
|
|
83
|
+
* Returns a Promise object that is rejected with the given reason.
|
|
84
|
+
*/
|
|
85
|
+
public static reject(reason: string): IPromise<void> {
|
|
86
|
+
return new SimplePromise<void>((resolve: TResolve<void>, reject: TReject): void => {
|
|
87
|
+
reject(reason);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
* Returns a promise that either fulfills when all of the promises in the iterable argument have fulfilled or
|
|
93
|
+
* rejects as soon as one of the promises in the iterable argument rejects. If the returned promise fulfills, it is
|
|
94
|
+
* fulfilled with an array of the values from the fulfilled promises in the same order as defined in the iterable.
|
|
95
|
+
* If the returned promise rejects, it is rejected with the reason from the first promise in the iterable that
|
|
96
|
+
* rejected. This method can be useful for aggregating results of multiple promises.
|
|
97
|
+
*/
|
|
98
|
+
public static all<T>(iter: IPromise<T>[]): IPromise<T[]> {
|
|
99
|
+
const deferred: IDeferred<T[]> = SimplePromise.defer<T[]>();
|
|
100
|
+
let done: boolean = true;
|
|
101
|
+
for (const promise of iter) {
|
|
102
|
+
if (promise.state == EPromiseStates.PENDING) {
|
|
103
|
+
done = false;
|
|
104
|
+
promise.once('fulfilled', (result: T): void => {
|
|
105
|
+
SimplePromise.poolResults(iter, deferred);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
promise.once('rejected', (reason: string): void => {
|
|
109
|
+
deferred.reject(reason);
|
|
110
|
+
});
|
|
111
|
+
} else if(promise.state == EPromiseStates.REJECTED) {
|
|
112
|
+
deferred.reject(promise.result as string);
|
|
113
|
+
done = false;
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (done)
|
|
119
|
+
SimplePromise.poolResults(iter, deferred);
|
|
120
|
+
|
|
121
|
+
return deferred.promise;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public static poolResults<T>(iter: IPromise<T>[], deferred: IDeferred<T[]>) {
|
|
125
|
+
let done: boolean = true;
|
|
126
|
+
const results: T[] = [];
|
|
127
|
+
for (const p of iter) {
|
|
128
|
+
if (p.state === EPromiseStates.REJECTED) {
|
|
129
|
+
deferred.reject(p.result as string);
|
|
130
|
+
break;
|
|
131
|
+
} else if (p.state === EPromiseStates.PENDING) {
|
|
132
|
+
done = false;
|
|
133
|
+
}
|
|
134
|
+
results.push(p.result as T);
|
|
135
|
+
}
|
|
136
|
+
if (done)
|
|
137
|
+
deferred.resolve(results);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/*
|
|
141
|
+
* Returns a promise that fulfills or rejects as soon as one of the promises in the iterable fulfills or rejects,
|
|
142
|
+
* with the value or reason from that promise.
|
|
143
|
+
*/
|
|
144
|
+
public static race<T>(iter: IPromise<T>[]): IPromise<T> {
|
|
145
|
+
const deferred: IDeferred<T> = SimplePromise.defer<T>();
|
|
146
|
+
|
|
147
|
+
for (const promise of iter) {
|
|
148
|
+
promise.once('fulfilled', (result: T) => {
|
|
149
|
+
deferred.resolve(result);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
promise.once('rejected', (reason: string) => {
|
|
153
|
+
deferred.reject(reason);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return deferred.promise;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/*
|
|
161
|
+
* Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return
|
|
162
|
+
* value of the called handler, or to its original settled value if the promise was not handled (i.e. if the
|
|
163
|
+
* relevant handler onFulfilled or onRejected is not a function).
|
|
164
|
+
*/
|
|
165
|
+
public then<X = T>(success?: (result: T) => X, error?: (reason: string) => string): IPromise<X> {
|
|
166
|
+
return new this.promiseClass<X>((resolve: TResolve<X>, reject: TReject): void => {
|
|
167
|
+
if (this.state === EPromiseStates.FULFILLED) {
|
|
168
|
+
if (success)
|
|
169
|
+
resolve(success(this.result as T));
|
|
170
|
+
} else if (this.state === EPromiseStates.REJECTED) {
|
|
171
|
+
if (error)
|
|
172
|
+
reject(error(this.result as string));
|
|
173
|
+
} else {
|
|
174
|
+
this.once('fulfilled', (result: T): void => {
|
|
175
|
+
if (success)
|
|
176
|
+
resolve(success(result));
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
this.once('rejected', (reason: string): void => {
|
|
180
|
+
if (error)
|
|
181
|
+
reject(error(reason));
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/*
|
|
188
|
+
* Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of
|
|
189
|
+
* the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled.
|
|
190
|
+
*/
|
|
191
|
+
public catch(onRejected: (reason: string) => string): IPromise<string> {
|
|
192
|
+
return this.then<string>(undefined, onRejected);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/*
|
|
196
|
+
* Appends a handler to the promise, and returns a new promise which is resolved when the original promise is
|
|
197
|
+
* resolved. The handler is called when the promise is settled, whether fulfilled or rejected.
|
|
198
|
+
*/
|
|
199
|
+
public finally<X = T>(finallyCallback: (result: T | string) => X | string): IPromise<X> {
|
|
200
|
+
const success: (r: T) => X = (result: T): X => finallyCallback(result) as X;
|
|
201
|
+
const error: (r: string) => string = (reason: string): string => finallyCallback(reason) as string;
|
|
202
|
+
|
|
203
|
+
return this.then<X>(success, error);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
protected _resolve(result: T): void {
|
|
207
|
+
if (this.state !== EPromiseStates.PENDING) return;
|
|
208
|
+
this._state = EPromiseStates.FULFILLED;
|
|
209
|
+
this._result = result;
|
|
210
|
+
this.dispatch('fulfilled', result);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
protected _reject(reason: string): void {
|
|
214
|
+
if (this.state !== EPromiseStates.PENDING) return;
|
|
215
|
+
this._state = EPromiseStates.REJECTED;
|
|
216
|
+
this._result = reason;
|
|
217
|
+
this.dispatch('rejected', reason);
|
|
218
|
+
}
|
|
219
|
+
}
|
package/src/Tag.ts
CHANGED
|
@@ -122,7 +122,7 @@ export class Tag extends DOMObject {
|
|
|
122
122
|
for (const attr of this.attributes) {
|
|
123
123
|
attr.mutate(mutation);
|
|
124
124
|
}
|
|
125
|
-
this.
|
|
125
|
+
this.dispatch('mutate', mutation);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
public get(attr: string) {
|
|
@@ -254,11 +254,11 @@ export class Tag extends DOMObject {
|
|
|
254
254
|
if (obj instanceof Controller) {
|
|
255
255
|
obj.init(this.scope, this, this.element);
|
|
256
256
|
} else {
|
|
257
|
-
this.scope.wrap(obj, triggerUpdates, updateFromWrapped);
|
|
258
257
|
obj['$scope'] = this.scope;
|
|
259
258
|
obj['$tag'] = this;
|
|
260
259
|
obj['$el'] = this.element;
|
|
261
260
|
}
|
|
261
|
+
this.scope.wrap(obj, triggerUpdates, updateFromWrapped);
|
|
262
262
|
return obj;
|
|
263
263
|
}
|
|
264
264
|
|
|
@@ -348,7 +348,7 @@ export class Tag extends DOMObject {
|
|
|
348
348
|
if (defer && attrClass.canDefer) {
|
|
349
349
|
await attrObj.defer();
|
|
350
350
|
this.deferredAttributes.push(attrObj);
|
|
351
|
-
attrObj.
|
|
351
|
+
attrObj.on('state', this.onAttributeStateChange.bind(this));
|
|
352
352
|
}
|
|
353
353
|
}
|
|
354
354
|
}
|
package/src/Types.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import {Registry} from "./Registry";
|
|
2
2
|
|
|
3
3
|
export class Types {
|
|
4
|
+
@Registry.type('any')
|
|
5
|
+
public static any(value: any): any {
|
|
6
|
+
return value as any;
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
@Registry.type('string')
|
|
5
10
|
public static string(value: string) {
|
|
6
|
-
return value
|
|
11
|
+
return `${value}`;
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
@Registry.type('integer')
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {Registry} from "./Registry";
|
|
2
|
+
|
|
3
|
+
export class Validators {
|
|
4
|
+
public static readonly _emailRegex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
|
|
5
|
+
|
|
6
|
+
@Registry.validator('email')
|
|
7
|
+
public static email(value: any): string[] {
|
|
8
|
+
const errors: string[] = [];
|
|
9
|
+
|
|
10
|
+
if(value != null && !this._emailRegex.test(value))
|
|
11
|
+
errors.push('Please enter a valid email address');
|
|
12
|
+
|
|
13
|
+
return errors;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Registry.validator('required')
|
|
17
|
+
public static required(value: any): string[] {
|
|
18
|
+
const errors: string[] = [];
|
|
19
|
+
|
|
20
|
+
if(value == null || value.length == 0)
|
|
21
|
+
errors.push('This field is required');
|
|
22
|
+
|
|
23
|
+
return errors;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Registry.validator('positive')
|
|
27
|
+
public static positive(value: any): string[] {
|
|
28
|
+
const errors: string[] = [];
|
|
29
|
+
|
|
30
|
+
if(value != null && value < 0)
|
|
31
|
+
errors.push('Please enter a positive number');
|
|
32
|
+
|
|
33
|
+
return errors;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Registry.validator('negative')
|
|
37
|
+
public static negative(value: any): string[] {
|
|
38
|
+
const errors: string[] = [];
|
|
39
|
+
|
|
40
|
+
if(value != null && value > 0)
|
|
41
|
+
errors.push('Please enter a negative number');
|
|
42
|
+
|
|
43
|
+
return errors;
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/attributes/Bind.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {Scope
|
|
1
|
+
import {Scope} from "../Scope";
|
|
2
2
|
import {Attribute} from "../Attribute";
|
|
3
3
|
import {Tree} from "../AST";
|
|
4
4
|
import {Registry} from "../Registry";
|
|
5
|
+
import {ScopeReference} from "../Scope/ScopeReference";
|
|
5
6
|
|
|
6
7
|
@Registry.attribute('vsn-bind')
|
|
7
8
|
export class Bind extends Attribute {
|
|
@@ -19,7 +20,7 @@ export class Bind extends Attribute {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
public async setup() {
|
|
22
|
-
this.property = this.getAttributeBinding();
|
|
23
|
+
this.property = this.getAttributeBinding(this.property);
|
|
23
24
|
const mods = this.getAttributeModifiers();
|
|
24
25
|
if (mods.length) {
|
|
25
26
|
if (mods.indexOf('from') > -1) {
|
|
@@ -53,7 +54,7 @@ export class Bind extends Attribute {
|
|
|
53
54
|
public async connect() {
|
|
54
55
|
if (this.doUpdateTo) {
|
|
55
56
|
this.updateTo();
|
|
56
|
-
this.boundScope.
|
|
57
|
+
this.boundScope.on(`change:${this.key}`, this.updateTo, this);
|
|
57
58
|
}
|
|
58
59
|
await super.connect();
|
|
59
60
|
}
|
|
@@ -90,7 +91,6 @@ export class Bind extends Attribute {
|
|
|
90
91
|
|
|
91
92
|
public mutate(mutation: MutationRecord) {
|
|
92
93
|
super.mutate(mutation);
|
|
93
|
-
|
|
94
94
|
if (!this.doUpdateFrom) return;
|
|
95
95
|
|
|
96
96
|
// Element innerText binding
|
|
@@ -8,6 +8,7 @@ export class ClassConstructor extends Attribute {
|
|
|
8
8
|
public static readonly scoped: boolean = true;
|
|
9
9
|
protected attributeKey: string;
|
|
10
10
|
protected className: string;
|
|
11
|
+
protected defaultClassName: string;
|
|
11
12
|
|
|
12
13
|
public async setup() {
|
|
13
14
|
const parentScope: Scope = this.tag.parentTag.scope;
|
|
@@ -15,7 +16,7 @@ export class ClassConstructor extends Attribute {
|
|
|
15
16
|
return;
|
|
16
17
|
|
|
17
18
|
this.attributeKey = this.getAttributeBinding();
|
|
18
|
-
this.className = this.getAttributeValue();
|
|
19
|
+
this.className = this.getAttributeValue(this.defaultClassName);
|
|
19
20
|
|
|
20
21
|
const cls = await Registry.instance.classes.get(this.className);
|
|
21
22
|
this.instantiateClass(cls);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {Registry} from "../Registry";
|
|
2
2
|
import {Attribute} from "../Attribute";
|
|
3
|
-
import {Scope
|
|
3
|
+
import {Scope} from "../Scope";
|
|
4
|
+
import {ScopeReference} from "../Scope/ScopeReference";
|
|
4
5
|
|
|
5
6
|
@Registry.attribute('vsn-json')
|
|
6
7
|
export class JSONAttribute extends Attribute {
|
package/src/attributes/List.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Attribute} from "../Attribute";
|
|
2
2
|
import {Tag} from "../Tag";
|
|
3
|
-
import {WrappedArray} from "../Scope";
|
|
3
|
+
import {WrappedArray} from "../Scope/WrappedArray";
|
|
4
4
|
import {Tree} from "../AST";
|
|
5
5
|
import {ElementHelper} from "../helpers/ElementHelper";
|
|
6
6
|
import {Registry} from "../Registry";
|
|
@@ -84,10 +84,10 @@ export class List extends Attribute {
|
|
|
84
84
|
this.items = new WrappedArray(this.items);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
(this.items as WrappedArray<any>).
|
|
87
|
+
(this.items as WrappedArray<any>).on('add', (item) => {
|
|
88
88
|
this.add(item);
|
|
89
89
|
});
|
|
90
|
-
(this.items as WrappedArray<any>).
|
|
90
|
+
(this.items as WrappedArray<any>).on('remove', (item) => {
|
|
91
91
|
this.remove(item);
|
|
92
92
|
});
|
|
93
93
|
|
|
@@ -137,6 +137,6 @@ export class List extends Attribute {
|
|
|
137
137
|
tag.wrap(obj);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
this.tag.
|
|
140
|
+
this.tag.dispatch('add', obj);
|
|
141
141
|
}
|
|
142
142
|
}
|
package/src/attributes/Radio.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {Registry} from "../Registry";
|
|
2
2
|
import {Attribute} from "../Attribute";
|
|
3
|
-
import {Scope
|
|
3
|
+
import {Scope} from "../Scope";
|
|
4
|
+
import {ScopeReference} from "../Scope/ScopeReference";
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
@Registry.attribute('vsn-radio')
|
|
@@ -31,7 +32,7 @@ export class Radio extends Attribute {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
public async connect() {
|
|
34
|
-
this.boundScope.
|
|
35
|
+
this.boundScope.on(`change:${this.key}`, this.checkSelected, this);
|
|
35
36
|
this.tag.addEventHandler('change', this.getAttributeModifiers(), this.handleEvent.bind(this));
|
|
36
37
|
await this.checkSelected();
|
|
37
38
|
await super.connect();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Attribute} from "../Attribute";
|
|
2
2
|
import {Tree} from "../AST";
|
|
3
|
-
import {ScopeReference} from "../Scope";
|
|
3
|
+
import {ScopeReference} from "../Scope/ScopeReference";
|
|
4
4
|
import {Registry} from "../Registry";
|
|
5
5
|
|
|
6
6
|
@Registry.attribute('vsn-scope-change')
|
|
@@ -18,7 +18,7 @@ export abstract class ScopeChange extends Attribute {
|
|
|
18
18
|
public async connect() {
|
|
19
19
|
const binding = this.getAttributeBinding();
|
|
20
20
|
const ref: ScopeReference = this.tag.scope.getReference(binding, false);
|
|
21
|
-
(await ref.getScope()).
|
|
21
|
+
(await ref.getScope()).on(`change:${await ref.getKey()}`, this.handleEvent.bind(this));
|
|
22
22
|
await super.connect();
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {Scope
|
|
1
|
+
import {Scope} from "../Scope";
|
|
2
2
|
import {Attribute} from "../Attribute";
|
|
3
3
|
import {Registry} from "../Registry";
|
|
4
|
+
import {ScopeReference} from "../Scope/ScopeReference";
|
|
4
5
|
|
|
5
6
|
@Registry.attribute('vsn-set')
|
|
6
7
|
export class SetAttribute extends Attribute {
|
|
@@ -22,7 +22,7 @@ export class StandardAttribute extends Attribute {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
public async connect() {
|
|
25
|
-
this.tag.scope.
|
|
25
|
+
this.tag.scope.on(`change:${this.key}`, this.updateTo.bind(this));
|
|
26
26
|
await super.connect();
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {Registry} from "../Registry";
|
|
2
2
|
import {Attribute} from "../Attribute";
|
|
3
|
-
import {Scope
|
|
3
|
+
import {Scope} from "../Scope";
|
|
4
|
+
import {ScopeReference} from "../Scope/ScopeReference";
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
@Registry.attribute('vsn-styles')
|
|
@@ -28,7 +29,7 @@ export class StyleAttribute extends Attribute {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
public async connect() {
|
|
31
|
-
this.styleScope.
|
|
32
|
+
this.styleScope.on(`change`, this.handleEvent.bind(this));
|
|
32
33
|
await super.connect();
|
|
33
34
|
}
|
|
34
35
|
|
package/src/vsn.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import {DOM} from "./DOM";
|
|
2
|
-
import {
|
|
3
|
-
import {WrappedArray} from "./Scope";
|
|
4
|
-
import {DataModel} from "simple-ts-models";
|
|
2
|
+
import {WrappedArray} from "./Scope/WrappedArray";
|
|
5
3
|
import {Registry} from "./Registry";
|
|
6
4
|
import "./Types";
|
|
7
5
|
import "./Formats";
|
|
@@ -9,6 +7,10 @@ import {Configuration} from "./Configuration";
|
|
|
9
7
|
import {VisionHelper} from "./helpers/VisionHelper";
|
|
10
8
|
import {Tree} from "./AST";
|
|
11
9
|
import {Query} from "./Query";
|
|
10
|
+
import {EventDispatcher} from "./EventDispatcher";
|
|
11
|
+
import {DynamicScopeData} from "./Scope/DynamicScopeData";
|
|
12
|
+
import {Controller} from "./Controller";
|
|
13
|
+
import {property} from "./Scope/properties/Property";
|
|
12
14
|
|
|
13
15
|
export class Vision extends EventDispatcher {
|
|
14
16
|
protected static _instance: Vision;
|
|
@@ -28,7 +30,7 @@ export class Vision extends EventDispatcher {
|
|
|
28
30
|
}
|
|
29
31
|
this.registry.classes.register('Object', Object);
|
|
30
32
|
this.registry.classes.register('WrappedArray', WrappedArray);
|
|
31
|
-
this.registry.classes.register('
|
|
33
|
+
this.registry.classes.register('Data', DynamicScopeData);
|
|
32
34
|
|
|
33
35
|
if (VisionHelper.window) {
|
|
34
36
|
window['Vision'] = Vision;
|
|
@@ -72,6 +74,15 @@ export * from './Registry';
|
|
|
72
74
|
export * from './Attribute';
|
|
73
75
|
export * from './AST';
|
|
74
76
|
export {DOM} from './DOM';
|
|
75
|
-
export {
|
|
77
|
+
export {Scope} from './Scope';
|
|
78
|
+
export {ScopeReference} from './Scope/ScopeReference';
|
|
79
|
+
export {WrappedArray} from './Scope/WrappedArray';
|
|
76
80
|
export {Controller} from './Controller';
|
|
81
|
+
export {Property, property} from './Scope/properties/Property';
|
|
82
|
+
export {Field} from './Model/Field';
|
|
83
|
+
export {Model} from './Model';
|
|
84
|
+
export {EventDispatcher} from './EventDispatcher';
|
|
85
|
+
export {MessageList} from './MessageList';
|
|
86
|
+
export {SimplePromise} from './SimplePromise';
|
|
87
|
+
export {Tag} from './Tag';
|
|
77
88
|
export const vision: Vision = Vision.instance;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {SimplePromise} from "../../src/SimplePromise";
|
|
2
|
+
import {DOM} from "../../src/DOM";
|
|
3
|
+
import {Tree} from "../../src/AST";
|
|
4
|
+
import {Scope} from "../../src/Scope";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
describe('ArithmeticAssignmentNode', () => {
|
|
8
|
+
it("should support simple arithmetic with numbers", async () => {
|
|
9
|
+
const tree = new Tree(`
|
|
10
|
+
a = 1;
|
|
11
|
+
a += 10;
|
|
12
|
+
b = a + 1;
|
|
13
|
+
b -= 10;
|
|
14
|
+
c = a + 1;
|
|
15
|
+
c /= 2;
|
|
16
|
+
d = a + 1;
|
|
17
|
+
d *= 2;
|
|
18
|
+
`);
|
|
19
|
+
const scope = new Scope();
|
|
20
|
+
await tree.evaluate(scope, null, null);
|
|
21
|
+
expect(scope.get("a")).toBe(11);
|
|
22
|
+
expect(scope.get("b")).toBe(2);
|
|
23
|
+
expect(scope.get("c")).toBe(6);
|
|
24
|
+
expect(scope.get("d")).toBe(24);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should support simple arithmetic with numbers inside nested objects", async () => {
|
|
28
|
+
const tree = new Tree(`
|
|
29
|
+
z = {};
|
|
30
|
+
a = 100;
|
|
31
|
+
z.z = {};
|
|
32
|
+
z.z.a = 10;
|
|
33
|
+
z.a = 1;
|
|
34
|
+
z.b = 15;
|
|
35
|
+
z.a += z.z.a;
|
|
36
|
+
z.b *= a + z.a + z.b;
|
|
37
|
+
z.z.b = z.z.a + z.a;
|
|
38
|
+
z.z.b *= z.z.a;
|
|
39
|
+
`);
|
|
40
|
+
const scope = new Scope();
|
|
41
|
+
await tree.evaluate(scope, null, null);
|
|
42
|
+
expect(await Tree.apply('z.z.a', scope, null, null)).toBe(10);
|
|
43
|
+
expect(await Tree.apply('z.a', scope, null, null)).toBe(11);
|
|
44
|
+
expect(await Tree.apply('z.b', scope, null, null)).toBe(1890);
|
|
45
|
+
expect(await Tree.apply('z.z.b', scope, null, null)).toBe(210);
|
|
46
|
+
});
|
|
47
|
+
});
|
package/test/AST.spec.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {Scope
|
|
1
|
+
import {WrappedArray} from '../src/Scope/WrappedArray';
|
|
2
|
+
import {Scope} from "../src/Scope";
|
|
3
3
|
import {Tree} from "../src/AST";
|
|
4
4
|
import {DOM} from "../src/DOM";
|
|
5
|
+
import {IDeferred, SimplePromise} from "../src/SimplePromise";
|
|
5
6
|
|
|
6
7
|
describe('Tree', () => {
|
|
7
8
|
let scope: Scope = null,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {Controller} from '../src/Controller';
|
|
2
|
+
import {DOM} from "../src/DOM";
|
|
3
|
+
import {SimplePromise} from "../src/SimplePromise";
|
|
4
|
+
import {Registry} from "../src/Registry";
|
|
5
|
+
import {property} from "../src/Scope/properties/Property";
|
|
6
|
+
import {Property} from "../src/vsn";
|
|
7
|
+
|
|
8
|
+
@Registry.controller('ControllerTestController')
|
|
9
|
+
class TestController extends Controller {
|
|
10
|
+
@property()
|
|
11
|
+
public test: string;
|
|
12
|
+
|
|
13
|
+
@property(Property, {
|
|
14
|
+
type: 'integer',
|
|
15
|
+
min: 0,
|
|
16
|
+
max: 100,
|
|
17
|
+
validators: [
|
|
18
|
+
'positive',
|
|
19
|
+
]
|
|
20
|
+
})
|
|
21
|
+
public positive_integer: number;
|
|
22
|
+
|
|
23
|
+
isValid(): boolean {
|
|
24
|
+
return this.test === 'test';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe('Controller', () => {
|
|
29
|
+
it("methods should be callable from vsn-script", async () => {
|
|
30
|
+
document.body.innerHTML = `
|
|
31
|
+
<div vsn-controller:test="ControllerTestController" vsn-set:test.test="notTest" vsn-bind="test.test"></div>
|
|
32
|
+
`;
|
|
33
|
+
const dom = new DOM(document);
|
|
34
|
+
const deferred = SimplePromise.defer();
|
|
35
|
+
dom.once('built', async () => {
|
|
36
|
+
expect(await dom.eval('test.test')).toBe('notTest');
|
|
37
|
+
expect(await dom.eval('test.isValid()')).toBe(false);
|
|
38
|
+
await dom.eval('test.test = "test"');
|
|
39
|
+
expect(await dom.eval('test.isValid()')).toBe(true);
|
|
40
|
+
deferred.resolve();
|
|
41
|
+
});
|
|
42
|
+
await deferred.promise;
|
|
43
|
+
});
|
|
44
|
+
});
|