spikijs 1.0.6 → 1.0.7
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/README.md +1 -1
- package/package.json +11 -1
- package/spiki.esm.js +394 -285
- package/spiki.esm.min.js +1 -1
- package/spiki.js +393 -284
- package/spiki.min.js +1 -1
package/spiki.js
CHANGED
|
@@ -1,459 +1,568 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
|
-
var spiki = (
|
|
5
|
-
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
4
|
+
var spiki = (() => {
|
|
5
|
+
// --- State & Storage ---
|
|
6
|
+
var componentRegistry = Object.create(null);
|
|
7
|
+
var eventMetadataMap = new WeakMap();
|
|
8
|
+
var dependencyMap = new WeakMap();
|
|
9
|
+
var proxyCache = new WeakMap();
|
|
10
|
+
var pathSplitCache = new Map();
|
|
11
|
+
var schedulerQueue = new Set();
|
|
12
|
+
|
|
13
|
+
var loopRegex = /^\s*(.*?)\s+in\s+(.+)\s*$/;
|
|
14
|
+
|
|
15
|
+
// --- Global State Variables ---
|
|
16
|
+
var currentActiveEffect;
|
|
17
|
+
var isFlushingQueue;
|
|
18
|
+
var globalStore;
|
|
19
|
+
var shouldTriggerEffects = true;
|
|
20
|
+
var resolvedPromise = Promise.resolve();
|
|
21
|
+
|
|
22
|
+
// -------------------------------------------------------------------------
|
|
17
23
|
// 1. Array Interceptors
|
|
24
|
+
// -------------------------------------------------------------------------
|
|
18
25
|
var arrayInstrumentations = {};
|
|
19
|
-
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(
|
|
20
|
-
arrayInstrumentations[
|
|
26
|
+
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(methodName => {
|
|
27
|
+
arrayInstrumentations[methodName] = function () {
|
|
21
28
|
var args = [];
|
|
22
|
-
for (var
|
|
23
|
-
args[
|
|
29
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
30
|
+
args[i] = arguments[i];
|
|
24
31
|
}
|
|
25
|
-
|
|
32
|
+
|
|
33
|
+
shouldTriggerEffects = false;
|
|
26
34
|
try {
|
|
27
|
-
var
|
|
28
|
-
return
|
|
35
|
+
var result = Array.prototype[methodName].apply(this, args);
|
|
36
|
+
return result;
|
|
29
37
|
} finally {
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
shouldTriggerEffects = true;
|
|
39
|
+
triggerDependency(this, 'length');
|
|
32
40
|
}
|
|
33
41
|
};
|
|
34
42
|
});
|
|
35
43
|
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
// -------------------------------------------------------------------------
|
|
45
|
+
// 2. Helper Functions
|
|
46
|
+
// -------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
var createScope = (parentScope) => {
|
|
49
|
+
var proto = Object.create(parentScope);
|
|
39
50
|
return new Proxy(proto, {
|
|
40
|
-
set:
|
|
41
|
-
if (target.hasOwnProperty(key))
|
|
51
|
+
set: (target, key, value, receiver) => {
|
|
52
|
+
if (target.hasOwnProperty(key)) {
|
|
53
|
+
return Reflect.set(target, key, value, receiver);
|
|
54
|
+
}
|
|
55
|
+
|
|
42
56
|
var cursor = target;
|
|
43
57
|
while (cursor && !Object.prototype.hasOwnProperty.call(cursor, key)) {
|
|
44
58
|
cursor = Object.getPrototypeOf(cursor);
|
|
45
59
|
}
|
|
60
|
+
|
|
46
61
|
return Reflect.set(cursor || target, key, value);
|
|
47
62
|
}
|
|
48
63
|
});
|
|
49
64
|
};
|
|
50
65
|
|
|
51
|
-
var
|
|
52
|
-
if (typeof path !== 'string') return {
|
|
66
|
+
var evaluatePath = (scope, path) => {
|
|
67
|
+
if (typeof path !== 'string') return { value: path, context: scope };
|
|
53
68
|
|
|
54
69
|
if (path.indexOf('.') === -1) {
|
|
55
|
-
return {
|
|
70
|
+
return { value: scope ? scope[path] : undefined, context: scope };
|
|
56
71
|
}
|
|
57
72
|
|
|
58
|
-
var parts =
|
|
73
|
+
var parts = pathSplitCache.get(path);
|
|
59
74
|
if (!parts) {
|
|
60
|
-
if (
|
|
75
|
+
if (pathSplitCache.size > 1000) pathSplitCache.clear();
|
|
61
76
|
parts = path.split('.');
|
|
62
|
-
|
|
77
|
+
pathSplitCache.set(path, parts);
|
|
63
78
|
}
|
|
64
79
|
|
|
65
|
-
var
|
|
80
|
+
var currentValue = scope;
|
|
81
|
+
var currentContext = scope;
|
|
82
|
+
|
|
66
83
|
for (var i = 0; i < parts.length; i++) {
|
|
67
84
|
var part = parts[i];
|
|
68
|
-
if (
|
|
69
|
-
return {
|
|
85
|
+
if (currentValue == null) {
|
|
86
|
+
return { value: currentValue, context: null };
|
|
70
87
|
}
|
|
71
|
-
|
|
72
|
-
|
|
88
|
+
currentContext = currentValue;
|
|
89
|
+
currentValue = currentValue[part];
|
|
73
90
|
}
|
|
74
|
-
return {
|
|
91
|
+
return { value: currentValue, context: currentContext };
|
|
75
92
|
};
|
|
76
93
|
|
|
77
|
-
var nextTick =
|
|
78
|
-
return !
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
94
|
+
var nextTick = (fn) => {
|
|
95
|
+
return !schedulerQueue.has(fn) &&
|
|
96
|
+
schedulerQueue.add(fn) &&
|
|
97
|
+
!isFlushingQueue &&
|
|
98
|
+
(isFlushingQueue = true) &&
|
|
99
|
+
resolvedPromise.then(() => {
|
|
100
|
+
schedulerQueue.forEach(job => job());
|
|
101
|
+
schedulerQueue.clear();
|
|
102
|
+
isFlushingQueue = false;
|
|
103
|
+
});
|
|
84
104
|
};
|
|
85
105
|
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
106
|
+
// -------------------------------------------------------------------------
|
|
107
|
+
// 3. Reactivity System
|
|
108
|
+
// -------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
var trackDependency = (target, key) => {
|
|
111
|
+
if (!currentActiveEffect) return;
|
|
112
|
+
|
|
113
|
+
var depsMap = dependencyMap.get(target);
|
|
114
|
+
if (!depsMap) {
|
|
115
|
+
depsMap = new Map();
|
|
116
|
+
dependencyMap.set(target, depsMap);
|
|
93
117
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
118
|
+
|
|
119
|
+
var depSet = depsMap.get(key);
|
|
120
|
+
if (!depSet) {
|
|
121
|
+
depSet = new Set();
|
|
122
|
+
depsMap.set(key, depSet);
|
|
98
123
|
}
|
|
99
|
-
|
|
100
|
-
|
|
124
|
+
|
|
125
|
+
depSet.add(currentActiveEffect);
|
|
126
|
+
currentActiveEffect.dependencies.add(depSet);
|
|
101
127
|
};
|
|
102
128
|
|
|
103
|
-
var
|
|
104
|
-
var depsMap,
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
|
|
129
|
+
var triggerDependency = (target, key) => {
|
|
130
|
+
var depsMap, depSet;
|
|
131
|
+
if (shouldTriggerEffects && (depsMap = dependencyMap.get(target)) && (depSet = depsMap.get(key))) {
|
|
132
|
+
depSet.forEach(effectFn => {
|
|
133
|
+
effectFn.scheduler ? effectFn.scheduler(effectFn) : effectFn();
|
|
108
134
|
});
|
|
109
135
|
}
|
|
110
136
|
};
|
|
111
137
|
|
|
112
|
-
var
|
|
113
|
-
var runner =
|
|
114
|
-
runner.
|
|
115
|
-
runner.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
138
|
+
var createEffect = (fn, scheduler) => {
|
|
139
|
+
var runner = () => {
|
|
140
|
+
runner.dependencies.forEach(depSet => depSet.delete(runner));
|
|
141
|
+
runner.dependencies.clear();
|
|
142
|
+
|
|
143
|
+
var previousEffect = currentActiveEffect;
|
|
144
|
+
currentActiveEffect = runner;
|
|
145
|
+
try {
|
|
146
|
+
fn();
|
|
147
|
+
} finally {
|
|
148
|
+
currentActiveEffect = previousEffect;
|
|
149
|
+
}
|
|
119
150
|
};
|
|
120
|
-
|
|
121
|
-
runner.
|
|
151
|
+
|
|
152
|
+
runner.dependencies = new Set();
|
|
153
|
+
runner.scheduler = scheduler;
|
|
122
154
|
runner();
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
runner.
|
|
126
|
-
|
|
155
|
+
|
|
156
|
+
return () => {
|
|
157
|
+
runner.dependencies.forEach(depSet => depSet.delete(runner));
|
|
158
|
+
runner.dependencies.clear();
|
|
159
|
+
schedulerQueue.delete(runner);
|
|
127
160
|
};
|
|
128
161
|
};
|
|
129
162
|
|
|
130
|
-
var
|
|
131
|
-
if (!obj || typeof obj !== 'object' || obj.
|
|
132
|
-
|
|
133
|
-
|
|
163
|
+
var makeReactive = (obj) => {
|
|
164
|
+
if (!obj || typeof obj !== 'object' || obj.__isProxy || obj instanceof Node) return obj;
|
|
165
|
+
|
|
166
|
+
var existingProxy = proxyCache.get(obj);
|
|
167
|
+
if (existingProxy) return existingProxy;
|
|
134
168
|
|
|
135
169
|
var proxy = new Proxy(obj, {
|
|
136
|
-
get:
|
|
137
|
-
if (
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
170
|
+
get: (target, key, receiver) => {
|
|
171
|
+
if (key === '__raw') return target;
|
|
172
|
+
if (key === '__isProxy') return true;
|
|
173
|
+
|
|
174
|
+
if (Array.isArray(target) && arrayInstrumentations.hasOwnProperty(key)) {
|
|
175
|
+
return arrayInstrumentations[key];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
trackDependency(target, key);
|
|
179
|
+
|
|
180
|
+
var result = Reflect.get(target, key, receiver);
|
|
181
|
+
return result && typeof result === 'object' && !(result instanceof Node)
|
|
182
|
+
? makeReactive(result)
|
|
183
|
+
: result;
|
|
142
184
|
},
|
|
143
|
-
set:
|
|
144
|
-
var
|
|
145
|
-
var hadKey = Array.isArray(
|
|
146
|
-
|
|
147
|
-
|
|
185
|
+
set: (target, key, value, receiver) => {
|
|
186
|
+
var oldValue = target[key];
|
|
187
|
+
var hadKey = Array.isArray(target)
|
|
188
|
+
? Number(key) < target.length
|
|
189
|
+
: Object.prototype.hasOwnProperty.call(target, key);
|
|
190
|
+
|
|
191
|
+
var result = Reflect.set(target, key, value, receiver);
|
|
192
|
+
|
|
193
|
+
if (shouldTriggerEffects) {
|
|
148
194
|
if (!hadKey) {
|
|
149
|
-
|
|
150
|
-
if (Array.isArray(
|
|
151
|
-
} else if (
|
|
152
|
-
|
|
195
|
+
triggerDependency(target, key);
|
|
196
|
+
if (Array.isArray(target)) triggerDependency(target, 'length');
|
|
197
|
+
} else if (oldValue !== value) {
|
|
198
|
+
triggerDependency(target, key);
|
|
153
199
|
}
|
|
154
200
|
}
|
|
155
|
-
return
|
|
201
|
+
return result;
|
|
156
202
|
},
|
|
157
|
-
deleteProperty:
|
|
158
|
-
var hadKey = Object.prototype.hasOwnProperty.call(
|
|
159
|
-
var
|
|
160
|
-
if (
|
|
161
|
-
|
|
162
|
-
if (Array.isArray(
|
|
203
|
+
deleteProperty: (target, key) => {
|
|
204
|
+
var hadKey = Object.prototype.hasOwnProperty.call(target, key);
|
|
205
|
+
var result = Reflect.deleteProperty(target, key);
|
|
206
|
+
if (result && hadKey) {
|
|
207
|
+
triggerDependency(target, key);
|
|
208
|
+
if (Array.isArray(target)) triggerDependency(target, 'length');
|
|
163
209
|
}
|
|
164
|
-
return
|
|
210
|
+
return result;
|
|
165
211
|
}
|
|
166
212
|
});
|
|
167
|
-
|
|
213
|
+
|
|
214
|
+
proxyCache.set(obj, proxy);
|
|
168
215
|
return proxy;
|
|
169
216
|
};
|
|
170
217
|
|
|
171
|
-
globalStore =
|
|
218
|
+
globalStore = makeReactive({});
|
|
172
219
|
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
220
|
+
// -------------------------------------------------------------------------
|
|
221
|
+
// 4. DOM Operations
|
|
222
|
+
// -------------------------------------------------------------------------
|
|
223
|
+
var domOperations = {
|
|
224
|
+
text: (el, value) => {
|
|
225
|
+
el.textContent = (value !== null && value !== undefined) ? value : '';
|
|
226
|
+
},
|
|
227
|
+
html: (el, value) => {
|
|
228
|
+
el.innerHTML = (value !== null && value !== undefined) ? value : '';
|
|
229
|
+
},
|
|
230
|
+
value: (el, value) => {
|
|
178
231
|
if (el.type === 'checkbox') {
|
|
179
|
-
el.checked = !!
|
|
232
|
+
el.checked = !!value;
|
|
180
233
|
} else if (el.type === 'radio' && el.name) {
|
|
181
|
-
el.checked = el.value ==
|
|
234
|
+
el.checked = el.value == value;
|
|
182
235
|
} else {
|
|
183
|
-
if (el.value !=
|
|
236
|
+
if (el.value != value) {
|
|
237
|
+
el.value = (value !== null && value !== undefined) ? value : '';
|
|
238
|
+
}
|
|
184
239
|
}
|
|
185
240
|
},
|
|
186
|
-
attr:
|
|
187
|
-
(
|
|
241
|
+
attr: (el, value, attributeName) => {
|
|
242
|
+
(value == null || value === false)
|
|
243
|
+
? el.removeAttribute(attributeName)
|
|
244
|
+
: el.setAttribute(attributeName, value === true ? '' : value);
|
|
188
245
|
},
|
|
189
|
-
class:
|
|
190
|
-
if (typeof
|
|
191
|
-
|
|
192
|
-
if (
|
|
246
|
+
class: (el, value) => {
|
|
247
|
+
if (typeof value === 'string') {
|
|
248
|
+
value.split(/\s+/).forEach(cls => {
|
|
249
|
+
if (cls) {
|
|
250
|
+
var isNegative = cls[0] === '!';
|
|
251
|
+
var className = isNegative ? cls.slice(1) : cls;
|
|
252
|
+
el.classList[isNegative ? 'remove' : 'add'](className);
|
|
253
|
+
}
|
|
193
254
|
});
|
|
194
255
|
}
|
|
195
256
|
},
|
|
196
|
-
init:
|
|
197
|
-
destroy:
|
|
257
|
+
init: () => { },
|
|
258
|
+
destroy: () => { }
|
|
198
259
|
};
|
|
199
260
|
|
|
200
|
-
//
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
261
|
+
// -------------------------------------------------------------------------
|
|
262
|
+
// 5. Engine / Mounting Logic
|
|
263
|
+
// -------------------------------------------------------------------------
|
|
264
|
+
var mountComponent = (rootElement) => {
|
|
265
|
+
if (rootElement.__isMounted) return;
|
|
266
|
+
rootElement.__isMounted = 1;
|
|
267
|
+
|
|
268
|
+
var componentName = rootElement.getAttribute('s-data');
|
|
269
|
+
var componentFactory = componentRegistry[componentName];
|
|
270
|
+
if (!componentFactory) return;
|
|
206
271
|
|
|
207
|
-
var state =
|
|
272
|
+
var state = makeReactive(componentFactory());
|
|
208
273
|
state.$refs = {};
|
|
209
|
-
state.$root =
|
|
274
|
+
state.$root = rootElement;
|
|
210
275
|
state.$store = globalStore;
|
|
211
276
|
|
|
212
|
-
var
|
|
277
|
+
var cleanupCallbacks = [];
|
|
213
278
|
|
|
214
|
-
var handleEvent =
|
|
215
|
-
var
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
var
|
|
219
|
-
var
|
|
220
|
-
var
|
|
279
|
+
var handleEvent = (e) => {
|
|
280
|
+
var target = e.target;
|
|
281
|
+
|
|
282
|
+
if (target.__modelPath && (e.type === 'input' || e.type === 'change')) {
|
|
283
|
+
var path = target.__modelPath;
|
|
284
|
+
var value = target.type === 'checkbox' ? target.checked : target.value;
|
|
285
|
+
var evaluation = evaluatePath(target.__scope || state, path);
|
|
286
|
+
var parentObject = evaluation.context;
|
|
221
287
|
|
|
222
288
|
if (path.indexOf('.') === -1) {
|
|
223
|
-
(
|
|
224
|
-
} else if (
|
|
289
|
+
(target.__scope || state)[path] = value;
|
|
290
|
+
} else if (parentObject) {
|
|
225
291
|
var parts = path.split('.');
|
|
226
|
-
|
|
292
|
+
parentObject[parts[parts.length - 1]] = value;
|
|
227
293
|
}
|
|
228
294
|
}
|
|
229
295
|
|
|
230
|
-
var
|
|
231
|
-
while (
|
|
232
|
-
var meta =
|
|
233
|
-
if (meta && (
|
|
234
|
-
var
|
|
235
|
-
var
|
|
236
|
-
var
|
|
237
|
-
|
|
296
|
+
var handlerName;
|
|
297
|
+
while (target && target !== rootElement.parentNode) {
|
|
298
|
+
var meta = eventMetadataMap.get(target);
|
|
299
|
+
if (meta && (handlerName = meta[e.type])) {
|
|
300
|
+
var evalResult = evaluatePath(target.__scope || state, handlerName);
|
|
301
|
+
var handlerFn = evalResult.value;
|
|
302
|
+
var handlerContext = evalResult.context;
|
|
303
|
+
|
|
304
|
+
if (typeof handlerFn === 'function') {
|
|
305
|
+
handlerFn.call(handlerContext, e);
|
|
306
|
+
}
|
|
238
307
|
}
|
|
239
|
-
|
|
308
|
+
target = target.parentNode;
|
|
240
309
|
}
|
|
241
310
|
};
|
|
242
311
|
|
|
243
|
-
var
|
|
312
|
+
var walkDOM = (el, currentScope, cleanupList) => {
|
|
244
313
|
if (el.nodeType !== 1 || el.hasAttribute('s-ignore')) return;
|
|
245
314
|
|
|
246
|
-
if (el !==
|
|
247
|
-
var
|
|
248
|
-
if (
|
|
315
|
+
if (el !== rootElement && el.hasAttribute('s-data')) {
|
|
316
|
+
var childComponent = mountComponent(el);
|
|
317
|
+
if (childComponent) cleanupList.push(childComponent.unmount);
|
|
249
318
|
return;
|
|
250
319
|
}
|
|
251
320
|
|
|
252
|
-
var
|
|
253
|
-
|
|
321
|
+
var attributeValue;
|
|
322
|
+
|
|
323
|
+
if ((attributeValue = el.getAttribute('s-if'))) {
|
|
254
324
|
var anchor = document.createTextNode('');
|
|
255
|
-
var
|
|
325
|
+
var branchCleanups = [];
|
|
256
326
|
el.replaceWith(anchor);
|
|
257
|
-
var
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
var
|
|
265
|
-
var
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
327
|
+
var activeNode;
|
|
328
|
+
|
|
329
|
+
cleanupList.push(() => {
|
|
330
|
+
branchCleanups.forEach(cb => cb());
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
return cleanupList.push(createEffect(() => {
|
|
334
|
+
var evaluation = evaluatePath(currentScope, attributeValue);
|
|
335
|
+
var result = evaluation.value;
|
|
336
|
+
var context = evaluation.context;
|
|
337
|
+
|
|
338
|
+
var isTruthy = typeof result === 'function' ? result.call(context, el) : result;
|
|
339
|
+
|
|
340
|
+
if (isTruthy) {
|
|
341
|
+
if (!activeNode) {
|
|
342
|
+
activeNode = el.cloneNode(true);
|
|
343
|
+
activeNode.removeAttribute('s-if');
|
|
344
|
+
walkDOM(activeNode, currentScope, branchCleanups);
|
|
345
|
+
anchor.parentNode.insertBefore(activeNode, anchor);
|
|
273
346
|
}
|
|
274
|
-
} else if (
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
347
|
+
} else if (activeNode) {
|
|
348
|
+
branchCleanups.forEach(cb => cb());
|
|
349
|
+
branchCleanups.length = 0;
|
|
350
|
+
activeNode.remove();
|
|
351
|
+
activeNode = null;
|
|
279
352
|
}
|
|
280
353
|
}, nextTick));
|
|
281
354
|
}
|
|
282
355
|
|
|
283
|
-
if (el.tagName === 'TEMPLATE' && (
|
|
284
|
-
var match =
|
|
356
|
+
if (el.tagName === 'TEMPLATE' && (attributeValue = el.getAttribute('s-for'))) {
|
|
357
|
+
var match = attributeValue.match(loopRegex);
|
|
285
358
|
if (!match) return;
|
|
286
|
-
|
|
359
|
+
|
|
360
|
+
var leftHandSide = match[1].replace(/[()]/g, '');
|
|
287
361
|
var listKey = match[2];
|
|
288
|
-
var splitLhs =
|
|
289
|
-
var
|
|
290
|
-
var
|
|
291
|
-
|
|
292
|
-
var
|
|
293
|
-
var
|
|
294
|
-
el.replaceWith(
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
362
|
+
var splitLhs = leftHandSide.split(',');
|
|
363
|
+
var itemAlias = splitLhs[0].trim();
|
|
364
|
+
var indexAlias = splitLhs[1] ? splitLhs[1].trim() : null;
|
|
365
|
+
|
|
366
|
+
var keyAttribute = el.getAttribute('s-key');
|
|
367
|
+
var anchorForLoop = document.createTextNode('');
|
|
368
|
+
el.replaceWith(anchorForLoop);
|
|
369
|
+
|
|
370
|
+
var nodePool = new Map();
|
|
371
|
+
|
|
372
|
+
cleanupList.push(() => {
|
|
373
|
+
nodePool.forEach(row => {
|
|
374
|
+
row.cleanups.forEach(cb => cb());
|
|
300
375
|
});
|
|
301
376
|
});
|
|
302
377
|
|
|
303
|
-
return
|
|
304
|
-
var
|
|
305
|
-
var rawItems =
|
|
378
|
+
return cleanupList.push(createEffect(() => {
|
|
379
|
+
var evaluation = evaluatePath(currentScope, listKey);
|
|
380
|
+
var rawItems = evaluation.value;
|
|
306
381
|
var items = rawItems;
|
|
307
|
-
|
|
382
|
+
|
|
383
|
+
if (Array.isArray(items)) trackDependency(items, 'length');
|
|
308
384
|
|
|
309
|
-
var
|
|
385
|
+
var domCursor = anchorForLoop;
|
|
310
386
|
var iterable = Array.isArray(items) ? items : items ? Object.keys(items) : [];
|
|
311
|
-
var
|
|
387
|
+
var nextNodePool = new Map();
|
|
312
388
|
|
|
313
|
-
iterable.forEach(
|
|
314
|
-
var key = Array.isArray(items) ?
|
|
315
|
-
var
|
|
389
|
+
iterable.forEach((rawItem, index) => {
|
|
390
|
+
var key = Array.isArray(items) ? index : rawItem;
|
|
391
|
+
var itemValue = Array.isArray(items) ? rawItem : items[rawItem];
|
|
316
392
|
|
|
317
|
-
var
|
|
318
|
-
if (
|
|
319
|
-
else
|
|
393
|
+
var rowUniqueKey;
|
|
394
|
+
if (keyAttribute && itemValue) rowUniqueKey = itemValue[keyAttribute];
|
|
395
|
+
else rowUniqueKey = (typeof itemValue === 'object' && itemValue)
|
|
396
|
+
? itemValue
|
|
397
|
+
: key + '_' + itemValue;
|
|
320
398
|
|
|
321
|
-
var row =
|
|
399
|
+
var row = nodePool.get(rowUniqueKey);
|
|
322
400
|
|
|
323
|
-
var defineAlias =
|
|
324
|
-
Object.defineProperty(targetObj,
|
|
401
|
+
var defineAlias = (targetObj) => {
|
|
402
|
+
Object.defineProperty(targetObj, itemAlias, {
|
|
325
403
|
configurable: true, enumerable: true,
|
|
326
|
-
get:
|
|
327
|
-
set:
|
|
404
|
+
get: () => items[key],
|
|
405
|
+
set: (v) => { items[key] = v; }
|
|
328
406
|
});
|
|
329
407
|
};
|
|
330
408
|
|
|
331
409
|
if (!row) {
|
|
332
410
|
var clone = el.content.cloneNode(true);
|
|
333
|
-
var
|
|
334
|
-
var
|
|
335
|
-
|
|
336
|
-
defineAlias(
|
|
337
|
-
if (
|
|
338
|
-
|
|
339
|
-
var
|
|
340
|
-
var
|
|
341
|
-
while (
|
|
342
|
-
|
|
343
|
-
var
|
|
344
|
-
|
|
345
|
-
|
|
411
|
+
var rowScope = createScope(currentScope);
|
|
412
|
+
var rowCleanups = [];
|
|
413
|
+
|
|
414
|
+
defineAlias(rowScope);
|
|
415
|
+
if (indexAlias) rowScope[indexAlias] = key;
|
|
416
|
+
|
|
417
|
+
var rowNodes = [];
|
|
418
|
+
var childNode = clone.firstChild;
|
|
419
|
+
while (childNode) {
|
|
420
|
+
rowNodes.push(childNode);
|
|
421
|
+
var nextSibling = childNode.nextSibling;
|
|
422
|
+
walkDOM(childNode, rowScope, rowCleanups);
|
|
423
|
+
childNode = nextSibling;
|
|
346
424
|
}
|
|
347
|
-
row = {
|
|
425
|
+
row = { nodes: rowNodes, scope: rowScope, cleanups: rowCleanups };
|
|
348
426
|
} else {
|
|
349
|
-
defineAlias(row.
|
|
350
|
-
if (
|
|
427
|
+
defineAlias(row.scope);
|
|
428
|
+
if (indexAlias) row.scope[indexAlias] = key;
|
|
351
429
|
}
|
|
352
430
|
|
|
353
|
-
if (row.
|
|
354
|
-
var
|
|
355
|
-
row.
|
|
356
|
-
|
|
431
|
+
if (row.nodes[0] !== domCursor.nextSibling) {
|
|
432
|
+
var fragment = document.createDocumentFragment();
|
|
433
|
+
row.nodes.forEach(n => fragment.appendChild(n));
|
|
434
|
+
domCursor.parentNode.insertBefore(fragment, domCursor.nextSibling);
|
|
357
435
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
436
|
+
|
|
437
|
+
domCursor = row.nodes[row.nodes.length - 1];
|
|
438
|
+
nextNodePool.set(rowUniqueKey, row);
|
|
439
|
+
nodePool.delete(rowUniqueKey);
|
|
361
440
|
});
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
row.
|
|
441
|
+
|
|
442
|
+
nodePool.forEach(row => {
|
|
443
|
+
row.cleanups.forEach(cb => cb());
|
|
444
|
+
row.nodes.forEach(n => n.remove());
|
|
365
445
|
});
|
|
366
|
-
|
|
446
|
+
nodePool = nextNodePool;
|
|
367
447
|
}, nextTick));
|
|
368
448
|
}
|
|
369
449
|
|
|
370
|
-
var
|
|
371
|
-
for (var i =
|
|
372
|
-
(
|
|
450
|
+
var attributes = el.attributes;
|
|
451
|
+
for (var i = attributes.length - 1; i >= 0; i--) {
|
|
452
|
+
((attr) => {
|
|
373
453
|
var name = attr.name;
|
|
374
454
|
var value = attr.value;
|
|
375
455
|
|
|
376
456
|
if (name[0] === ':') {
|
|
377
|
-
|
|
378
|
-
var
|
|
379
|
-
var
|
|
380
|
-
var
|
|
381
|
-
|
|
457
|
+
cleanupList.push(createEffect(() => {
|
|
458
|
+
var evaluation = evaluatePath(currentScope, value);
|
|
459
|
+
var result = evaluation.value;
|
|
460
|
+
var context = evaluation.context;
|
|
461
|
+
var opName = name.slice(1) === 'class' ? 'class' : 'attr';
|
|
462
|
+
|
|
463
|
+
domOperations[opName](
|
|
464
|
+
el,
|
|
465
|
+
typeof result === 'function' ? result.call(context, el) : result,
|
|
466
|
+
name.slice(1)
|
|
467
|
+
);
|
|
382
468
|
}, nextTick));
|
|
383
469
|
|
|
384
470
|
} else if (name[0] === 's' && name[1] === '-') {
|
|
385
|
-
var
|
|
386
|
-
|
|
471
|
+
var directiveType = name.slice(2);
|
|
472
|
+
|
|
473
|
+
if (directiveType === 'ref') {
|
|
387
474
|
state.$refs[value] = el;
|
|
388
|
-
} else if (
|
|
389
|
-
|
|
390
|
-
var
|
|
391
|
-
|
|
475
|
+
} else if (directiveType === 'model') {
|
|
476
|
+
cleanupList.push(createEffect(() => {
|
|
477
|
+
var evaluation = evaluatePath(currentScope, value);
|
|
478
|
+
domOperations.value(el, evaluation.value);
|
|
392
479
|
}, nextTick));
|
|
480
|
+
|
|
393
481
|
if (/^(INPUT|SELECT|TEXTAREA)$/.test(el.tagName)) {
|
|
394
|
-
el.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
482
|
+
el.__scope = currentScope;
|
|
483
|
+
el.__modelPath = value;
|
|
484
|
+
var eventType = (el.type === 'checkbox' || el.type === 'radio' || el.tagName === 'SELECT')
|
|
485
|
+
? 'change'
|
|
486
|
+
: 'input';
|
|
487
|
+
|
|
488
|
+
if (!rootElement.__listeningEvents) rootElement.__listeningEvents = new Set();
|
|
489
|
+
if (!rootElement.__listeningEvents.has(eventType)) {
|
|
490
|
+
rootElement.__listeningEvents.add(eventType);
|
|
491
|
+
rootElement.addEventListener(eventType, handleEvent);
|
|
400
492
|
}
|
|
401
493
|
}
|
|
402
|
-
} else if (
|
|
403
|
-
|
|
404
|
-
var
|
|
405
|
-
var
|
|
406
|
-
var
|
|
407
|
-
|
|
494
|
+
} else if (domOperations[directiveType]) {
|
|
495
|
+
cleanupList.push(createEffect(() => {
|
|
496
|
+
var evaluation = evaluatePath(currentScope, value);
|
|
497
|
+
var result = evaluation.value;
|
|
498
|
+
var context = evaluation.context;
|
|
499
|
+
domOperations[directiveType](
|
|
500
|
+
el,
|
|
501
|
+
typeof result === 'function' ? result.call(context, el) : result
|
|
502
|
+
);
|
|
408
503
|
}, nextTick));
|
|
409
504
|
} else {
|
|
410
|
-
el.
|
|
411
|
-
var meta =
|
|
505
|
+
el.__scope = currentScope;
|
|
506
|
+
var meta = eventMetadataMap.get(el);
|
|
412
507
|
if (!meta) {
|
|
413
508
|
meta = {};
|
|
414
|
-
|
|
509
|
+
eventMetadataMap.set(el, meta);
|
|
415
510
|
}
|
|
416
|
-
meta[
|
|
417
|
-
|
|
418
|
-
if (!
|
|
419
|
-
|
|
420
|
-
|
|
511
|
+
meta[directiveType] = value;
|
|
512
|
+
|
|
513
|
+
if (!rootElement.__listeningEvents) rootElement.__listeningEvents = new Set();
|
|
514
|
+
if (!rootElement.__listeningEvents.has(directiveType)) {
|
|
515
|
+
rootElement.__listeningEvents.add(directiveType);
|
|
516
|
+
rootElement.addEventListener(directiveType, handleEvent);
|
|
421
517
|
}
|
|
422
518
|
}
|
|
423
519
|
}
|
|
424
|
-
})(
|
|
520
|
+
})(attributes[i]);
|
|
425
521
|
}
|
|
426
522
|
|
|
427
523
|
var child = el.firstElementChild;
|
|
428
524
|
while (child) {
|
|
429
525
|
var next = child.nextElementSibling;
|
|
430
|
-
|
|
526
|
+
walkDOM(child, currentScope, cleanupList);
|
|
431
527
|
child = next;
|
|
432
528
|
}
|
|
433
529
|
};
|
|
434
530
|
|
|
435
|
-
|
|
531
|
+
walkDOM(rootElement, state, cleanupCallbacks);
|
|
436
532
|
if (state.init) state.init();
|
|
437
533
|
|
|
438
534
|
return {
|
|
439
|
-
unmount:
|
|
535
|
+
unmount: () => {
|
|
440
536
|
if (state.destroy) state.destroy.call(state);
|
|
441
|
-
|
|
442
|
-
if (
|
|
443
|
-
|
|
537
|
+
cleanupCallbacks.forEach(cb => cb());
|
|
538
|
+
if (rootElement.__listeningEvents) {
|
|
539
|
+
rootElement.__listeningEvents.forEach(evt => {
|
|
540
|
+
rootElement.removeEventListener(evt, handleEvent);
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
rootElement.__isMounted = 0;
|
|
444
544
|
}
|
|
445
545
|
};
|
|
446
546
|
};
|
|
447
547
|
|
|
448
548
|
return {
|
|
449
|
-
data:
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
549
|
+
data: (name, factoryFn) => {
|
|
550
|
+
componentRegistry[name] = factoryFn;
|
|
551
|
+
},
|
|
552
|
+
start: () => {
|
|
553
|
+
var elements = document.querySelectorAll('[s-data]');
|
|
554
|
+
for (var i = 0; i < elements.length; i++) {
|
|
555
|
+
mountComponent(elements[i]);
|
|
454
556
|
}
|
|
455
557
|
},
|
|
456
|
-
store:
|
|
558
|
+
store: (key, value) => {
|
|
559
|
+
return value === undefined
|
|
560
|
+
? globalStore[key]
|
|
561
|
+
: (globalStore[key] = value);
|
|
562
|
+
},
|
|
563
|
+
raw: (obj) => {
|
|
564
|
+
return (obj && obj.__raw) || obj;
|
|
565
|
+
}
|
|
457
566
|
};
|
|
458
567
|
})();
|
|
459
568
|
|