vsn 0.1.131 → 0.1.133
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/examples/cascading-function-sheets.html +27 -7
- package/demo/examples/item-filtering.html +1 -1
- package/demo/memory-leak-test.html +15 -0
- package/demo/resources/xhr-lazy.html +4 -3
- package/demo/resources/xhr-memory-leak-test.html +587 -0
- package/demo/vsn.js +2 -2
- package/dist/AST/AssignmentNode.js.map +1 -1
- package/dist/AST/ClassNode.d.ts +3 -0
- package/dist/AST/ClassNode.js +10 -8
- package/dist/AST/ClassNode.js.map +1 -1
- package/dist/AST/FunctionNode.js +11 -10
- package/dist/AST/FunctionNode.js.map +1 -1
- package/dist/AST/IndexNode.js +0 -1
- package/dist/AST/IndexNode.js.map +1 -1
- package/dist/DOM/AbstractDOM.d.ts +2 -1
- package/dist/DOM/AbstractDOM.js +8 -0
- package/dist/DOM/AbstractDOM.js.map +1 -1
- package/dist/DOM/DOMObject.js +3 -0
- package/dist/DOM/DOMObject.js.map +1 -1
- package/dist/Tag.js +20 -10
- package/dist/Tag.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/AST/AssignmentNode.ts +1 -0
- package/src/AST/ClassNode.ts +9 -6
- package/src/AST/FunctionNode.ts +11 -9
- package/src/AST/IndexNode.ts +0 -1
- package/src/DOM/AbstractDOM.ts +9 -1
- package/src/DOM/DOMObject.ts +3 -0
- package/src/Tag.ts +20 -11
- package/src/version.ts +1 -1
- package/test/AST/ClassNode.spec.ts +5 -5
package/src/AST/ClassNode.ts
CHANGED
|
@@ -14,6 +14,7 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
14
14
|
public static readonly classParents: {[name: string]: string[]} = {};
|
|
15
15
|
public static readonly classChildren: {[name: string]: string[]} = {}; // List of child class selectors for a given class selector
|
|
16
16
|
public static readonly preppedTags: {[name: string]: Tag[]} = {};
|
|
17
|
+
public static readonly preppingElements: {[name: string]: HTMLElement[]} = {};
|
|
17
18
|
|
|
18
19
|
protected requiresPrep: boolean = true;
|
|
19
20
|
public readonly classScope: Scope = new Scope();
|
|
@@ -59,6 +60,7 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
59
60
|
ClassNode.classes[this._fullSelector] = this;
|
|
60
61
|
ClassNode.classChildren[this._fullSelector] = [];
|
|
61
62
|
ClassNode.preppedTags[this._fullSelector] = [];
|
|
63
|
+
ClassNode.preppingElements[this._fullSelector] = []
|
|
62
64
|
|
|
63
65
|
if (ClassNode.classParents[this.selector] === undefined)
|
|
64
66
|
ClassNode.classParents[this.selector] = [];
|
|
@@ -79,8 +81,11 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
79
81
|
|
|
80
82
|
public async findClassElements(dom: DOM, tag: Tag = null) {
|
|
81
83
|
const tags: Tag[] = [];
|
|
82
|
-
for (const element of Array.from(dom.querySelectorAll(this.
|
|
84
|
+
for (const element of Array.from(dom.querySelectorAll(this.fullSelector, tag))) {
|
|
85
|
+
if (ClassNode.preppingElements[this._fullSelector].indexOf(element as HTMLElement) > -1) continue;
|
|
86
|
+
ClassNode.preppingElements[this._fullSelector].push(element as HTMLElement);
|
|
83
87
|
tags.push(await ClassNode.addElementClass(this._fullSelector, element as HTMLElement, dom, element[Tag.TaggedVariable] || null));
|
|
88
|
+
ClassNode.preppingElements[this._fullSelector].splice(ClassNode.preppingElements[this._fullSelector].indexOf(element as HTMLElement), 1);
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
for (const childSelector of ClassNode.classChildren[this._fullSelector]) {
|
|
@@ -102,14 +107,12 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
102
107
|
hasConstruct = this.classScope.has('construct');
|
|
103
108
|
|
|
104
109
|
tag.createScope(true);
|
|
105
|
-
// Create object scope
|
|
106
|
-
tag.scope.set('this', new Scope(tag.scope));
|
|
107
110
|
const meta = this.updateMeta();
|
|
108
111
|
meta['PrepForSelector'] = this.fullSelector;
|
|
109
112
|
await this.block.prepare(tag.scope, dom, tag, meta);
|
|
110
113
|
if (hasConstruct) {
|
|
111
114
|
const fncCls: FunctionNode = this.classScope.get('construct') as FunctionNode;
|
|
112
|
-
const fnc = await fncCls.getFunction(tag.scope, dom, tag,
|
|
115
|
+
const fnc = await fncCls.getFunction(tag.scope, dom, tag, true);
|
|
113
116
|
await fnc();
|
|
114
117
|
}
|
|
115
118
|
tag.dispatch(`${this.fullSelector}.construct`, tag.element.id);
|
|
@@ -122,7 +125,7 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
122
125
|
|
|
123
126
|
if (hasDeconstruct) {
|
|
124
127
|
const fncCls: FunctionNode = this.classScope.get('deconstruct') as FunctionNode;
|
|
125
|
-
const fnc = await fncCls.getFunction(tag.scope, dom, tag,
|
|
128
|
+
const fnc = await fncCls.getFunction(tag.scope, dom, tag, true);
|
|
126
129
|
await fnc();
|
|
127
130
|
}
|
|
128
131
|
for (const key of this.classScope.keys) {
|
|
@@ -133,7 +136,7 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
133
136
|
}
|
|
134
137
|
tag.dispatch(`${this.fullSelector}.deconstruct`);
|
|
135
138
|
ClassNode.preppedTags[this.fullSelector].splice(ClassNode.preppedTags[this.fullSelector].indexOf(tag), 1);
|
|
136
|
-
|
|
139
|
+
ClassNode.removePreparedClassFromElement(tag.element, this.fullSelector);
|
|
137
140
|
}
|
|
138
141
|
|
|
139
142
|
public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
|
package/src/AST/FunctionNode.ts
CHANGED
|
@@ -24,14 +24,15 @@ export class FunctionNode extends Node implements TreeNode {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
public async prepare(scope: Scope, dom: DOM, tag: Tag = null, meta?: any): Promise<void> {
|
|
27
|
-
if (meta?.ClassNode) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
} else {
|
|
33
|
-
|
|
34
|
-
}
|
|
27
|
+
// if (meta?.ClassNode) {
|
|
28
|
+
// // Set on object instance
|
|
29
|
+
// if (tag && tag.scope.has('this')) {
|
|
30
|
+
// tag.scope.get('this').set(this.name, this);
|
|
31
|
+
// }
|
|
32
|
+
// } else {
|
|
33
|
+
// scope.set(this.name, this);
|
|
34
|
+
// }
|
|
35
|
+
scope.set(this.name, this);
|
|
35
36
|
await super.prepare(scope, dom, tag, meta);
|
|
36
37
|
}
|
|
37
38
|
|
|
@@ -41,7 +42,7 @@ export class FunctionNode extends Node implements TreeNode {
|
|
|
41
42
|
|
|
42
43
|
public async collectGarbage() {
|
|
43
44
|
for (const f of this.garbage) {
|
|
44
|
-
f.
|
|
45
|
+
f.deconstruct();
|
|
45
46
|
}
|
|
46
47
|
this.garbage = [];
|
|
47
48
|
}
|
|
@@ -52,6 +53,7 @@ export class FunctionNode extends Node implements TreeNode {
|
|
|
52
53
|
let functionScope;
|
|
53
54
|
if (createFunctionScope && !(scope instanceof FunctionScope)) {
|
|
54
55
|
functionScope = new FunctionScope(scope);
|
|
56
|
+
functionScope.set('this', scope);
|
|
55
57
|
self.garbage.push(functionScope);
|
|
56
58
|
} else {
|
|
57
59
|
functionScope = scope;
|
package/src/AST/IndexNode.ts
CHANGED
package/src/DOM/AbstractDOM.ts
CHANGED
|
@@ -206,6 +206,7 @@ export abstract class AbstractDOM extends EventDispatcher {
|
|
|
206
206
|
|
|
207
207
|
for (const ele of Array.from(mutation.removedNodes)) {
|
|
208
208
|
for (const tag of this.getTagsFromParent(ele)) {
|
|
209
|
+
if (tag.hasAttribute('vsn-template')) continue;
|
|
209
210
|
tag.deconstruct();
|
|
210
211
|
}
|
|
211
212
|
}
|
|
@@ -247,7 +248,7 @@ export abstract class AbstractDOM extends EventDispatcher {
|
|
|
247
248
|
return discovered;
|
|
248
249
|
}
|
|
249
250
|
|
|
250
|
-
async buildTag<T
|
|
251
|
+
async buildTag<T extends Tag>(element: HTMLElement, returnExisting: boolean = false, cls: any = Tag): Promise<T> {
|
|
251
252
|
if (element[Tag.TaggedVariable]) return returnExisting ? element[Tag.TaggedVariable] : null;
|
|
252
253
|
if (element.tagName.toLowerCase() === 'slot')
|
|
253
254
|
cls = SlotTag;
|
|
@@ -256,9 +257,16 @@ export abstract class AbstractDOM extends EventDispatcher {
|
|
|
256
257
|
|
|
257
258
|
const tag: T = new cls(element, this);
|
|
258
259
|
this.tags.push(tag as any);
|
|
260
|
+
tag.once('deconstruct', this.removeTag, this);
|
|
259
261
|
return tag;
|
|
260
262
|
}
|
|
261
263
|
|
|
264
|
+
protected removeTag(tag: Tag) {
|
|
265
|
+
const index = this.tags.indexOf(tag);
|
|
266
|
+
if (index > -1)
|
|
267
|
+
this.tags.splice(index, 1);
|
|
268
|
+
}
|
|
269
|
+
|
|
262
270
|
async setupTags(tags: Tag[]) {
|
|
263
271
|
// Configure, setup & execute attributes
|
|
264
272
|
for (const tag of tags)
|
package/src/DOM/DOMObject.ts
CHANGED
package/src/Tag.ts
CHANGED
|
@@ -257,10 +257,13 @@ export class Tag extends DOMObject {
|
|
|
257
257
|
|
|
258
258
|
public addChild(tag: Tag) {
|
|
259
259
|
this._children.push(tag);
|
|
260
|
+
tag.once('deconstruct', this.removeChild, this);
|
|
260
261
|
}
|
|
261
262
|
|
|
262
263
|
public removeChild(tag: Tag) {
|
|
263
|
-
this._children.
|
|
264
|
+
const index = this._children.indexOf(tag);
|
|
265
|
+
if (index > -1)
|
|
266
|
+
this._children.splice(index, 1);
|
|
264
267
|
}
|
|
265
268
|
|
|
266
269
|
public get children(): Tag[] {
|
|
@@ -268,17 +271,18 @@ export class Tag extends DOMObject {
|
|
|
268
271
|
}
|
|
269
272
|
|
|
270
273
|
public findParentTag() {
|
|
271
|
-
let parentElement: HTMLElement = DOM.getParentElement(this.element);
|
|
272
274
|
let foundParent = false;
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
275
|
+
if (this.element) {
|
|
276
|
+
let parentElement: HTMLElement = DOM.getParentElement(this.element);
|
|
277
|
+
while (parentElement) {
|
|
278
|
+
if (parentElement[Tag.TaggedVariable]) {
|
|
279
|
+
foundParent = true;
|
|
280
|
+
this.parentTag = parentElement[Tag.TaggedVariable];
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
parentElement = DOM.getParentElement(parentElement);
|
|
278
284
|
}
|
|
279
|
-
parentElement = DOM.getParentElement(parentElement);
|
|
280
285
|
}
|
|
281
|
-
|
|
282
286
|
if (!foundParent && DOM.instance.root !== this)
|
|
283
287
|
return DOM.instance.root;
|
|
284
288
|
}
|
|
@@ -292,7 +296,7 @@ export class Tag extends DOMObject {
|
|
|
292
296
|
}
|
|
293
297
|
|
|
294
298
|
public set parentTag(tag: Tag) {
|
|
295
|
-
if (this.element === document.body)
|
|
299
|
+
if (this.element === document.body || tag.element === document.body)
|
|
296
300
|
return;
|
|
297
301
|
|
|
298
302
|
if (this._parentTag && this._parentTag !== tag) {
|
|
@@ -320,7 +324,7 @@ export class Tag extends DOMObject {
|
|
|
320
324
|
if (!!this.parentTag)
|
|
321
325
|
return this.parentTag.scope;
|
|
322
326
|
|
|
323
|
-
return
|
|
327
|
+
return DOM.instance.root.scope;
|
|
324
328
|
}
|
|
325
329
|
|
|
326
330
|
public get controller(): Controller {
|
|
@@ -806,6 +810,11 @@ export class Tag extends DOMObject {
|
|
|
806
810
|
this._controller.deconstruct();
|
|
807
811
|
this._controller = null;
|
|
808
812
|
}
|
|
813
|
+
if (this.element) {
|
|
814
|
+
this.element[Tag.TaggedVariable] = null;
|
|
815
|
+
(this as any).element = null;
|
|
816
|
+
}
|
|
817
|
+
this._parentTag = null;
|
|
809
818
|
super.deconstruct();
|
|
810
819
|
}
|
|
811
820
|
}
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = '0.1.
|
|
1
|
+
export const VERSION = '0.1.133';
|
|
2
2
|
|
|
@@ -52,13 +52,13 @@ describe('ClassNode', () => {
|
|
|
52
52
|
<script type="text/vsn" vsn-script>
|
|
53
53
|
class .simple-construct {
|
|
54
54
|
func construct() {
|
|
55
|
-
a|integer = "15";
|
|
56
|
-
log('####### construct', a);
|
|
55
|
+
this.a|integer = "15";
|
|
56
|
+
log('####### construct', this.a);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
func test() {
|
|
60
|
-
a += 1;
|
|
61
|
-
log('####### testing', a);
|
|
60
|
+
this.a += 1;
|
|
61
|
+
log('####### testing', this.a);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
</script>
|
|
@@ -82,7 +82,7 @@ describe('ClassNode', () => {
|
|
|
82
82
|
<script type="text/vsn" vsn-script>
|
|
83
83
|
class .testing {
|
|
84
84
|
func construct() {
|
|
85
|
-
a|integer = 0;
|
|
85
|
+
this.a|integer = 0;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
class .test {
|