@esportsplus/reactivity 0.25.3 → 0.25.4
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/build/constants.d.ts +8 -1
- package/build/constants.js +8 -1
- package/build/index.d.ts +2 -2
- package/build/index.js +2 -2
- package/build/reactive/array.js +18 -27
- package/build/reactive/index.d.ts +14 -13
- package/build/reactive/index.js +2 -1
- package/build/system.d.ts +2 -2
- package/build/system.js +10 -10
- package/build/transformer/detector.d.ts +2 -2
- package/build/transformer/detector.js +14 -14
- package/build/transformer/index.d.ts +3 -7
- package/build/transformer/index.js +21 -39
- package/build/transformer/plugins/tsc.js +7 -2
- package/build/transformer/plugins/vite.js +7 -9
- package/build/transformer/transforms/array.d.ts +3 -3
- package/build/transformer/transforms/array.js +16 -22
- package/build/transformer/transforms/object.d.ts +3 -3
- package/build/transformer/transforms/object.js +40 -56
- package/build/transformer/transforms/primitives.d.ts +3 -3
- package/build/transformer/transforms/primitives.js +54 -112
- package/build/types.d.ts +2 -2
- package/package.json +6 -6
- package/readme.md +5 -5
- package/src/constants.ts +20 -13
- package/src/index.ts +2 -2
- package/src/reactive/array.ts +18 -32
- package/src/reactive/index.ts +18 -15
- package/src/system.ts +14 -21
- package/src/transformer/detector.ts +16 -25
- package/src/transformer/index.ts +24 -46
- package/src/transformer/plugins/tsc.ts +8 -2
- package/src/transformer/plugins/vite.ts +9 -12
- package/src/transformer/transforms/array.ts +20 -37
- package/src/transformer/transforms/object.ts +54 -78
- package/src/transformer/transforms/primitives.ts +65 -140
- package/src/types.ts +5 -3
- package/test/vite.config.ts +1 -1
- package/build/transformer/transforms/utilities.d.ts +0 -8
- package/build/transformer/transforms/utilities.js +0 -27
- package/src/transformer/transforms/utilities.ts +0 -45
- package/storage/tsc-transform-analysis-2026-01-04.md +0 -125
package/src/reactive/array.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isArray } from '@esportsplus/utilities';
|
|
2
|
-
import { read,
|
|
2
|
+
import { read, signal, write } from '~/system';
|
|
3
3
|
import { REACTIVE_ARRAY, REACTIVE_OBJECT } from '~/constants';
|
|
4
4
|
import type { Signal } from '~/types';
|
|
5
5
|
|
|
@@ -44,8 +44,10 @@ type Listener<V> = {
|
|
|
44
44
|
type Listeners = Record<string, (Listener<any> | null)[]>;
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
function
|
|
48
|
-
|
|
47
|
+
function dispose(value: unknown) {
|
|
48
|
+
if (value !== null && typeof value === 'object' && (value as any)[REACTIVE_OBJECT] === true) {
|
|
49
|
+
(value as { dispose(): void }).dispose();
|
|
50
|
+
}
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
|
|
@@ -75,7 +77,7 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
75
77
|
this[i] = value;
|
|
76
78
|
|
|
77
79
|
if (i >= super.length) {
|
|
78
|
-
|
|
80
|
+
write(this._length, i + 1);
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
this.dispatch('set', { index: i, item: value });
|
|
@@ -83,7 +85,7 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
83
85
|
|
|
84
86
|
clear() {
|
|
85
87
|
this.dispose();
|
|
86
|
-
|
|
88
|
+
write(this._length, 0);
|
|
87
89
|
this.dispatch('clear');
|
|
88
90
|
}
|
|
89
91
|
|
|
@@ -108,7 +110,7 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
if (added.length) {
|
|
111
|
-
|
|
113
|
+
write(this._length, super.length);
|
|
112
114
|
this.dispatch('concat', { items: added });
|
|
113
115
|
}
|
|
114
116
|
|
|
@@ -147,17 +149,11 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
dispose() {
|
|
150
|
-
let item;
|
|
151
|
-
|
|
152
152
|
while (this.length) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (isReactiveObject(item)) {
|
|
156
|
-
item.dispose();
|
|
157
|
-
}
|
|
153
|
+
dispose(super.pop());
|
|
158
154
|
}
|
|
159
155
|
|
|
160
|
-
|
|
156
|
+
write(this._length, 0);
|
|
161
157
|
}
|
|
162
158
|
|
|
163
159
|
on<K extends keyof Events<T>>(event: K, listener: Listener<Events<T>[K]>) {
|
|
@@ -197,11 +193,8 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
197
193
|
let item = super.pop();
|
|
198
194
|
|
|
199
195
|
if (item !== undefined) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (isReactiveObject(item)) {
|
|
203
|
-
item.dispose();
|
|
204
|
-
}
|
|
196
|
+
dispose(item);
|
|
197
|
+
write(this._length, super.length);
|
|
205
198
|
|
|
206
199
|
this.dispatch('pop', { item });
|
|
207
200
|
}
|
|
@@ -216,7 +209,7 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
216
209
|
|
|
217
210
|
let length = super.push(...items);
|
|
218
211
|
|
|
219
|
-
|
|
212
|
+
write(this._length, length);
|
|
220
213
|
this.dispatch('push', { items });
|
|
221
214
|
|
|
222
215
|
return length;
|
|
@@ -233,11 +226,8 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
233
226
|
let item = super.shift();
|
|
234
227
|
|
|
235
228
|
if (item !== undefined) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (isReactiveObject(item)) {
|
|
239
|
-
item.dispose();
|
|
240
|
-
}
|
|
229
|
+
dispose(item);
|
|
230
|
+
write(this._length, super.length);
|
|
241
231
|
|
|
242
232
|
this.dispatch('shift', { item });
|
|
243
233
|
}
|
|
@@ -294,14 +284,10 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
294
284
|
let removed = super.splice(start, deleteCount, ...items);
|
|
295
285
|
|
|
296
286
|
if (items.length > 0 || removed.length > 0) {
|
|
297
|
-
|
|
287
|
+
write(this._length, super.length);
|
|
298
288
|
|
|
299
289
|
for (let i = 0, n = removed.length; i < n; i++) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (isReactiveObject(item)) {
|
|
303
|
-
item.dispose();
|
|
304
|
-
}
|
|
290
|
+
dispose(removed[i]);
|
|
305
291
|
}
|
|
306
292
|
|
|
307
293
|
this.dispatch('splice', { deleteCount, items, start });
|
|
@@ -313,7 +299,7 @@ class ReactiveArray<T> extends Array<T> {
|
|
|
313
299
|
unshift(...items: T[]) {
|
|
314
300
|
let length = super.unshift(...items);
|
|
315
301
|
|
|
316
|
-
|
|
302
|
+
write(this._length, length);
|
|
317
303
|
this.dispatch('unshift', { items });
|
|
318
304
|
|
|
319
305
|
return length;
|
package/src/reactive/index.ts
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
import { Prettify } from '@esportsplus/utilities';
|
|
2
2
|
import { ReactiveArray } from './array';
|
|
3
|
+
import { PACKAGE } from '~/constants';
|
|
4
|
+
import { Reactive } from '~/types';
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
// Branded type to prevent assignment to computed values
|
|
6
8
|
declare const READONLY: unique symbol;
|
|
7
9
|
|
|
10
|
+
type Guard<T> =
|
|
11
|
+
T extends Record<PropertyKey, unknown>
|
|
12
|
+
? T extends { dispose: any }
|
|
13
|
+
? { never: '[ dispose ] is a reserved key' }
|
|
14
|
+
: T
|
|
15
|
+
: never;
|
|
16
|
+
|
|
8
17
|
type Infer<T> =
|
|
9
18
|
T extends (...args: unknown[]) => Promise<infer R>
|
|
10
19
|
? R | undefined
|
|
11
20
|
: T extends (...args: any[]) => infer R
|
|
12
21
|
? R
|
|
13
22
|
: T extends (infer U)[]
|
|
14
|
-
? ReactiveArray<U>
|
|
23
|
+
? U[] & Pick<ReactiveArray<U>, 'clear' | 'on' | 'once'>
|
|
15
24
|
: T extends ReactiveObject<any>
|
|
16
25
|
? T
|
|
17
26
|
: T extends Record<PropertyKey, unknown>
|
|
@@ -20,24 +29,18 @@ type Infer<T> =
|
|
|
20
29
|
|
|
21
30
|
type ReactiveObject<T> =
|
|
22
31
|
T extends Record<PropertyKey, unknown>
|
|
23
|
-
? Prettify<{ [K in keyof T]: Infer<T[K]> } & { dispose: VoidFunction }>
|
|
32
|
+
? Reactive< Prettify<{ [K in keyof T]: Infer<T[K]> } & { dispose: VoidFunction }> >
|
|
24
33
|
: T extends (infer U)[]
|
|
25
|
-
? ReactiveArray<U>
|
|
34
|
+
? U[] & Pick<ReactiveArray<U>, 'clear' | 'on' | 'once'>
|
|
26
35
|
: never;
|
|
27
36
|
|
|
28
|
-
type ReactiveObjectGuard<T> = T extends { dispose: any } ? { never: '[ dispose ] is a reserved key' } : T;
|
|
29
|
-
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
function reactive<T extends
|
|
33
|
-
|
|
34
|
-
function reactive<T
|
|
35
|
-
// Array literal → existing ReactiveArray behavior
|
|
36
|
-
function reactive<T>(_input: T[]): ReactiveArray<T>;
|
|
37
|
-
// Everything else → passthrough type (allows assignment)
|
|
38
|
-
function reactive<T>(_input: T): T {
|
|
38
|
+
function reactive<T extends () => unknown>(_input: T): Reactive< ReturnType<T> & { readonly [READONLY]: true } >;
|
|
39
|
+
function reactive<T extends Record<PropertyKey, any>>(_input: Guard<T>): ReactiveObject<T>;
|
|
40
|
+
function reactive<T>(_input: T[]): Reactive< T[] & Pick<ReactiveArray<T>, 'clear' | 'on' | 'once'> >;
|
|
41
|
+
function reactive<T>(_input: T): Reactive<T> {
|
|
39
42
|
throw new Error(
|
|
40
|
-
|
|
43
|
+
`${PACKAGE}: reactive() called at runtime. ` +
|
|
41
44
|
'Ensure vite-plugin-reactivity-compile is configured.'
|
|
42
45
|
);
|
|
43
46
|
}
|
|
@@ -45,4 +48,4 @@ function reactive<T>(_input: T): T {
|
|
|
45
48
|
|
|
46
49
|
export default reactive;
|
|
47
50
|
export { reactive, ReactiveArray };
|
|
48
|
-
export type { ReactiveObject };
|
|
51
|
+
export type { Reactive, ReactiveObject };
|
package/src/system.ts
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
COMPUTED,
|
|
3
3
|
SIGNAL,
|
|
4
|
-
STABILIZER_IDLE,
|
|
5
|
-
|
|
6
|
-
STABILIZER_RUNNING,
|
|
7
|
-
STABILIZER_SCHEDULED,
|
|
8
|
-
STATE_CHECK,
|
|
9
|
-
STATE_DIRTY,
|
|
10
|
-
STATE_IN_HEAP,
|
|
11
|
-
STATE_NONE,
|
|
12
|
-
STATE_NOTIFY_MASK,
|
|
13
|
-
STATE_RECOMPUTING
|
|
4
|
+
STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED,
|
|
5
|
+
STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING
|
|
14
6
|
} from './constants';
|
|
15
7
|
import { Computed, Link, Signal } from './types';
|
|
16
8
|
import { isObject } from '@esportsplus/utilities';
|
|
@@ -529,7 +521,16 @@ const root = <T>(fn: ((dispose: VoidFunction) => T) | (() => T)) => {
|
|
|
529
521
|
|
|
530
522
|
root.disposables = 0;
|
|
531
523
|
|
|
532
|
-
const
|
|
524
|
+
const signal = <T>(value: T): Signal<T> => {
|
|
525
|
+
return {
|
|
526
|
+
subs: null,
|
|
527
|
+
subsTail: null,
|
|
528
|
+
type: SIGNAL,
|
|
529
|
+
value,
|
|
530
|
+
};
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
const write = <T>(signal: Signal<T>, value: T) => {
|
|
533
534
|
if (signal.value === value) {
|
|
534
535
|
return;
|
|
535
536
|
}
|
|
@@ -548,15 +549,6 @@ const set = <T>(signal: Signal<T>, value: T) => {
|
|
|
548
549
|
schedule();
|
|
549
550
|
};
|
|
550
551
|
|
|
551
|
-
const signal = <T>(value: T): Signal<T> => {
|
|
552
|
-
return {
|
|
553
|
-
subs: null,
|
|
554
|
-
subsTail: null,
|
|
555
|
-
type: SIGNAL,
|
|
556
|
-
value,
|
|
557
|
-
};
|
|
558
|
-
};
|
|
559
|
-
|
|
560
552
|
|
|
561
553
|
export {
|
|
562
554
|
computed,
|
|
@@ -565,6 +557,7 @@ export {
|
|
|
565
557
|
isComputed, isSignal,
|
|
566
558
|
onCleanup,
|
|
567
559
|
read, root,
|
|
568
|
-
|
|
560
|
+
signal,
|
|
561
|
+
write
|
|
569
562
|
};
|
|
570
563
|
export type { Computed, Signal };
|
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { code as c } from '@esportsplus/typescript/transformer';
|
|
2
2
|
import { ts } from '@esportsplus/typescript';
|
|
3
|
+
import { COMPILATION_ENTRYPOINT, COMPILATION_ENTRYPOINT_REGEX } from '~/constants';
|
|
3
4
|
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
hasUsage: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const REACTIVE_REGEX = /\breactive\b/;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function visit(ctx: DetectContext, node: ts.Node): void {
|
|
15
|
-
if (ctx.hasImport && ctx.hasUsage) {
|
|
6
|
+
function visit(ctx: { imported: boolean; used: boolean; }, node: ts.Node): void {
|
|
7
|
+
if (ctx.imported && ctx.used) {
|
|
16
8
|
return;
|
|
17
9
|
}
|
|
18
10
|
|
|
@@ -24,11 +16,10 @@ function visit(ctx: DetectContext, node: ts.Node): void {
|
|
|
24
16
|
let elements = node.importClause.namedBindings.elements;
|
|
25
17
|
|
|
26
18
|
for (let i = 0, n = elements.length; i < n; i++) {
|
|
27
|
-
let
|
|
28
|
-
name = el.propertyName?.text ?? el.name.text;
|
|
19
|
+
let element = elements[i];
|
|
29
20
|
|
|
30
|
-
if (name ===
|
|
31
|
-
ctx.
|
|
21
|
+
if ((element.propertyName?.text ?? element.name.text) === COMPILATION_ENTRYPOINT) {
|
|
22
|
+
ctx.imported = true;
|
|
32
23
|
break;
|
|
33
24
|
}
|
|
34
25
|
}
|
|
@@ -37,29 +28,29 @@ function visit(ctx: DetectContext, node: ts.Node): void {
|
|
|
37
28
|
if (
|
|
38
29
|
ts.isCallExpression(node) &&
|
|
39
30
|
ts.isIdentifier(node.expression) &&
|
|
40
|
-
node.expression.text ===
|
|
31
|
+
node.expression.text === COMPILATION_ENTRYPOINT
|
|
41
32
|
) {
|
|
42
|
-
ctx.
|
|
33
|
+
ctx.used = true;
|
|
43
34
|
}
|
|
44
35
|
|
|
45
36
|
ts.forEachChild(node, n => visit(ctx, n));
|
|
46
37
|
}
|
|
47
38
|
|
|
48
39
|
|
|
49
|
-
const
|
|
50
|
-
if (!
|
|
40
|
+
const contains = (code: string): boolean => {
|
|
41
|
+
if (!c.contains(code, { regex: COMPILATION_ENTRYPOINT_REGEX })) {
|
|
51
42
|
return false;
|
|
52
43
|
}
|
|
53
44
|
|
|
54
|
-
let ctx
|
|
55
|
-
|
|
56
|
-
|
|
45
|
+
let ctx = {
|
|
46
|
+
imported: false,
|
|
47
|
+
used: false
|
|
57
48
|
};
|
|
58
49
|
|
|
59
50
|
visit(ctx, ts.createSourceFile('detect.ts', code, ts.ScriptTarget.Latest, false));
|
|
60
51
|
|
|
61
|
-
return ctx.
|
|
52
|
+
return ctx.imported && ctx.used;
|
|
62
53
|
};
|
|
63
54
|
|
|
64
55
|
|
|
65
|
-
export {
|
|
56
|
+
export { contains };
|
package/src/transformer/index.ts
CHANGED
|
@@ -1,67 +1,45 @@
|
|
|
1
|
-
import type { Bindings, TransformResult } from '~/types';
|
|
2
|
-
import { mightNeedTransform } from './detector';
|
|
3
|
-
import { transformReactiveArrays } from './transforms/array';
|
|
4
|
-
import { transformReactiveObjects } from './transforms/object';
|
|
5
|
-
import { transformReactivePrimitives } from './transforms/primitives';
|
|
6
1
|
import { ts } from '@esportsplus/typescript';
|
|
2
|
+
import { uid } from '@esportsplus/typescript/transformer';
|
|
3
|
+
import { COMPILATION_NAMESPACE } from '~/constants.js';
|
|
4
|
+
import type { Bindings, TransformResult } from '~/types';
|
|
5
|
+
import { contains } from './detector';
|
|
6
|
+
import array from './transforms/array';
|
|
7
|
+
import object from './transforms/object';
|
|
8
|
+
import primitives from './transforms/primitives';
|
|
7
9
|
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return (sourceFile: ts.SourceFile): ts.SourceFile => {
|
|
12
|
-
let result = transform(sourceFile);
|
|
11
|
+
let ns = uid(COMPILATION_NAMESPACE),
|
|
12
|
+
transforms = [object, array, primitives];
|
|
13
13
|
|
|
14
|
-
return result.transformed ? result.sourceFile : sourceFile;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
14
|
|
|
19
15
|
const transform = (sourceFile: ts.SourceFile): TransformResult => {
|
|
20
16
|
let bindings: Bindings = new Map(),
|
|
21
17
|
code = sourceFile.getFullText(),
|
|
22
18
|
current = sourceFile,
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
result: string,
|
|
20
|
+
transformed = false;
|
|
25
21
|
|
|
26
|
-
if (!
|
|
22
|
+
if (!contains(code)) {
|
|
27
23
|
return { code, sourceFile, transformed: false };
|
|
28
24
|
}
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (result !== code) {
|
|
34
|
-
current = ts.createSourceFile(sourceFile.fileName, result, sourceFile.languageVersion, true);
|
|
35
|
-
code = result;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
result = transformReactiveArrays(current, bindings);
|
|
26
|
+
for (let i = 0, n = transforms.length; i < n; i++) {
|
|
27
|
+
result = transforms[i](current, bindings, ns);
|
|
39
28
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
29
|
+
if (result !== code) {
|
|
30
|
+
current = ts.createSourceFile(sourceFile.fileName, result, sourceFile.languageVersion, true);
|
|
31
|
+
code = result;
|
|
32
|
+
transformed = true;
|
|
33
|
+
}
|
|
43
34
|
}
|
|
44
35
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
current = ts.createSourceFile(sourceFile.fileName, result, sourceFile.languageVersion, true);
|
|
49
|
-
code = result;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (code === original) {
|
|
53
|
-
return { code, sourceFile, transformed: false };
|
|
36
|
+
if (transformed) {
|
|
37
|
+
code = `import * as ${ns} from '@esportsplus/reactivity';\n` + code;
|
|
38
|
+
sourceFile = ts.createSourceFile(sourceFile.fileName, code, sourceFile.languageVersion, true);
|
|
54
39
|
}
|
|
55
40
|
|
|
56
|
-
return {
|
|
57
|
-
code,
|
|
58
|
-
sourceFile: current,
|
|
59
|
-
transformed: true
|
|
60
|
-
};
|
|
41
|
+
return { code, sourceFile, transformed };
|
|
61
42
|
};
|
|
62
43
|
|
|
63
44
|
|
|
64
|
-
export {
|
|
65
|
-
export { transformReactiveArrays } from './transforms/array';
|
|
66
|
-
export { transformReactiveObjects } from './transforms/object';
|
|
67
|
-
export { transformReactivePrimitives } from './transforms/primitives';
|
|
45
|
+
export { contains, transform };
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { transform } from '~/transformer';
|
|
2
2
|
import { ts } from '@esportsplus/typescript';
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
// TypeScript custom transformers API requires program parameter, but we don't use it
|
|
6
6
|
export default (_program: ts.Program): ts.TransformerFactory<ts.SourceFile> => {
|
|
7
|
-
return
|
|
7
|
+
return () => {
|
|
8
|
+
return (sourceFile: ts.SourceFile): ts.SourceFile => {
|
|
9
|
+
let result = transform(sourceFile);
|
|
10
|
+
|
|
11
|
+
return result.transformed ? result.sourceFile : sourceFile;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
8
14
|
};
|
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
import { TRANSFORM_PATTERN } from '@esportsplus/typescript/transformer';
|
|
2
|
-
import { mightNeedTransform, transform } from '~/transformer';
|
|
3
1
|
import type { Plugin } from 'vite';
|
|
4
2
|
import { ts } from '@esportsplus/typescript';
|
|
3
|
+
import { TRANSFORM_PATTERN } from '@esportsplus/typescript/transformer';
|
|
4
|
+
import { contains, transform } from '~/transformer';
|
|
5
|
+
import { PACKAGE } from '~/constants';
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
export default (): Plugin => {
|
|
8
9
|
return {
|
|
9
10
|
enforce: 'pre',
|
|
10
|
-
name:
|
|
11
|
-
|
|
11
|
+
name: `${PACKAGE}/plugin-vite`,
|
|
12
12
|
transform(code: string, id: string) {
|
|
13
|
-
if (!TRANSFORM_PATTERN.test(id) || id.includes('node_modules')) {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (!mightNeedTransform(code)) {
|
|
13
|
+
if (!TRANSFORM_PATTERN.test(id) || id.includes('node_modules') || !contains(code)) {
|
|
18
14
|
return null;
|
|
19
15
|
}
|
|
20
16
|
|
|
21
17
|
try {
|
|
22
|
-
let
|
|
23
|
-
|
|
18
|
+
let result = transform(
|
|
19
|
+
ts.createSourceFile(id, code, ts.ScriptTarget.Latest, true)
|
|
20
|
+
);
|
|
24
21
|
|
|
25
22
|
if (!result.transformed) {
|
|
26
23
|
return null;
|
|
@@ -29,7 +26,7 @@ export default (): Plugin => {
|
|
|
29
26
|
return { code: result.code, map: null };
|
|
30
27
|
}
|
|
31
28
|
catch (error) {
|
|
32
|
-
console.error(
|
|
29
|
+
console.error(`${PACKAGE}: Error transforming ${id}:`, error);
|
|
33
30
|
return null;
|
|
34
31
|
}
|
|
35
32
|
}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { applyReplacements, Replacement } from './utilities';
|
|
1
|
+
import { code as c, type Replacement } from '@esportsplus/typescript/transformer';
|
|
3
2
|
import { ts } from '@esportsplus/typescript';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
interface TransformContext {
|
|
7
|
-
bindings: Bindings;
|
|
8
|
-
replacements: Replacement[];
|
|
9
|
-
sourceFile: ts.SourceFile;
|
|
10
|
-
}
|
|
3
|
+
import { COMPILATION_TYPE_ARRAY } from '~/constants';
|
|
4
|
+
import type { Bindings } from '~/types';
|
|
11
5
|
|
|
12
6
|
|
|
13
7
|
function getExpressionName(node: ts.Expression): string | null {
|
|
@@ -27,13 +21,13 @@ function getPropertyPath(node: ts.PropertyAccessExpression): string | null {
|
|
|
27
21
|
parts: string[] = [];
|
|
28
22
|
|
|
29
23
|
while (ts.isPropertyAccessExpression(current)) {
|
|
30
|
-
parts.
|
|
24
|
+
parts.push(current.name.text);
|
|
31
25
|
current = current.expression;
|
|
32
26
|
}
|
|
33
27
|
|
|
34
28
|
if (ts.isIdentifier(current)) {
|
|
35
|
-
parts.
|
|
36
|
-
return parts.join('.');
|
|
29
|
+
parts.push(current.text);
|
|
30
|
+
return parts.reverse().join('.');
|
|
37
31
|
}
|
|
38
32
|
|
|
39
33
|
return null;
|
|
@@ -42,32 +36,24 @@ function getPropertyPath(node: ts.PropertyAccessExpression): string | null {
|
|
|
42
36
|
function isAssignmentTarget(node: ts.Node): boolean {
|
|
43
37
|
let parent = node.parent;
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (
|
|
39
|
+
return !!parent && (
|
|
50
40
|
(ts.isBinaryExpression(parent) && parent.left === node) ||
|
|
51
41
|
ts.isPostfixUnaryExpression(parent) ||
|
|
52
42
|
ts.isPrefixUnaryExpression(parent)
|
|
53
|
-
)
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return false;
|
|
43
|
+
);
|
|
58
44
|
}
|
|
59
45
|
|
|
60
|
-
function visit(ctx:
|
|
46
|
+
function visit(ctx: { bindings: Bindings, replacements: Replacement[], sourceFile: ts.SourceFile }, node: ts.Node): void {
|
|
61
47
|
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) {
|
|
62
|
-
if (ts.isIdentifier(node.initializer) && ctx.bindings.get(node.initializer.text) ===
|
|
63
|
-
ctx.bindings.set(node.name.text,
|
|
48
|
+
if (ts.isIdentifier(node.initializer) && ctx.bindings.get(node.initializer.text) === COMPILATION_TYPE_ARRAY) {
|
|
49
|
+
ctx.bindings.set(node.name.text, COMPILATION_TYPE_ARRAY);
|
|
64
50
|
}
|
|
65
51
|
|
|
66
52
|
if (ts.isPropertyAccessExpression(node.initializer)) {
|
|
67
53
|
let path = getPropertyPath(node.initializer);
|
|
68
54
|
|
|
69
|
-
if (path && ctx.bindings.get(path) ===
|
|
70
|
-
ctx.bindings.set(node.name.text,
|
|
55
|
+
if (path && ctx.bindings.get(path) === COMPILATION_TYPE_ARRAY) {
|
|
56
|
+
ctx.bindings.set(node.name.text, COMPILATION_TYPE_ARRAY);
|
|
71
57
|
}
|
|
72
58
|
}
|
|
73
59
|
}
|
|
@@ -82,7 +68,7 @@ function visit(ctx: TransformContext, node: ts.Node): void {
|
|
|
82
68
|
ts.isIdentifier(param.type.typeName) &&
|
|
83
69
|
param.type.typeName.text === 'ReactiveArray'
|
|
84
70
|
) {
|
|
85
|
-
ctx.bindings.set(param.name.text,
|
|
71
|
+
ctx.bindings.set(param.name.text, COMPILATION_TYPE_ARRAY);
|
|
86
72
|
}
|
|
87
73
|
}
|
|
88
74
|
}
|
|
@@ -94,7 +80,7 @@ function visit(ctx: TransformContext, node: ts.Node): void {
|
|
|
94
80
|
) {
|
|
95
81
|
let name = getExpressionName(node.expression);
|
|
96
82
|
|
|
97
|
-
if (name && ctx.bindings.get(name) ===
|
|
83
|
+
if (name && ctx.bindings.get(name) === COMPILATION_TYPE_ARRAY) {
|
|
98
84
|
let objText = node.expression.getText(ctx.sourceFile);
|
|
99
85
|
|
|
100
86
|
ctx.replacements.push({
|
|
@@ -113,7 +99,7 @@ function visit(ctx: TransformContext, node: ts.Node): void {
|
|
|
113
99
|
let elemAccess = node.left,
|
|
114
100
|
objName = getExpressionName(elemAccess.expression);
|
|
115
101
|
|
|
116
|
-
if (objName && ctx.bindings.get(objName) ===
|
|
102
|
+
if (objName && ctx.bindings.get(objName) === COMPILATION_TYPE_ARRAY) {
|
|
117
103
|
let indexText = elemAccess.argumentExpression.getText(ctx.sourceFile),
|
|
118
104
|
objText = elemAccess.expression.getText(ctx.sourceFile),
|
|
119
105
|
valueText = node.right.getText(ctx.sourceFile);
|
|
@@ -130,9 +116,9 @@ function visit(ctx: TransformContext, node: ts.Node): void {
|
|
|
130
116
|
}
|
|
131
117
|
|
|
132
118
|
|
|
133
|
-
|
|
119
|
+
export default (sourceFile: ts.SourceFile, bindings: Bindings, _ns: string): string => {
|
|
134
120
|
let code = sourceFile.getFullText(),
|
|
135
|
-
ctx
|
|
121
|
+
ctx = {
|
|
136
122
|
bindings,
|
|
137
123
|
replacements: [],
|
|
138
124
|
sourceFile
|
|
@@ -140,8 +126,5 @@ const transformReactiveArrays = (sourceFile: ts.SourceFile, bindings: Bindings):
|
|
|
140
126
|
|
|
141
127
|
visit(ctx, sourceFile);
|
|
142
128
|
|
|
143
|
-
return
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
export { transformReactiveArrays };
|
|
129
|
+
return c.replace(code, ctx.replacements);
|
|
130
|
+
};
|