@esportsplus/reactivity 0.25.7 → 0.25.9
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 +7 -7
- package/build/constants.js +7 -7
- package/build/reactive/index.js +2 -2
- package/build/transformer/index.d.ts +1 -1
- package/build/transformer/index.js +38 -4
- package/build/transformer/plugins/vite.js +2 -2
- package/build/transformer/transforms/array.js +8 -8
- package/build/transformer/transforms/object.js +9 -9
- package/build/transformer/transforms/primitives.js +8 -8
- package/package.json +1 -1
- package/src/constants.ts +7 -7
- package/src/reactive/index.ts +2 -2
- package/src/transformer/index.ts +53 -4
- package/src/transformer/plugins/vite.ts +2 -2
- package/src/transformer/transforms/array.ts +8 -8
- package/src/transformer/transforms/object.ts +9 -9
- package/src/transformer/transforms/primitives.ts +8 -8
- package/build/transformer/detector.d.ts +0 -2
- package/build/transformer/detector.js +0 -38
- package/src/transformer/detector.ts +0 -56
package/build/constants.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
declare const
|
|
2
|
-
declare const
|
|
3
|
-
declare const
|
|
4
|
-
declare const
|
|
5
|
-
declare const
|
|
6
|
-
declare const
|
|
1
|
+
declare const COMPILER_ENTRYPOINT = "reactive";
|
|
2
|
+
declare const COMPILER_ENTRYPOINT_REGEX: RegExp;
|
|
3
|
+
declare const COMPILER_NAMESPACE: string;
|
|
4
|
+
declare const COMPILER_TYPE_ARRAY = "array";
|
|
5
|
+
declare const COMPILER_TYPE_COMPUTED = "computed";
|
|
6
|
+
declare const COMPILER_TYPE_SIGNAL = "signal";
|
|
7
7
|
declare const COMPUTED: unique symbol;
|
|
8
8
|
declare const PACKAGE = "@esportsplus/reactivity";
|
|
9
9
|
declare const REACTIVE_ARRAY: unique symbol;
|
|
@@ -19,4 +19,4 @@ declare const STATE_DIRTY: number;
|
|
|
19
19
|
declare const STATE_RECOMPUTING: number;
|
|
20
20
|
declare const STATE_IN_HEAP: number;
|
|
21
21
|
declare const STATE_NOTIFY_MASK: number;
|
|
22
|
-
export {
|
|
22
|
+
export { COMPILER_TYPE_ARRAY, COMPILER_TYPE_COMPUTED, COMPILER_ENTRYPOINT, COMPILER_ENTRYPOINT_REGEX, COMPILER_NAMESPACE, COMPILER_TYPE_SIGNAL, COMPUTED, PACKAGE, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING };
|
package/build/constants.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { uid } from '@esportsplus/typescript/transformer';
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
2
|
+
const COMPILER_ENTRYPOINT = 'reactive';
|
|
3
|
+
const COMPILER_ENTRYPOINT_REGEX = /\breactive\b/;
|
|
4
|
+
const COMPILER_NAMESPACE = uid(COMPILER_ENTRYPOINT);
|
|
5
|
+
const COMPILER_TYPE_ARRAY = 'array';
|
|
6
|
+
const COMPILER_TYPE_COMPUTED = 'computed';
|
|
7
|
+
const COMPILER_TYPE_SIGNAL = 'signal';
|
|
8
8
|
const COMPUTED = Symbol('reactivity.computed');
|
|
9
9
|
const PACKAGE = '@esportsplus/reactivity';
|
|
10
10
|
const REACTIVE_ARRAY = Symbol('reactivity.reactive.array');
|
|
@@ -20,4 +20,4 @@ const STATE_DIRTY = 1 << 1;
|
|
|
20
20
|
const STATE_RECOMPUTING = 1 << 2;
|
|
21
21
|
const STATE_IN_HEAP = 1 << 3;
|
|
22
22
|
const STATE_NOTIFY_MASK = (STATE_CHECK | STATE_DIRTY);
|
|
23
|
-
export {
|
|
23
|
+
export { COMPILER_TYPE_ARRAY, COMPILER_TYPE_COMPUTED, COMPILER_ENTRYPOINT, COMPILER_ENTRYPOINT_REGEX, COMPILER_NAMESPACE, COMPILER_TYPE_SIGNAL, COMPUTED, PACKAGE, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING };
|
package/build/reactive/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ReactiveArray } from './array.js';
|
|
2
|
-
import {
|
|
2
|
+
import { COMPILER_ENTRYPOINT, PACKAGE } from '../constants.js';
|
|
3
3
|
function reactive(_input) {
|
|
4
|
-
throw new Error(`${PACKAGE}: ${
|
|
4
|
+
throw new Error(`${PACKAGE}: ${COMPILER_ENTRYPOINT}() called at runtime. ` +
|
|
5
5
|
'Ensure vite plugin is configured.');
|
|
6
6
|
}
|
|
7
7
|
export default reactive;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ts } from '@esportsplus/typescript';
|
|
2
2
|
import type { TransformResult } from '../types.js';
|
|
3
|
-
|
|
3
|
+
declare function contains(code: string): boolean;
|
|
4
4
|
declare const transform: (sourceFile: ts.SourceFile) => TransformResult;
|
|
5
5
|
export { contains, transform };
|
|
@@ -1,17 +1,51 @@
|
|
|
1
1
|
import { ts } from '@esportsplus/typescript';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { code as c } from '@esportsplus/typescript/transformer';
|
|
3
|
+
import { COMPILER_ENTRYPOINT, COMPILER_ENTRYPOINT_REGEX, COMPILER_NAMESPACE } from '../constants.js';
|
|
4
4
|
import array from './transforms/array.js';
|
|
5
5
|
import object from './transforms/object.js';
|
|
6
6
|
import primitives from './transforms/primitives.js';
|
|
7
7
|
let transforms = [object, array, primitives];
|
|
8
|
+
function contains(code) {
|
|
9
|
+
if (!c.contains(code, { regex: COMPILER_ENTRYPOINT_REGEX })) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
let ctx = {
|
|
13
|
+
imported: false,
|
|
14
|
+
used: false
|
|
15
|
+
};
|
|
16
|
+
visit(ctx, ts.createSourceFile('detect.ts', code, ts.ScriptTarget.Latest, false));
|
|
17
|
+
return ctx.imported && ctx.used;
|
|
18
|
+
}
|
|
19
|
+
function visit(ctx, node) {
|
|
20
|
+
if (ctx.imported && ctx.used) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (ts.isImportDeclaration(node) &&
|
|
24
|
+
node.importClause?.namedBindings &&
|
|
25
|
+
ts.isNamedImports(node.importClause.namedBindings)) {
|
|
26
|
+
let elements = node.importClause.namedBindings.elements;
|
|
27
|
+
for (let i = 0, n = elements.length; i < n; i++) {
|
|
28
|
+
let element = elements[i];
|
|
29
|
+
if ((element.propertyName?.text ?? element.name.text) === COMPILER_ENTRYPOINT) {
|
|
30
|
+
ctx.imported = true;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (ts.isCallExpression(node) &&
|
|
36
|
+
ts.isIdentifier(node.expression) &&
|
|
37
|
+
node.expression.text === COMPILER_ENTRYPOINT) {
|
|
38
|
+
ctx.used = true;
|
|
39
|
+
}
|
|
40
|
+
ts.forEachChild(node, n => visit(ctx, n));
|
|
41
|
+
}
|
|
8
42
|
const transform = (sourceFile) => {
|
|
9
43
|
let bindings = new Map(), code = sourceFile.getFullText(), current = sourceFile, result, transformed = false;
|
|
10
44
|
if (!contains(code)) {
|
|
11
45
|
return { code, sourceFile, transformed: false };
|
|
12
46
|
}
|
|
13
47
|
for (let i = 0, n = transforms.length; i < n; i++) {
|
|
14
|
-
result = transforms[i](current, bindings,
|
|
48
|
+
result = transforms[i](current, bindings, COMPILER_NAMESPACE);
|
|
15
49
|
if (result !== code) {
|
|
16
50
|
current = ts.createSourceFile(sourceFile.fileName, result, sourceFile.languageVersion, true);
|
|
17
51
|
code = result;
|
|
@@ -19,7 +53,7 @@ const transform = (sourceFile) => {
|
|
|
19
53
|
}
|
|
20
54
|
}
|
|
21
55
|
if (transformed) {
|
|
22
|
-
code = `import * as ${
|
|
56
|
+
code = `import * as ${COMPILER_NAMESPACE} from '@esportsplus/reactivity';\n` + code;
|
|
23
57
|
sourceFile = ts.createSourceFile(sourceFile.fileName, code, sourceFile.languageVersion, true);
|
|
24
58
|
}
|
|
25
59
|
return { code, sourceFile, transformed };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { ts } from '@esportsplus/typescript';
|
|
2
2
|
import { TRANSFORM_PATTERN } from '@esportsplus/typescript/transformer';
|
|
3
|
-
import {
|
|
3
|
+
import { transform } from '../../transformer/index.js';
|
|
4
4
|
import { PACKAGE } from '../../constants.js';
|
|
5
5
|
export default () => {
|
|
6
6
|
return {
|
|
7
7
|
enforce: 'pre',
|
|
8
8
|
name: `${PACKAGE}/plugin-vite`,
|
|
9
9
|
transform(code, id) {
|
|
10
|
-
if (!TRANSFORM_PATTERN.test(id) || id.includes('node_modules')
|
|
10
|
+
if (!TRANSFORM_PATTERN.test(id) || id.includes('node_modules')) {
|
|
11
11
|
return null;
|
|
12
12
|
}
|
|
13
13
|
try {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { code as c } from '@esportsplus/typescript/transformer';
|
|
2
2
|
import { ts } from '@esportsplus/typescript';
|
|
3
|
-
import {
|
|
3
|
+
import { COMPILER_TYPE_ARRAY } from '../../constants.js';
|
|
4
4
|
function getExpressionName(node) {
|
|
5
5
|
if (ts.isIdentifier(node)) {
|
|
6
6
|
return node.text;
|
|
@@ -30,13 +30,13 @@ function isAssignmentTarget(node) {
|
|
|
30
30
|
}
|
|
31
31
|
function visit(ctx, node) {
|
|
32
32
|
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) {
|
|
33
|
-
if (ts.isIdentifier(node.initializer) && ctx.bindings.get(node.initializer.text) ===
|
|
34
|
-
ctx.bindings.set(node.name.text,
|
|
33
|
+
if (ts.isIdentifier(node.initializer) && ctx.bindings.get(node.initializer.text) === COMPILER_TYPE_ARRAY) {
|
|
34
|
+
ctx.bindings.set(node.name.text, COMPILER_TYPE_ARRAY);
|
|
35
35
|
}
|
|
36
36
|
if (ts.isPropertyAccessExpression(node.initializer)) {
|
|
37
37
|
let path = getPropertyPath(node.initializer);
|
|
38
|
-
if (path && ctx.bindings.get(path) ===
|
|
39
|
-
ctx.bindings.set(node.name.text,
|
|
38
|
+
if (path && ctx.bindings.get(path) === COMPILER_TYPE_ARRAY) {
|
|
39
|
+
ctx.bindings.set(node.name.text, COMPILER_TYPE_ARRAY);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -47,7 +47,7 @@ function visit(ctx, node) {
|
|
|
47
47
|
ts.isTypeReferenceNode(param.type) &&
|
|
48
48
|
ts.isIdentifier(param.type.typeName) &&
|
|
49
49
|
param.type.typeName.text === 'ReactiveArray') {
|
|
50
|
-
ctx.bindings.set(param.name.text,
|
|
50
|
+
ctx.bindings.set(param.name.text, COMPILER_TYPE_ARRAY);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -55,7 +55,7 @@ function visit(ctx, node) {
|
|
|
55
55
|
node.name.text === 'length' &&
|
|
56
56
|
!isAssignmentTarget(node)) {
|
|
57
57
|
let name = getExpressionName(node.expression);
|
|
58
|
-
if (name && ctx.bindings.get(name) ===
|
|
58
|
+
if (name && ctx.bindings.get(name) === COMPILER_TYPE_ARRAY) {
|
|
59
59
|
let objText = node.expression.getText(ctx.sourceFile);
|
|
60
60
|
ctx.replacements.push({
|
|
61
61
|
end: node.end,
|
|
@@ -68,7 +68,7 @@ function visit(ctx, node) {
|
|
|
68
68
|
node.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
69
69
|
ts.isElementAccessExpression(node.left)) {
|
|
70
70
|
let elemAccess = node.left, objName = getExpressionName(elemAccess.expression);
|
|
71
|
-
if (objName && ctx.bindings.get(objName) ===
|
|
71
|
+
if (objName && ctx.bindings.get(objName) === COMPILER_TYPE_ARRAY) {
|
|
72
72
|
let indexText = elemAccess.argumentExpression.getText(ctx.sourceFile), objText = elemAccess.expression.getText(ctx.sourceFile), valueText = node.right.getText(ctx.sourceFile);
|
|
73
73
|
ctx.replacements.push({
|
|
74
74
|
end: node.end,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ts } from '@esportsplus/typescript';
|
|
2
2
|
import { code as c } from '@esportsplus/typescript/transformer';
|
|
3
|
-
import {
|
|
3
|
+
import { COMPILER_TYPE_ARRAY, COMPILER_TYPE_COMPUTED, COMPILER_TYPE_SIGNAL, PACKAGE } from '../../constants.js';
|
|
4
4
|
function analyzeProperty(prop, sourceFile) {
|
|
5
5
|
if (!ts.isPropertyAssignment(prop)) {
|
|
6
6
|
return null;
|
|
@@ -14,7 +14,7 @@ function analyzeProperty(prop, sourceFile) {
|
|
|
14
14
|
}
|
|
15
15
|
let value = prop.initializer, valueText = value.getText(sourceFile);
|
|
16
16
|
if (ts.isArrowFunction(value) || ts.isFunctionExpression(value)) {
|
|
17
|
-
return { key, type:
|
|
17
|
+
return { key, type: COMPILER_TYPE_COMPUTED, valueText };
|
|
18
18
|
}
|
|
19
19
|
if (ts.isArrayLiteralExpression(value)) {
|
|
20
20
|
let elements = value.elements, elementsText = '';
|
|
@@ -24,26 +24,26 @@ function analyzeProperty(prop, sourceFile) {
|
|
|
24
24
|
}
|
|
25
25
|
elementsText += elements[i].getText(sourceFile);
|
|
26
26
|
}
|
|
27
|
-
return { key, type:
|
|
27
|
+
return { key, type: COMPILER_TYPE_ARRAY, valueText: elementsText };
|
|
28
28
|
}
|
|
29
|
-
return { key, type:
|
|
29
|
+
return { key, type: COMPILER_TYPE_SIGNAL, valueText };
|
|
30
30
|
}
|
|
31
31
|
function buildClassCode(className, properties, ns) {
|
|
32
32
|
let accessors = [], disposeStatements = [], fields = [], paramCounter = 0;
|
|
33
33
|
fields.push(`[${ns}.REACTIVE_OBJECT] = true;`);
|
|
34
34
|
for (let i = 0, n = properties.length; i < n; i++) {
|
|
35
35
|
let { key, type, valueText } = properties[i];
|
|
36
|
-
if (type ===
|
|
36
|
+
if (type === COMPILER_TYPE_SIGNAL) {
|
|
37
37
|
let param = `_v${paramCounter++}`;
|
|
38
38
|
fields.push(`#${key} = ${ns}.signal(${valueText});`);
|
|
39
39
|
accessors.push(`get ${key}() { return ${ns}.read(this.#${key}); }`);
|
|
40
40
|
accessors.push(`set ${key}(${param}) { ${ns}.write(this.#${key}, ${param}); }`);
|
|
41
41
|
}
|
|
42
|
-
else if (type ===
|
|
42
|
+
else if (type === COMPILER_TYPE_ARRAY) {
|
|
43
43
|
fields.push(`${key} = new ${ns}.ReactiveArray(${valueText});`);
|
|
44
44
|
disposeStatements.push(`this.${key}.dispose();`);
|
|
45
45
|
}
|
|
46
|
-
else if (type ===
|
|
46
|
+
else if (type === COMPILER_TYPE_COMPUTED) {
|
|
47
47
|
fields.push(`#${key} = null;`);
|
|
48
48
|
accessors.push(`get ${key}() { return ${ns}.read(this.#${key} ??= ${ns}.computed(${valueText})); }`);
|
|
49
49
|
disposeStatements.push(`if (this.#${key}) ${ns}.dispose(this.#${key});`);
|
|
@@ -100,8 +100,8 @@ function visit(ctx, node) {
|
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
102
|
properties.push(analyzed);
|
|
103
|
-
if (analyzed.type ===
|
|
104
|
-
ctx.bindings.set(`${varName}.${analyzed.key}`,
|
|
103
|
+
if (analyzed.type === COMPILER_TYPE_ARRAY && varName) {
|
|
104
|
+
ctx.bindings.set(`${varName}.${analyzed.key}`, COMPILER_TYPE_ARRAY);
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
ctx.calls.push({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ts } from '@esportsplus/typescript';
|
|
2
2
|
import { code as c } from '@esportsplus/typescript/transformer';
|
|
3
|
-
import {
|
|
3
|
+
import { COMPILER_TYPE_COMPUTED, COMPILER_ENTRYPOINT, COMPILER_TYPE_SIGNAL, PACKAGE } from '../../constants.js';
|
|
4
4
|
let COMPOUND_OPERATORS = new Map([
|
|
5
5
|
[ts.SyntaxKind.AmpersandAmpersandEqualsToken, '&&'],
|
|
6
6
|
[ts.SyntaxKind.AmpersandEqualsToken, '&'],
|
|
@@ -20,12 +20,12 @@ let COMPOUND_OPERATORS = new Map([
|
|
|
20
20
|
]);
|
|
21
21
|
function classifyReactiveArg(arg) {
|
|
22
22
|
if (ts.isArrowFunction(arg) || ts.isFunctionExpression(arg)) {
|
|
23
|
-
return
|
|
23
|
+
return COMPILER_TYPE_COMPUTED;
|
|
24
24
|
}
|
|
25
25
|
if (ts.isObjectLiteralExpression(arg) || ts.isArrayLiteralExpression(arg)) {
|
|
26
26
|
return null;
|
|
27
27
|
}
|
|
28
|
-
return
|
|
28
|
+
return COMPILER_TYPE_SIGNAL;
|
|
29
29
|
}
|
|
30
30
|
function findBinding(bindings, name, node) {
|
|
31
31
|
for (let i = 0, n = bindings.length; i < n; i++) {
|
|
@@ -83,7 +83,7 @@ function isReactiveReassignment(node) {
|
|
|
83
83
|
parent.right === node &&
|
|
84
84
|
ts.isCallExpression(node) &&
|
|
85
85
|
ts.isIdentifier(node.expression) &&
|
|
86
|
-
node.expression.text ===
|
|
86
|
+
node.expression.text === COMPILER_ENTRYPOINT) {
|
|
87
87
|
return true;
|
|
88
88
|
}
|
|
89
89
|
return false;
|
|
@@ -114,7 +114,7 @@ function visit(ctx, node) {
|
|
|
114
114
|
let clause = node.importClause;
|
|
115
115
|
if (clause?.namedBindings && ts.isNamedImports(clause.namedBindings)) {
|
|
116
116
|
for (let i = 0, n = clause.namedBindings.elements.length; i < n; i++) {
|
|
117
|
-
if (clause.namedBindings.elements[i].name.text ===
|
|
117
|
+
if (clause.namedBindings.elements[i].name.text === COMPILER_ENTRYPOINT) {
|
|
118
118
|
ctx.hasReactiveImport = true;
|
|
119
119
|
break;
|
|
120
120
|
}
|
|
@@ -124,7 +124,7 @@ function visit(ctx, node) {
|
|
|
124
124
|
if (ctx.hasReactiveImport &&
|
|
125
125
|
ts.isCallExpression(node) &&
|
|
126
126
|
ts.isIdentifier(node.expression) &&
|
|
127
|
-
node.expression.text ===
|
|
127
|
+
node.expression.text === COMPILER_ENTRYPOINT &&
|
|
128
128
|
node.arguments.length > 0) {
|
|
129
129
|
let arg = node.arguments[0], classification = classifyReactiveArg(arg);
|
|
130
130
|
if (classification) {
|
|
@@ -143,7 +143,7 @@ function visit(ctx, node) {
|
|
|
143
143
|
ctx.scopedBindings.push({ name: varName, scope, type: classification });
|
|
144
144
|
ctx.bindings.set(varName, classification);
|
|
145
145
|
}
|
|
146
|
-
if (classification ===
|
|
146
|
+
if (classification === COMPILER_TYPE_COMPUTED) {
|
|
147
147
|
let argStart = arg.getStart(ctx.sourceFile);
|
|
148
148
|
ctx.computedArgRanges.push({ end: arg.end, start: argStart });
|
|
149
149
|
let argCtx = {
|
|
@@ -186,7 +186,7 @@ function visit(ctx, node) {
|
|
|
186
186
|
!(ts.isTypeOfExpression(node.parent) && node.parent.expression === node)) {
|
|
187
187
|
let writeCtx = isWriteContext(node);
|
|
188
188
|
if (writeCtx) {
|
|
189
|
-
if (binding.type !==
|
|
189
|
+
if (binding.type !== COMPILER_TYPE_COMPUTED) {
|
|
190
190
|
let parent = node.parent;
|
|
191
191
|
if (writeCtx === 'simple' && ts.isBinaryExpression(parent)) {
|
|
192
192
|
ctx.replacements.push({
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { uid } from '@esportsplus/typescript/transformer';
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const COMPILER_ENTRYPOINT = 'reactive';
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const COMPILER_ENTRYPOINT_REGEX = /\breactive\b/;
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const COMPILER_NAMESPACE = uid(COMPILER_ENTRYPOINT);
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const COMPILER_TYPE_ARRAY = 'array';
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const COMPILER_TYPE_COMPUTED = 'computed';
|
|
13
13
|
|
|
14
|
-
const
|
|
14
|
+
const COMPILER_TYPE_SIGNAL = 'signal';
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
const COMPUTED = Symbol('reactivity.computed');
|
|
@@ -48,7 +48,7 @@ const STATE_NOTIFY_MASK = (STATE_CHECK | STATE_DIRTY);
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
export {
|
|
51
|
-
|
|
51
|
+
COMPILER_TYPE_ARRAY, COMPILER_TYPE_COMPUTED, COMPILER_ENTRYPOINT, COMPILER_ENTRYPOINT_REGEX, COMPILER_NAMESPACE, COMPILER_TYPE_SIGNAL, COMPUTED,
|
|
52
52
|
PACKAGE,
|
|
53
53
|
REACTIVE_ARRAY, REACTIVE_OBJECT,
|
|
54
54
|
SIGNAL,
|
package/src/reactive/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactiveArray } from './array';
|
|
2
|
-
import {
|
|
2
|
+
import { COMPILER_ENTRYPOINT, PACKAGE } from '~/constants';
|
|
3
3
|
import { Reactive } from '~/types';
|
|
4
4
|
|
|
5
5
|
|
|
@@ -14,7 +14,7 @@ type Guard<T> =
|
|
|
14
14
|
function reactive<T extends Record<PropertyKey, any>>(_input: Guard<T>): Reactive<T>;
|
|
15
15
|
function reactive<T>(_input: T): Reactive<T> {
|
|
16
16
|
throw new Error(
|
|
17
|
-
`${PACKAGE}: ${
|
|
17
|
+
`${PACKAGE}: ${COMPILER_ENTRYPOINT}() called at runtime. ` +
|
|
18
18
|
'Ensure vite plugin is configured.'
|
|
19
19
|
);
|
|
20
20
|
}
|
package/src/transformer/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ts } from '@esportsplus/typescript';
|
|
2
|
-
import {
|
|
2
|
+
import { code as c } from '@esportsplus/typescript/transformer';
|
|
3
|
+
import { COMPILER_ENTRYPOINT, COMPILER_ENTRYPOINT_REGEX, COMPILER_NAMESPACE } from '~/constants';
|
|
3
4
|
import type { Bindings, TransformResult } from '~/types';
|
|
4
|
-
import { contains } from './detector';
|
|
5
5
|
import array from './transforms/array';
|
|
6
6
|
import object from './transforms/object';
|
|
7
7
|
import primitives from './transforms/primitives';
|
|
@@ -10,6 +10,55 @@ import primitives from './transforms/primitives';
|
|
|
10
10
|
let transforms = [object, array, primitives];
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
function contains(code: string): boolean {
|
|
14
|
+
if (!c.contains(code, { regex: COMPILER_ENTRYPOINT_REGEX })) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let ctx = {
|
|
19
|
+
imported: false,
|
|
20
|
+
used: false
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
visit(ctx, ts.createSourceFile('detect.ts', code, ts.ScriptTarget.Latest, false));
|
|
24
|
+
|
|
25
|
+
return ctx.imported && ctx.used;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function visit(ctx: { imported: boolean; used: boolean; }, node: ts.Node): void {
|
|
29
|
+
if (ctx.imported && ctx.used) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (
|
|
34
|
+
ts.isImportDeclaration(node) &&
|
|
35
|
+
node.importClause?.namedBindings &&
|
|
36
|
+
ts.isNamedImports(node.importClause.namedBindings)
|
|
37
|
+
) {
|
|
38
|
+
let elements = node.importClause.namedBindings.elements;
|
|
39
|
+
|
|
40
|
+
for (let i = 0, n = elements.length; i < n; i++) {
|
|
41
|
+
let element = elements[i];
|
|
42
|
+
|
|
43
|
+
if ((element.propertyName?.text ?? element.name.text) === COMPILER_ENTRYPOINT) {
|
|
44
|
+
ctx.imported = true;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (
|
|
51
|
+
ts.isCallExpression(node) &&
|
|
52
|
+
ts.isIdentifier(node.expression) &&
|
|
53
|
+
node.expression.text === COMPILER_ENTRYPOINT
|
|
54
|
+
) {
|
|
55
|
+
ctx.used = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ts.forEachChild(node, n => visit(ctx, n));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
13
62
|
const transform = (sourceFile: ts.SourceFile): TransformResult => {
|
|
14
63
|
let bindings: Bindings = new Map(),
|
|
15
64
|
code = sourceFile.getFullText(),
|
|
@@ -22,7 +71,7 @@ const transform = (sourceFile: ts.SourceFile): TransformResult => {
|
|
|
22
71
|
}
|
|
23
72
|
|
|
24
73
|
for (let i = 0, n = transforms.length; i < n; i++) {
|
|
25
|
-
result = transforms[i](current, bindings,
|
|
74
|
+
result = transforms[i](current, bindings, COMPILER_NAMESPACE);
|
|
26
75
|
|
|
27
76
|
if (result !== code) {
|
|
28
77
|
current = ts.createSourceFile(sourceFile.fileName, result, sourceFile.languageVersion, true);
|
|
@@ -32,7 +81,7 @@ const transform = (sourceFile: ts.SourceFile): TransformResult => {
|
|
|
32
81
|
}
|
|
33
82
|
|
|
34
83
|
if (transformed) {
|
|
35
|
-
code = `import * as ${
|
|
84
|
+
code = `import * as ${COMPILER_NAMESPACE} from '@esportsplus/reactivity';\n` + code;
|
|
36
85
|
sourceFile = ts.createSourceFile(sourceFile.fileName, code, sourceFile.languageVersion, true);
|
|
37
86
|
}
|
|
38
87
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Plugin } from 'vite';
|
|
2
2
|
import { ts } from '@esportsplus/typescript';
|
|
3
3
|
import { TRANSFORM_PATTERN } from '@esportsplus/typescript/transformer';
|
|
4
|
-
import {
|
|
4
|
+
import { transform } from '~/transformer';
|
|
5
5
|
import { PACKAGE } from '~/constants';
|
|
6
6
|
|
|
7
7
|
|
|
@@ -10,7 +10,7 @@ export default (): Plugin => {
|
|
|
10
10
|
enforce: 'pre',
|
|
11
11
|
name: `${PACKAGE}/plugin-vite`,
|
|
12
12
|
transform(code: string, id: string) {
|
|
13
|
-
if (!TRANSFORM_PATTERN.test(id) || id.includes('node_modules')
|
|
13
|
+
if (!TRANSFORM_PATTERN.test(id) || id.includes('node_modules')) {
|
|
14
14
|
return null;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { code as c, type Replacement } from '@esportsplus/typescript/transformer';
|
|
2
2
|
import { ts } from '@esportsplus/typescript';
|
|
3
|
-
import {
|
|
3
|
+
import { COMPILER_TYPE_ARRAY } from '~/constants';
|
|
4
4
|
import type { Bindings } from '~/types';
|
|
5
5
|
|
|
6
6
|
|
|
@@ -45,15 +45,15 @@ function isAssignmentTarget(node: ts.Node): boolean {
|
|
|
45
45
|
|
|
46
46
|
function visit(ctx: { bindings: Bindings, replacements: Replacement[], sourceFile: ts.SourceFile }, node: ts.Node): void {
|
|
47
47
|
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) {
|
|
48
|
-
if (ts.isIdentifier(node.initializer) && ctx.bindings.get(node.initializer.text) ===
|
|
49
|
-
ctx.bindings.set(node.name.text,
|
|
48
|
+
if (ts.isIdentifier(node.initializer) && ctx.bindings.get(node.initializer.text) === COMPILER_TYPE_ARRAY) {
|
|
49
|
+
ctx.bindings.set(node.name.text, COMPILER_TYPE_ARRAY);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
if (ts.isPropertyAccessExpression(node.initializer)) {
|
|
53
53
|
let path = getPropertyPath(node.initializer);
|
|
54
54
|
|
|
55
|
-
if (path && ctx.bindings.get(path) ===
|
|
56
|
-
ctx.bindings.set(node.name.text,
|
|
55
|
+
if (path && ctx.bindings.get(path) === COMPILER_TYPE_ARRAY) {
|
|
56
|
+
ctx.bindings.set(node.name.text, COMPILER_TYPE_ARRAY);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -68,7 +68,7 @@ function visit(ctx: { bindings: Bindings, replacements: Replacement[], sourceFil
|
|
|
68
68
|
ts.isIdentifier(param.type.typeName) &&
|
|
69
69
|
param.type.typeName.text === 'ReactiveArray'
|
|
70
70
|
) {
|
|
71
|
-
ctx.bindings.set(param.name.text,
|
|
71
|
+
ctx.bindings.set(param.name.text, COMPILER_TYPE_ARRAY);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -80,7 +80,7 @@ function visit(ctx: { bindings: Bindings, replacements: Replacement[], sourceFil
|
|
|
80
80
|
) {
|
|
81
81
|
let name = getExpressionName(node.expression);
|
|
82
82
|
|
|
83
|
-
if (name && ctx.bindings.get(name) ===
|
|
83
|
+
if (name && ctx.bindings.get(name) === COMPILER_TYPE_ARRAY) {
|
|
84
84
|
let objText = node.expression.getText(ctx.sourceFile);
|
|
85
85
|
|
|
86
86
|
ctx.replacements.push({
|
|
@@ -99,7 +99,7 @@ function visit(ctx: { bindings: Bindings, replacements: Replacement[], sourceFil
|
|
|
99
99
|
let elemAccess = node.left,
|
|
100
100
|
objName = getExpressionName(elemAccess.expression);
|
|
101
101
|
|
|
102
|
-
if (objName && ctx.bindings.get(objName) ===
|
|
102
|
+
if (objName && ctx.bindings.get(objName) === COMPILER_TYPE_ARRAY) {
|
|
103
103
|
let indexText = elemAccess.argumentExpression.getText(ctx.sourceFile),
|
|
104
104
|
objText = elemAccess.expression.getText(ctx.sourceFile),
|
|
105
105
|
valueText = node.right.getText(ctx.sourceFile);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ts } from '@esportsplus/typescript';
|
|
2
2
|
import { code as c, type Replacement } from '@esportsplus/typescript/transformer';
|
|
3
|
-
import {
|
|
3
|
+
import { COMPILER_TYPE_ARRAY, COMPILER_TYPE_COMPUTED, COMPILER_TYPE_SIGNAL, PACKAGE } from '~/constants';
|
|
4
4
|
import type { Bindings } from '~/types';
|
|
5
5
|
|
|
6
6
|
|
|
@@ -47,7 +47,7 @@ function analyzeProperty(prop: ts.ObjectLiteralElementLike, sourceFile: ts.Sourc
|
|
|
47
47
|
valueText = value.getText(sourceFile);
|
|
48
48
|
|
|
49
49
|
if (ts.isArrowFunction(value) || ts.isFunctionExpression(value)) {
|
|
50
|
-
return { key, type:
|
|
50
|
+
return { key, type: COMPILER_TYPE_COMPUTED, valueText };
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
if (ts.isArrayLiteralExpression(value)) {
|
|
@@ -62,10 +62,10 @@ function analyzeProperty(prop: ts.ObjectLiteralElementLike, sourceFile: ts.Sourc
|
|
|
62
62
|
elementsText += elements[i].getText(sourceFile);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
return { key, type:
|
|
65
|
+
return { key, type: COMPILER_TYPE_ARRAY, valueText: elementsText };
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
return { key, type:
|
|
68
|
+
return { key, type: COMPILER_TYPE_SIGNAL, valueText };
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
function buildClassCode(className: string, properties: AnalyzedProperty[], ns: string): string {
|
|
@@ -79,18 +79,18 @@ function buildClassCode(className: string, properties: AnalyzedProperty[], ns: s
|
|
|
79
79
|
for (let i = 0, n = properties.length; i < n; i++) {
|
|
80
80
|
let { key, type, valueText } = properties[i];
|
|
81
81
|
|
|
82
|
-
if (type ===
|
|
82
|
+
if (type === COMPILER_TYPE_SIGNAL) {
|
|
83
83
|
let param = `_v${paramCounter++}`;
|
|
84
84
|
|
|
85
85
|
fields.push(`#${key} = ${ns}.signal(${valueText});`);
|
|
86
86
|
accessors.push(`get ${key}() { return ${ns}.read(this.#${key}); }`);
|
|
87
87
|
accessors.push(`set ${key}(${param}) { ${ns}.write(this.#${key}, ${param}); }`);
|
|
88
88
|
}
|
|
89
|
-
else if (type ===
|
|
89
|
+
else if (type === COMPILER_TYPE_ARRAY) {
|
|
90
90
|
fields.push(`${key} = new ${ns}.ReactiveArray(${valueText});`);
|
|
91
91
|
disposeStatements.push(`this.${key}.dispose();`);
|
|
92
92
|
}
|
|
93
|
-
else if (type ===
|
|
93
|
+
else if (type === COMPILER_TYPE_COMPUTED) {
|
|
94
94
|
fields.push(`#${key} = null;`);
|
|
95
95
|
accessors.push(`get ${key}() { return ${ns}.read(this.#${key} ??= ${ns}.computed(${valueText})); }`);
|
|
96
96
|
disposeStatements.push(`if (this.#${key}) ${ns}.dispose(this.#${key});`);
|
|
@@ -167,8 +167,8 @@ function visit(ctx: TransformContext, node: ts.Node): void {
|
|
|
167
167
|
|
|
168
168
|
properties.push(analyzed);
|
|
169
169
|
|
|
170
|
-
if (analyzed.type ===
|
|
171
|
-
ctx.bindings.set(`${varName}.${analyzed.key}`,
|
|
170
|
+
if (analyzed.type === COMPILER_TYPE_ARRAY && varName) {
|
|
171
|
+
ctx.bindings.set(`${varName}.${analyzed.key}`, COMPILER_TYPE_ARRAY);
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ts } from '@esportsplus/typescript';
|
|
2
2
|
import { code as c, type Range, type Replacement } from '@esportsplus/typescript/transformer';
|
|
3
3
|
import type { BindingType, Bindings } from '~/types';
|
|
4
|
-
import {
|
|
4
|
+
import { COMPILER_TYPE_COMPUTED, COMPILER_ENTRYPOINT, COMPILER_TYPE_SIGNAL, PACKAGE } from '~/constants';
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
interface ArgContext {
|
|
@@ -51,14 +51,14 @@ let COMPOUND_OPERATORS = new Map<ts.SyntaxKind, string>([
|
|
|
51
51
|
|
|
52
52
|
function classifyReactiveArg(arg: ts.Expression): BindingType | null {
|
|
53
53
|
if (ts.isArrowFunction(arg) || ts.isFunctionExpression(arg)) {
|
|
54
|
-
return
|
|
54
|
+
return COMPILER_TYPE_COMPUTED;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
if (ts.isObjectLiteralExpression(arg) || ts.isArrayLiteralExpression(arg)) {
|
|
58
58
|
return null;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
return
|
|
61
|
+
return COMPILER_TYPE_SIGNAL;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
function findBinding(bindings: ScopeBinding[], name: string, node: ts.Node): ScopeBinding | undefined {
|
|
@@ -137,7 +137,7 @@ function isReactiveReassignment(node: ts.Node): boolean {
|
|
|
137
137
|
parent.right === node &&
|
|
138
138
|
ts.isCallExpression(node) &&
|
|
139
139
|
ts.isIdentifier((node as ts.CallExpression).expression) &&
|
|
140
|
-
((node as ts.CallExpression).expression as ts.Identifier).text ===
|
|
140
|
+
((node as ts.CallExpression).expression as ts.Identifier).text === COMPILER_ENTRYPOINT
|
|
141
141
|
) {
|
|
142
142
|
return true;
|
|
143
143
|
}
|
|
@@ -181,7 +181,7 @@ function visit(ctx: TransformContext, node: ts.Node): void {
|
|
|
181
181
|
|
|
182
182
|
if (clause?.namedBindings && ts.isNamedImports(clause.namedBindings)) {
|
|
183
183
|
for (let i = 0, n = clause.namedBindings.elements.length; i < n; i++) {
|
|
184
|
-
if (clause.namedBindings.elements[i].name.text ===
|
|
184
|
+
if (clause.namedBindings.elements[i].name.text === COMPILER_ENTRYPOINT) {
|
|
185
185
|
ctx.hasReactiveImport = true;
|
|
186
186
|
break;
|
|
187
187
|
}
|
|
@@ -193,7 +193,7 @@ function visit(ctx: TransformContext, node: ts.Node): void {
|
|
|
193
193
|
ctx.hasReactiveImport &&
|
|
194
194
|
ts.isCallExpression(node) &&
|
|
195
195
|
ts.isIdentifier(node.expression) &&
|
|
196
|
-
node.expression.text ===
|
|
196
|
+
node.expression.text === COMPILER_ENTRYPOINT &&
|
|
197
197
|
node.arguments.length > 0
|
|
198
198
|
) {
|
|
199
199
|
let arg = node.arguments[0],
|
|
@@ -221,7 +221,7 @@ function visit(ctx: TransformContext, node: ts.Node): void {
|
|
|
221
221
|
ctx.bindings.set(varName, classification);
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
if (classification ===
|
|
224
|
+
if (classification === COMPILER_TYPE_COMPUTED) {
|
|
225
225
|
let argStart = arg.getStart(ctx.sourceFile);
|
|
226
226
|
|
|
227
227
|
ctx.computedArgRanges.push({ end: arg.end, start: argStart });
|
|
@@ -278,7 +278,7 @@ function visit(ctx: TransformContext, node: ts.Node): void {
|
|
|
278
278
|
let writeCtx = isWriteContext(node);
|
|
279
279
|
|
|
280
280
|
if (writeCtx) {
|
|
281
|
-
if (binding.type !==
|
|
281
|
+
if (binding.type !== COMPILER_TYPE_COMPUTED) {
|
|
282
282
|
let parent = node.parent;
|
|
283
283
|
|
|
284
284
|
if (writeCtx === 'simple' && ts.isBinaryExpression(parent)) {
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { code as c } from '@esportsplus/typescript/transformer';
|
|
2
|
-
import { ts } from '@esportsplus/typescript';
|
|
3
|
-
import { COMPILATION_ENTRYPOINT, COMPILATION_ENTRYPOINT_REGEX } from '../constants.js';
|
|
4
|
-
function visit(ctx, node) {
|
|
5
|
-
if (ctx.imported && ctx.used) {
|
|
6
|
-
return;
|
|
7
|
-
}
|
|
8
|
-
if (ts.isImportDeclaration(node) &&
|
|
9
|
-
node.importClause?.namedBindings &&
|
|
10
|
-
ts.isNamedImports(node.importClause.namedBindings)) {
|
|
11
|
-
let elements = node.importClause.namedBindings.elements;
|
|
12
|
-
for (let i = 0, n = elements.length; i < n; i++) {
|
|
13
|
-
let element = elements[i];
|
|
14
|
-
if ((element.propertyName?.text ?? element.name.text) === COMPILATION_ENTRYPOINT) {
|
|
15
|
-
ctx.imported = true;
|
|
16
|
-
break;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
if (ts.isCallExpression(node) &&
|
|
21
|
-
ts.isIdentifier(node.expression) &&
|
|
22
|
-
node.expression.text === COMPILATION_ENTRYPOINT) {
|
|
23
|
-
ctx.used = true;
|
|
24
|
-
}
|
|
25
|
-
ts.forEachChild(node, n => visit(ctx, n));
|
|
26
|
-
}
|
|
27
|
-
const contains = (code) => {
|
|
28
|
-
if (!c.contains(code, { regex: COMPILATION_ENTRYPOINT_REGEX })) {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
let ctx = {
|
|
32
|
-
imported: false,
|
|
33
|
-
used: false
|
|
34
|
-
};
|
|
35
|
-
visit(ctx, ts.createSourceFile('detect.ts', code, ts.ScriptTarget.Latest, false));
|
|
36
|
-
return ctx.imported && ctx.used;
|
|
37
|
-
};
|
|
38
|
-
export { contains };
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { code as c } from '@esportsplus/typescript/transformer';
|
|
2
|
-
import { ts } from '@esportsplus/typescript';
|
|
3
|
-
import { COMPILATION_ENTRYPOINT, COMPILATION_ENTRYPOINT_REGEX } from '~/constants';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
function visit(ctx: { imported: boolean; used: boolean; }, node: ts.Node): void {
|
|
7
|
-
if (ctx.imported && ctx.used) {
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
if (
|
|
12
|
-
ts.isImportDeclaration(node) &&
|
|
13
|
-
node.importClause?.namedBindings &&
|
|
14
|
-
ts.isNamedImports(node.importClause.namedBindings)
|
|
15
|
-
) {
|
|
16
|
-
let elements = node.importClause.namedBindings.elements;
|
|
17
|
-
|
|
18
|
-
for (let i = 0, n = elements.length; i < n; i++) {
|
|
19
|
-
let element = elements[i];
|
|
20
|
-
|
|
21
|
-
if ((element.propertyName?.text ?? element.name.text) === COMPILATION_ENTRYPOINT) {
|
|
22
|
-
ctx.imported = true;
|
|
23
|
-
break;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (
|
|
29
|
-
ts.isCallExpression(node) &&
|
|
30
|
-
ts.isIdentifier(node.expression) &&
|
|
31
|
-
node.expression.text === COMPILATION_ENTRYPOINT
|
|
32
|
-
) {
|
|
33
|
-
ctx.used = true;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
ts.forEachChild(node, n => visit(ctx, n));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const contains = (code: string): boolean => {
|
|
41
|
-
if (!c.contains(code, { regex: COMPILATION_ENTRYPOINT_REGEX })) {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
let ctx = {
|
|
46
|
-
imported: false,
|
|
47
|
-
used: false
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
visit(ctx, ts.createSourceFile('detect.ts', code, ts.ScriptTarget.Latest, false));
|
|
51
|
-
|
|
52
|
-
return ctx.imported && ctx.used;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
export { contains };
|