mancha 0.7.3 → 0.8.1
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 +27 -11
- package/dist/cli.js +1 -1
- package/dist/core.d.ts +2 -36
- package/dist/core.js +5 -83
- package/dist/css_gen_utils.js +9 -9
- package/dist/dome.d.ts +2 -0
- package/dist/dome.js +11 -0
- package/dist/mancha.js +1 -1
- package/dist/plugins.js +92 -91
- package/dist/store.d.ts +50 -0
- package/dist/store.js +182 -0
- package/package.json +2 -2
- package/yarn-error.log +2069 -1064
- package/dist/reactive.d.ts +0 -82
- package/dist/reactive.js +0 -255
package/dist/reactive.d.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
type ProxyValueListener<T> = (curr: T | null, prev: T | null) => any | Promise<any>;
|
|
2
|
-
type ProxyStoreListener = (...values: any[]) => any | Promise<any>;
|
|
3
|
-
declare abstract class IDebouncer {
|
|
4
|
-
timeouts: Map<Function, ReturnType<typeof setTimeout>>;
|
|
5
|
-
debounce<T>(millis: number, callback: () => T | Promise<T>): Promise<T>;
|
|
6
|
-
}
|
|
7
|
-
/** Default debouncer time in millis. */
|
|
8
|
-
export declare const REACTIVE_DEBOUNCE_MILLIS = 10;
|
|
9
|
-
export declare function proxifyObject<T extends object>(obj: T, callback: () => void): T;
|
|
10
|
-
export declare class ReactiveProxy<T> extends IDebouncer {
|
|
11
|
-
private value;
|
|
12
|
-
private listeners;
|
|
13
|
-
protected constructor(value?: T | null, ...listeners: ProxyValueListener<T>[]);
|
|
14
|
-
static from<T>(value: T | ReactiveProxy<T>, ...listeners: ProxyValueListener<T>[]): ReactiveProxy<T>;
|
|
15
|
-
private wrapObjValue;
|
|
16
|
-
get(): T | null;
|
|
17
|
-
set(value: T | null): Promise<void>;
|
|
18
|
-
watch(listener: ProxyValueListener<T>): void;
|
|
19
|
-
unwatch(listener: ProxyValueListener<T>): void;
|
|
20
|
-
trigger(prev?: T | null): Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
export declare class InertProxy<T> extends ReactiveProxy<T> {
|
|
23
|
-
static from<T>(value: T | InertProxy<T>, ...listeners: ProxyValueListener<T>[]): InertProxy<T>;
|
|
24
|
-
watch(_: ProxyValueListener<T>): void;
|
|
25
|
-
trigger(_?: T | null): Promise<void>;
|
|
26
|
-
}
|
|
27
|
-
export declare class ReactiveProxyStore extends IDebouncer {
|
|
28
|
-
protected readonly store: Map<string, ReactiveProxy<any>>;
|
|
29
|
-
protected readonly debouncedListeners: Map<Function, ProxyValueListener<any>>;
|
|
30
|
-
lock: Promise<void>;
|
|
31
|
-
constructor(data?: {
|
|
32
|
-
[key: string]: any;
|
|
33
|
-
});
|
|
34
|
-
private wrapFnValue;
|
|
35
|
-
get $(): ReactiveProxyStore & {
|
|
36
|
-
[key: string]: any;
|
|
37
|
-
};
|
|
38
|
-
entries(): IterableIterator<[string, ReactiveProxy<any>]>;
|
|
39
|
-
get<K extends string>(key: K): any;
|
|
40
|
-
set<K extends string>(key: K, value: any): Promise<void>;
|
|
41
|
-
del<K extends string>(key: K): boolean;
|
|
42
|
-
has<K extends string>(key: K): boolean;
|
|
43
|
-
/**
|
|
44
|
-
* Updates the internal store with the provided data.
|
|
45
|
-
* @param data data to add to the internal store.
|
|
46
|
-
*/
|
|
47
|
-
update(data: {
|
|
48
|
-
[key: string]: any;
|
|
49
|
-
}): Promise<void>;
|
|
50
|
-
watch(keys: string | string[], listener: ProxyStoreListener): void;
|
|
51
|
-
unwatch(keys: string | string[], listener: ProxyStoreListener): void;
|
|
52
|
-
trigger(keys: string | string[]): Promise<void>;
|
|
53
|
-
trace<T>(callback: (this: ReactiveProxyStore & {
|
|
54
|
-
[key: string]: any;
|
|
55
|
-
}) => T | Promise<T>): Promise<[T, string[]]>;
|
|
56
|
-
/**
|
|
57
|
-
* Computes the result of `callback` and stores it as `key` in the store. If any of the other
|
|
58
|
-
* store elements referenced in `callback` change, the computed value will be updated.
|
|
59
|
-
* @param key key of the computed property
|
|
60
|
-
* @param callback function that computes property
|
|
61
|
-
*/
|
|
62
|
-
computed<T>(key: string, callback: (this: {
|
|
63
|
-
[key: string]: any;
|
|
64
|
-
}) => T | Promise<T>): Promise<void>;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Proxifies a ReactiveProxyStore object, allowing for direct access to its keys.
|
|
68
|
-
* Calls to existing methods should still work, e.g.
|
|
69
|
-
* ```
|
|
70
|
-
* const store = new ReactiveProxyStore();
|
|
71
|
-
* const proxy = proxify(store);
|
|
72
|
-
* // The following two lines are equivalent.
|
|
73
|
-
* proxy.key = "value";
|
|
74
|
-
* proxy.set("key", "value");
|
|
75
|
-
* ```
|
|
76
|
-
* @param store ReactiveProxyStore object to proxify.
|
|
77
|
-
* @returns Proxified object.
|
|
78
|
-
*/
|
|
79
|
-
export declare function proxifyStore(store: ReactiveProxyStore, callback?: (event: "get" | "set", key: string, value?: any) => void): ReactiveProxyStore & {
|
|
80
|
-
[key: string]: any;
|
|
81
|
-
};
|
|
82
|
-
export {};
|
package/dist/reactive.js
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
class IDebouncer {
|
|
2
|
-
timeouts = new Map();
|
|
3
|
-
debounce(millis, callback) {
|
|
4
|
-
return new Promise((resolve, reject) => {
|
|
5
|
-
const timeout = this.timeouts.get(callback);
|
|
6
|
-
if (timeout)
|
|
7
|
-
clearTimeout(timeout);
|
|
8
|
-
this.timeouts.set(callback, setTimeout(() => {
|
|
9
|
-
try {
|
|
10
|
-
resolve(callback());
|
|
11
|
-
this.timeouts.delete(callback);
|
|
12
|
-
}
|
|
13
|
-
catch (exc) {
|
|
14
|
-
reject(exc);
|
|
15
|
-
}
|
|
16
|
-
}, millis));
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
function isProxified(object) {
|
|
21
|
-
return object instanceof ReactiveProxy || object["__is_proxy__"];
|
|
22
|
-
}
|
|
23
|
-
/** Default debouncer time in millis. */
|
|
24
|
-
export const REACTIVE_DEBOUNCE_MILLIS = 10;
|
|
25
|
-
export function proxifyObject(obj, callback) {
|
|
26
|
-
// If this object is already a proxy or not a plain object (or array), return it as-is.
|
|
27
|
-
if (obj == null || isProxified(obj) || (obj.constructor !== Object && !Array.isArray(obj))) {
|
|
28
|
-
return obj;
|
|
29
|
-
}
|
|
30
|
-
// First, proxify any existing properties.
|
|
31
|
-
for (const key in obj) {
|
|
32
|
-
if (obj.hasOwnProperty(key) && typeof obj[key] === "object" && obj[key] != null) {
|
|
33
|
-
obj[key] = proxifyObject(obj[key], callback);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
// Then, proxify the object itself.
|
|
37
|
-
return new Proxy(obj, {
|
|
38
|
-
deleteProperty: (target, property) => {
|
|
39
|
-
if (property in target) {
|
|
40
|
-
delete target[property];
|
|
41
|
-
callback();
|
|
42
|
-
return true;
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
set: (target, prop, value, receiver) => {
|
|
49
|
-
if (typeof value === "object")
|
|
50
|
-
value = proxifyObject(value, callback);
|
|
51
|
-
const ret = Reflect.set(target, prop, value, receiver);
|
|
52
|
-
callback();
|
|
53
|
-
return ret;
|
|
54
|
-
},
|
|
55
|
-
get: (target, prop, receiver) => {
|
|
56
|
-
if (prop === "__is_proxy__")
|
|
57
|
-
return true;
|
|
58
|
-
return Reflect.get(target, prop, receiver);
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
export class ReactiveProxy extends IDebouncer {
|
|
63
|
-
value = null;
|
|
64
|
-
listeners = [];
|
|
65
|
-
constructor(value = null, ...listeners) {
|
|
66
|
-
super();
|
|
67
|
-
this.value = this.wrapObjValue(value);
|
|
68
|
-
listeners.forEach((x) => this.watch(x));
|
|
69
|
-
}
|
|
70
|
-
static from(value, ...listeners) {
|
|
71
|
-
if (value instanceof ReactiveProxy) {
|
|
72
|
-
listeners.forEach(value.watch);
|
|
73
|
-
return value;
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
return new ReactiveProxy(value, ...listeners);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
wrapObjValue(value) {
|
|
80
|
-
if (value === null || typeof value !== "object")
|
|
81
|
-
return value;
|
|
82
|
-
else
|
|
83
|
-
return proxifyObject(value, () => this.trigger());
|
|
84
|
-
}
|
|
85
|
-
get() {
|
|
86
|
-
return this.value;
|
|
87
|
-
}
|
|
88
|
-
async set(value) {
|
|
89
|
-
if (this.value !== value) {
|
|
90
|
-
const prev = this.value;
|
|
91
|
-
// Convert value to a proxy if it's an object.
|
|
92
|
-
this.value = this.wrapObjValue(value);
|
|
93
|
-
await this.trigger(prev);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
watch(listener) {
|
|
97
|
-
this.listeners.push(listener);
|
|
98
|
-
}
|
|
99
|
-
unwatch(listener) {
|
|
100
|
-
this.listeners = this.listeners.filter((x) => x !== listener);
|
|
101
|
-
}
|
|
102
|
-
trigger(prev = null) {
|
|
103
|
-
// Make a copy of the listeners, so that newly added listeners are not called.
|
|
104
|
-
const listeners = this.listeners.slice();
|
|
105
|
-
// Debounce the listeners to avoid multiple calls when the value changes rapidly.
|
|
106
|
-
return this.debounce(REACTIVE_DEBOUNCE_MILLIS, () => Promise.all(listeners.map((x) => x(this.value, prev))).then(() => { }));
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
export class InertProxy extends ReactiveProxy {
|
|
110
|
-
static from(value, ...listeners) {
|
|
111
|
-
if (value instanceof ReactiveProxy) {
|
|
112
|
-
return value;
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
return new InertProxy(value, ...listeners);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
watch(_) { }
|
|
119
|
-
trigger(_) {
|
|
120
|
-
return Promise.resolve();
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
export class ReactiveProxyStore extends IDebouncer {
|
|
124
|
-
store = new Map();
|
|
125
|
-
debouncedListeners = new Map();
|
|
126
|
-
lock = Promise.resolve();
|
|
127
|
-
constructor(data) {
|
|
128
|
-
super();
|
|
129
|
-
for (const [key, value] of Object.entries(data || {})) {
|
|
130
|
-
this.store.set(key, ReactiveProxy.from(this.wrapFnValue(value)));
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
wrapFnValue(value) {
|
|
134
|
-
if (!value || typeof value !== "function")
|
|
135
|
-
return value;
|
|
136
|
-
else
|
|
137
|
-
return (...args) => value.call(proxifyStore(this), ...args);
|
|
138
|
-
}
|
|
139
|
-
get $() {
|
|
140
|
-
return proxifyStore(this);
|
|
141
|
-
}
|
|
142
|
-
entries() {
|
|
143
|
-
return this.store.entries();
|
|
144
|
-
}
|
|
145
|
-
get(key) {
|
|
146
|
-
return this.store.get(key)?.get();
|
|
147
|
-
}
|
|
148
|
-
async set(key, value) {
|
|
149
|
-
if (this.store.has(key)) {
|
|
150
|
-
await this.store.get(key).set(this.wrapFnValue(value));
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
this.store.set(key, ReactiveProxy.from(this.wrapFnValue(value)));
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
del(key) {
|
|
157
|
-
return this.store.delete(key);
|
|
158
|
-
}
|
|
159
|
-
has(key) {
|
|
160
|
-
return this.store.has(key);
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Updates the internal store with the provided data.
|
|
164
|
-
* @param data data to add to the internal store.
|
|
165
|
-
*/
|
|
166
|
-
async update(data) {
|
|
167
|
-
await Promise.all(Object.entries(data).map(([key, value]) => this.set(key, value)));
|
|
168
|
-
}
|
|
169
|
-
watch(keys, listener) {
|
|
170
|
-
keys = Array.isArray(keys) ? keys : [keys];
|
|
171
|
-
// Ignore the listener's specific value and retrieve all current values from store.
|
|
172
|
-
const debounceFunction = () => listener(...keys.map((key) => this.store.get(key).get()));
|
|
173
|
-
// Create a wrapper listener that debounces the inner listener.
|
|
174
|
-
const debouncedListener = () => this.debounce(REACTIVE_DEBOUNCE_MILLIS, debounceFunction);
|
|
175
|
-
keys.forEach((key) => this.store.get(key).watch(debouncedListener));
|
|
176
|
-
// The caller will not have access to the wrapped listener, so to unwatch we need to store it.
|
|
177
|
-
this.debouncedListeners.set(listener, debouncedListener);
|
|
178
|
-
}
|
|
179
|
-
unwatch(keys, listener) {
|
|
180
|
-
keys = Array.isArray(keys) ? keys : [keys];
|
|
181
|
-
keys.forEach((key) => this.store.get(key).unwatch(this.debouncedListeners.get(listener)));
|
|
182
|
-
this.debouncedListeners.delete(listener);
|
|
183
|
-
}
|
|
184
|
-
async trigger(keys) {
|
|
185
|
-
keys = Array.isArray(keys) ? keys : [keys];
|
|
186
|
-
await Promise.all(keys.map((key) => this.store.get(key).trigger()));
|
|
187
|
-
}
|
|
188
|
-
async trace(callback) {
|
|
189
|
-
// Track the dependencies by adding a hook to the proxified store.
|
|
190
|
-
const dependencies = new Set();
|
|
191
|
-
const proxy = proxifyStore(this, (event, key) => {
|
|
192
|
-
if (event === "get")
|
|
193
|
-
dependencies.add(key);
|
|
194
|
-
});
|
|
195
|
-
// Execute the callback and return the result and dependencies.
|
|
196
|
-
const result = await callback.call(proxy);
|
|
197
|
-
return [result, Array.from(dependencies)];
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Computes the result of `callback` and stores it as `key` in the store. If any of the other
|
|
201
|
-
* store elements referenced in `callback` change, the computed value will be updated.
|
|
202
|
-
* @param key key of the computed property
|
|
203
|
-
* @param callback function that computes property
|
|
204
|
-
*/
|
|
205
|
-
async computed(key, callback) {
|
|
206
|
-
const [result, dependencies] = await this.trace(callback);
|
|
207
|
-
this.watch(dependencies, async () => this.set(key, await callback.call(proxifyStore(this))));
|
|
208
|
-
this.set(key, result);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Proxifies a ReactiveProxyStore object, allowing for direct access to its keys.
|
|
213
|
-
* Calls to existing methods should still work, e.g.
|
|
214
|
-
* ```
|
|
215
|
-
* const store = new ReactiveProxyStore();
|
|
216
|
-
* const proxy = proxify(store);
|
|
217
|
-
* // The following two lines are equivalent.
|
|
218
|
-
* proxy.key = "value";
|
|
219
|
-
* proxy.set("key", "value");
|
|
220
|
-
* ```
|
|
221
|
-
* @param store ReactiveProxyStore object to proxify.
|
|
222
|
-
* @returns Proxified object.
|
|
223
|
-
*/
|
|
224
|
-
export function proxifyStore(store, callback = () => { }) {
|
|
225
|
-
const keys = Array.from(store.entries()).map(([key]) => key);
|
|
226
|
-
const keyval = Object.fromEntries(keys.map((key) => [key, undefined]));
|
|
227
|
-
return new Proxy(Object.assign({}, store, keyval), {
|
|
228
|
-
get: (_, prop, receiver) => {
|
|
229
|
-
if (typeof prop === "string" && store.has(prop)) {
|
|
230
|
-
callback("get", prop);
|
|
231
|
-
return store.get(prop);
|
|
232
|
-
}
|
|
233
|
-
else if (prop === "get") {
|
|
234
|
-
// If someone calls the `get()` method, we need to wrap it so that the callback is called.
|
|
235
|
-
return (key) => {
|
|
236
|
-
callback("get", key);
|
|
237
|
-
return store.get(key);
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
return Reflect.get(store, prop, receiver);
|
|
242
|
-
}
|
|
243
|
-
},
|
|
244
|
-
set: (_, prop, value, receiver) => {
|
|
245
|
-
if (typeof prop !== "string" || prop in store) {
|
|
246
|
-
Reflect.set(store, prop, value, receiver);
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
callback("set", prop, value);
|
|
250
|
-
store.set(prop, value);
|
|
251
|
-
}
|
|
252
|
-
return true;
|
|
253
|
-
},
|
|
254
|
-
});
|
|
255
|
-
}
|