@nudojs/cli 0.2.1 → 0.3.0
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/package.json +12 -7
- package/src/abs-route.ts +273 -0
- package/src/builtins/builtin-prototype.ts +279 -0
- package/src/builtins/builtin-static.ts +260 -0
- package/src/eval-binary.ts +113 -0
- package/src/evaluator-api.ts +3 -0
- package/src/evaluator.ts +174 -633
- package/src/index.ts +373 -270
- package/src/narrowing.ts +7 -0
- package/src/phi-from-test.ts +42 -0
- package/src/run-test.ts +92 -0
- package/src/term-registry.ts +96 -0
- package/CHANGELOG.md +0 -41
- package/dist/chunk-3HCPXPEW.js +0 -5286
- package/dist/evaluator-api.d.ts +0 -151
- package/dist/evaluator-api.js +0 -214
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -4035
- package/examples/real-world.js +0 -66
- package/examples/validate-real-world.ts +0 -160
- package/src/__tests__/builtin-advanced.test.ts +0 -292
- package/src/__tests__/builtin-api.test.ts +0 -308
- package/src/__tests__/builtin-functions.test.ts +0 -313
- package/src/__tests__/builtin-map.test.ts +0 -129
- package/src/__tests__/builtin-promise.test.ts +0 -150
- package/src/__tests__/builtin-regexp.test.ts +0 -133
- package/src/__tests__/builtin-set.test.ts +0 -163
- package/src/__tests__/builtin-url.test.ts +0 -256
- package/src/__tests__/builtin-web.test.ts +0 -340
- package/src/__tests__/combination-scenarios.test.ts +0 -384
- package/src/__tests__/edge-cases.test.ts +0 -749
- package/src/__tests__/evaluator-loops.test.ts +0 -283
- package/src/__tests__/evaluator-nullish-coalescing.test.ts +0 -86
- package/src/__tests__/evaluator-optional-chaining.test.ts +0 -37
- package/src/__tests__/evaluator-phase2.test.ts +0 -564
- package/src/__tests__/evaluator-phase3.test.ts +0 -864
- package/src/__tests__/evaluator-refined.test.ts +0 -121
- package/src/__tests__/evaluator-string-methods.test.ts +0 -151
- package/src/__tests__/evaluator.test.ts +0 -943
- package/src/__tests__/mock-arrow-function.test.ts +0 -169
- package/src/__tests__/mock-comparison.test.ts +0 -221
- package/src/__tests__/mock-comprehensive.test.ts +0 -250
- package/src/__tests__/mock-final-integration.test.ts +0 -263
- package/src/__tests__/mock-helpers.test.ts +0 -174
- package/src/__tests__/mock-realworld.test.ts +0 -191
- package/src/__tests__/mock-rest-debug.test.ts +0 -110
- package/src/__tests__/mock-rest-edge.test.ts +0 -176
- package/src/__tests__/mock-sinon-runtime.test.ts +0 -168
- package/src/__tests__/narrowing-discriminated.test.ts +0 -35
- package/src/__tests__/narrowing-in-operator.test.ts +0 -56
- package/src/__tests__/narrowing-switch.test.ts +0 -56
- package/src/__tests__/narrowing-truthiness.test.ts +0 -52
- package/src/__tests__/narrowing.test.ts +0 -82
- package/src/__tests__/nudo-mock-syntax.test.ts +0 -245
- package/src/__tests__/realworld-patterns.test.ts +0 -430
- package/src/__tests__/syntax-sugar.test.ts +0 -345
- package/src/builtins/index.ts +0 -61
- package/tsconfig.json +0 -9
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { parse, extractDirectives, type CaseDirective } from "@nudojs/parser";
|
|
3
|
-
import { typeValueToString, createEnvironment } from "@nudojs/core";
|
|
4
|
-
import { evaluateFunctionFull } from "../evaluator.js";
|
|
5
|
-
|
|
6
|
-
function runTest(source: string): { name: string; caseName: string; result: string }[] {
|
|
7
|
-
const ast = parse(source);
|
|
8
|
-
const directives = extractDirectives(ast);
|
|
9
|
-
const env = createEnvironment();
|
|
10
|
-
const results: { name: string; caseName: string; result: string }[] = [];
|
|
11
|
-
|
|
12
|
-
for (const fn of directives) {
|
|
13
|
-
const caseDirectives = fn.directives.filter((d): d is CaseDirective => d.kind === "case");
|
|
14
|
-
for (const dir of caseDirectives) {
|
|
15
|
-
const result = evaluateFunctionFull(fn.node, dir.args, env);
|
|
16
|
-
results.push({
|
|
17
|
-
name: fn.name,
|
|
18
|
-
caseName: dir.name,
|
|
19
|
-
result: typeValueToString(result.value),
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return results;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
describe("Syntax Sugar Tests", () => {
|
|
27
|
-
describe("Compound Assignment Operators", () => {
|
|
28
|
-
it("+=", () => {
|
|
29
|
-
const results = runTest(`
|
|
30
|
-
// @nudo:case "add-assign" ([1, 2, 3, 4, 5])
|
|
31
|
-
function sum(arr) {
|
|
32
|
-
let total = 0;
|
|
33
|
-
for (const n of arr) {
|
|
34
|
-
total += n;
|
|
35
|
-
}
|
|
36
|
-
return total;
|
|
37
|
-
}
|
|
38
|
-
`);
|
|
39
|
-
expect(results[0].result).toBe("15");
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("-=", () => {
|
|
43
|
-
const results = runTest(`
|
|
44
|
-
// @nudo:case "sub-assign" (100, [10, 20, 30])
|
|
45
|
-
function subtract(initial, values) {
|
|
46
|
-
let result = initial;
|
|
47
|
-
for (const v of values) {
|
|
48
|
-
result -= v;
|
|
49
|
-
}
|
|
50
|
-
return result;
|
|
51
|
-
}
|
|
52
|
-
`);
|
|
53
|
-
expect(results[0].result).toBe("40");
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("*=", () => {
|
|
57
|
-
const results = runTest(`
|
|
58
|
-
// @nudo:case "mul-assign" ([2, 3, 4])
|
|
59
|
-
function product(arr) {
|
|
60
|
-
let result = 1;
|
|
61
|
-
for (const n of arr) {
|
|
62
|
-
result *= n;
|
|
63
|
-
}
|
|
64
|
-
return result;
|
|
65
|
-
}
|
|
66
|
-
`);
|
|
67
|
-
expect(results[0].result).toBe("24");
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("/=", () => {
|
|
71
|
-
const results = runTest(`
|
|
72
|
-
// @nudo:case "div-assign" (1000, [2, 5])
|
|
73
|
-
function divide(initial, divisors) {
|
|
74
|
-
let result = initial;
|
|
75
|
-
for (const d of divisors) {
|
|
76
|
-
result /= d;
|
|
77
|
-
}
|
|
78
|
-
return result;
|
|
79
|
-
}
|
|
80
|
-
`);
|
|
81
|
-
expect(results[0].result).toBe("100");
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("%=", () => {
|
|
85
|
-
const results = runTest(`
|
|
86
|
-
// @nudo:case "mod-assign" (17, [5, 3])
|
|
87
|
-
function modChain(initial, divisors) {
|
|
88
|
-
let result = initial;
|
|
89
|
-
for (const d of divisors) {
|
|
90
|
-
result %= d;
|
|
91
|
-
}
|
|
92
|
-
return result;
|
|
93
|
-
}
|
|
94
|
-
`);
|
|
95
|
-
expect(results[0].result).toBe("2");
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("string +=", () => {
|
|
99
|
-
const results = runTest(`
|
|
100
|
-
// @nudo:case "concat-assign" (["Hello", " ", "World"])
|
|
101
|
-
function concat(parts) {
|
|
102
|
-
let result = "";
|
|
103
|
-
for (const part of parts) {
|
|
104
|
-
result += part;
|
|
105
|
-
}
|
|
106
|
-
return result;
|
|
107
|
-
}
|
|
108
|
-
`);
|
|
109
|
-
expect(results[0].result).toBe('"Hello World"');
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
describe("Object Method Shorthand", () => {
|
|
114
|
-
it("basic method shorthand", () => {
|
|
115
|
-
const results = runTest(`
|
|
116
|
-
// @nudo:case "method" ()
|
|
117
|
-
function createObj() {
|
|
118
|
-
return {
|
|
119
|
-
greet(name) {
|
|
120
|
-
return "Hello, " + name;
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
`);
|
|
125
|
-
expect(results[0].result).toContain("greet");
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it("multiple methods", () => {
|
|
129
|
-
const results = runTest(`
|
|
130
|
-
// @nudo:case "methods" ()
|
|
131
|
-
function createCalculator() {
|
|
132
|
-
return {
|
|
133
|
-
add(a, b) { return a + b; },
|
|
134
|
-
subtract(a, b) { return a - b; },
|
|
135
|
-
multiply(a, b) { return a * b; }
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
`);
|
|
139
|
-
expect(results[0].result).toContain("add");
|
|
140
|
-
expect(results[0].result).toContain("subtract");
|
|
141
|
-
expect(results[0].result).toContain("multiply");
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("method with rest parameters", () => {
|
|
145
|
-
const results = runTest(`
|
|
146
|
-
// @nudo:case "rest-params" ()
|
|
147
|
-
function createLogger() {
|
|
148
|
-
return {
|
|
149
|
-
log(...args) {
|
|
150
|
-
return args;
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
`);
|
|
155
|
-
expect(results[0].result).toContain("log");
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it("mixed properties and methods", () => {
|
|
159
|
-
const results = runTest(`
|
|
160
|
-
// @nudo:case "mixed" ()
|
|
161
|
-
function createService() {
|
|
162
|
-
return {
|
|
163
|
-
name: "MyService",
|
|
164
|
-
version: 1,
|
|
165
|
-
start() { return "started"; },
|
|
166
|
-
stop() { return "stopped"; }
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
`);
|
|
170
|
-
expect(results[0].result).toContain("name");
|
|
171
|
-
expect(results[0].result).toContain("version");
|
|
172
|
-
expect(results[0].result).toContain("start");
|
|
173
|
-
expect(results[0].result).toContain("stop");
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
describe("Async/Await Combinations", () => {
|
|
178
|
-
it("async function returning literal", () => {
|
|
179
|
-
const results = runTest(`
|
|
180
|
-
// @nudo:case "async-literal" ()
|
|
181
|
-
async function getValue() {
|
|
182
|
-
return 42;
|
|
183
|
-
}
|
|
184
|
-
`);
|
|
185
|
-
expect(results[0].result).toBe("Promise<42>");
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it("async function returning Promise", () => {
|
|
189
|
-
const results = runTest(`
|
|
190
|
-
// @nudo:case "async-promise" ()
|
|
191
|
-
async function getValue() {
|
|
192
|
-
return Promise.resolve(42);
|
|
193
|
-
}
|
|
194
|
-
`);
|
|
195
|
-
expect(results[0].result).toBe("Promise<42>");
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it("async function with await", () => {
|
|
199
|
-
const results = runTest(`
|
|
200
|
-
// @nudo:case "async-await" ()
|
|
201
|
-
async function getValue() {
|
|
202
|
-
const result = await Promise.resolve(42);
|
|
203
|
-
return result;
|
|
204
|
-
}
|
|
205
|
-
`);
|
|
206
|
-
expect(results[0].result).toBe("Promise<42>");
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it("async function with try/catch", () => {
|
|
210
|
-
const results = runTest(`
|
|
211
|
-
// @nudo:case "async-try-catch" ()
|
|
212
|
-
async function safeOperation() {
|
|
213
|
-
try {
|
|
214
|
-
const result = await Promise.resolve("success");
|
|
215
|
-
return { success: true, data: result };
|
|
216
|
-
} catch (e) {
|
|
217
|
-
return { success: false, error: "failed" };
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
`);
|
|
221
|
-
expect(results[0].result).toContain("Promise");
|
|
222
|
-
expect(results[0].result).toContain("success");
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it("async function with multiple awaits", () => {
|
|
226
|
-
const results = runTest(`
|
|
227
|
-
// @nudo:case "async-multi-await" ()
|
|
228
|
-
async function fetchAll() {
|
|
229
|
-
const a = await Promise.resolve(1);
|
|
230
|
-
const b = await Promise.resolve(2);
|
|
231
|
-
return [a, b];
|
|
232
|
-
}
|
|
233
|
-
`);
|
|
234
|
-
expect(results[0].result).toBe("Promise<[1, 2]>");
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
describe("Destructuring Patterns", () => {
|
|
239
|
-
it("object destructuring in parameters", () => {
|
|
240
|
-
const results = runTest(`
|
|
241
|
-
// @nudo:case "destructure-obj" ({ name: "Alice", age: 30 })
|
|
242
|
-
function greet({ name, age }) {
|
|
243
|
-
return name + " is " + age;
|
|
244
|
-
}
|
|
245
|
-
`);
|
|
246
|
-
expect(results[0].result).toBe('"Alice is 30"');
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it("array destructuring in parameters", () => {
|
|
250
|
-
const results = runTest(`
|
|
251
|
-
// @nudo:case "destructure-arr" ([1, 2, 3])
|
|
252
|
-
function sum([a, b, c]) {
|
|
253
|
-
return a + b + c;
|
|
254
|
-
}
|
|
255
|
-
`);
|
|
256
|
-
expect(results[0].result).toBe("6");
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
it("nested destructuring", () => {
|
|
260
|
-
const results = runTest(`
|
|
261
|
-
// @nudo:case "destructure-nested" ({ user: { name: "Alice", address: { city: "NYC" } } })
|
|
262
|
-
function getCity({ user: { address: { city } } }) {
|
|
263
|
-
return city;
|
|
264
|
-
}
|
|
265
|
-
`);
|
|
266
|
-
expect(results[0].result).toBe('"NYC"');
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
it("destructuring with defaults", () => {
|
|
270
|
-
const results = runTest(`
|
|
271
|
-
// @nudo:case "destructure-default" ({ name: "Alice" })
|
|
272
|
-
function greet({ name, greeting = "Hello" }) {
|
|
273
|
-
return greeting + ", " + name;
|
|
274
|
-
}
|
|
275
|
-
`);
|
|
276
|
-
expect(results[0].result).toBe('"Hello, Alice"');
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
describe("Template Literals", () => {
|
|
281
|
-
it("basic template literal", () => {
|
|
282
|
-
const results = runTest(`
|
|
283
|
-
// @nudo:case "template" ("World")
|
|
284
|
-
function greet(name) {
|
|
285
|
-
return \`Hello, \${name}!\`;
|
|
286
|
-
}
|
|
287
|
-
`);
|
|
288
|
-
expect(results[0].result).toBe('"Hello, World!"');
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
it("template literal with expressions", () => {
|
|
292
|
-
const results = runTest(`
|
|
293
|
-
// @nudo:case "template-expr" (2, 3)
|
|
294
|
-
function calculate(a, b) {
|
|
295
|
-
return \`\${a} + \${b} = \${a + b}\`;
|
|
296
|
-
}
|
|
297
|
-
`);
|
|
298
|
-
expect(results[0].result).toBe('"2 + 3 = 5"');
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
describe("Optional Chaining", () => {
|
|
303
|
-
it("basic optional chaining", () => {
|
|
304
|
-
const results = runTest(`
|
|
305
|
-
// @nudo:case "optional-chain" ({ user: { name: "Alice" } })
|
|
306
|
-
function getName(obj) {
|
|
307
|
-
return obj?.user?.name;
|
|
308
|
-
}
|
|
309
|
-
`);
|
|
310
|
-
expect(results[0].result).toBe('"Alice"');
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
it("optional chaining with undefined", () => {
|
|
314
|
-
const results = runTest(`
|
|
315
|
-
// @nudo:case "optional-undefined" ({})
|
|
316
|
-
function getName(obj) {
|
|
317
|
-
return obj?.user?.name;
|
|
318
|
-
}
|
|
319
|
-
`);
|
|
320
|
-
expect(results[0].result).toBe("undefined");
|
|
321
|
-
});
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
describe("Nullish Coalescing", () => {
|
|
325
|
-
it("basic nullish coalescing", () => {
|
|
326
|
-
const results = runTest(`
|
|
327
|
-
// @nudo:case "nullish" (null)
|
|
328
|
-
function getValue(x) {
|
|
329
|
-
return x ?? "default";
|
|
330
|
-
}
|
|
331
|
-
`);
|
|
332
|
-
expect(results[0].result).toBe('"default"');
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
it("nullish with defined value", () => {
|
|
336
|
-
const results = runTest(`
|
|
337
|
-
// @nudo:case "nullish-defined" ("hello")
|
|
338
|
-
function getValue(x) {
|
|
339
|
-
return x ?? "default";
|
|
340
|
-
}
|
|
341
|
-
`);
|
|
342
|
-
expect(results[0].result).toBe('"hello"');
|
|
343
|
-
});
|
|
344
|
-
});
|
|
345
|
-
});
|
package/src/builtins/index.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { type TypeValue } from "@nudojs/core";
|
|
2
|
-
import { PROMISE_STATIC_METHODS } from "./builtin-promise.ts";
|
|
3
|
-
import { MAP_INSTANCE_METHODS, createMapType } from "./builtin-map.ts";
|
|
4
|
-
import { SET_INSTANCE_METHODS, createSetType } from "./builtin-set.ts";
|
|
5
|
-
import { REGEXP_INSTANCE_METHODS, createRegExpType } from "./builtin-regexp.ts";
|
|
6
|
-
import { URL_INSTANCE_METHODS, URLSearchParams_INSTANCE_METHODS, createURLType, createURLSearchParamsType } from "./builtin-url.ts";
|
|
7
|
-
import {
|
|
8
|
-
RESPONSE_INSTANCE_METHODS,
|
|
9
|
-
HEADERS_INSTANCE_METHODS,
|
|
10
|
-
FORMDATA_INSTANCE_METHODS,
|
|
11
|
-
ABORTCONTROLLER_INSTANCE_METHODS,
|
|
12
|
-
createResponseType,
|
|
13
|
-
createHeadersType,
|
|
14
|
-
createFormDataType,
|
|
15
|
-
createAbortControllerType,
|
|
16
|
-
} from "./builtin-web.ts";
|
|
17
|
-
import { WEAKMAP_INSTANCE_METHODS, WEAKSET_INSTANCE_METHODS, createWeakMapType, createWeakSetType } from "./builtin-weak.ts";
|
|
18
|
-
import { SYMBOL_STATIC_METHODS, SYMBOL_STATIC_PROPS } from "./builtin-symbol.ts";
|
|
19
|
-
import { REFLECT_METHODS } from "./builtin-reflect.ts";
|
|
20
|
-
import { INTL_DATETIMEFORMAT_METHODS, INTL_NUMBERFORMAT_METHODS, createDateTimeFormatType, createNumberFormatType } from "./builtin-intl.ts";
|
|
21
|
-
|
|
22
|
-
export const ALL_STATIC_METHODS: Record<string, Record<string, TypeValue>> = {
|
|
23
|
-
Promise: PROMISE_STATIC_METHODS,
|
|
24
|
-
Symbol: SYMBOL_STATIC_METHODS,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const ALL_STATIC_PROPS: Record<string, Record<string, TypeValue>> = {
|
|
28
|
-
Symbol: SYMBOL_STATIC_PROPS,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export const ALL_INSTANCE_METHODS: Record<string, Record<string, (...args: TypeValue[]) => TypeValue>> = {
|
|
32
|
-
Map: MAP_INSTANCE_METHODS,
|
|
33
|
-
Set: SET_INSTANCE_METHODS,
|
|
34
|
-
RegExp: REGEXP_INSTANCE_METHODS,
|
|
35
|
-
URL: URL_INSTANCE_METHODS,
|
|
36
|
-
URLSearchParams: URLSearchParams_INSTANCE_METHODS,
|
|
37
|
-
Response: RESPONSE_INSTANCE_METHODS,
|
|
38
|
-
Headers: HEADERS_INSTANCE_METHODS,
|
|
39
|
-
FormData: FORMDATA_INSTANCE_METHODS,
|
|
40
|
-
AbortController: ABORTCONTROLLER_INSTANCE_METHODS,
|
|
41
|
-
WeakMap: WEAKMAP_INSTANCE_METHODS,
|
|
42
|
-
WeakSet: WEAKSET_INSTANCE_METHODS,
|
|
43
|
-
DateTimeFormat: INTL_DATETIMEFORMAT_METHODS,
|
|
44
|
-
NumberFormat: INTL_NUMBERFORMAT_METHODS,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export {
|
|
48
|
-
createMapType,
|
|
49
|
-
createSetType,
|
|
50
|
-
createRegExpType,
|
|
51
|
-
createURLType,
|
|
52
|
-
createURLSearchParamsType,
|
|
53
|
-
createResponseType,
|
|
54
|
-
createHeadersType,
|
|
55
|
-
createFormDataType,
|
|
56
|
-
createAbortControllerType,
|
|
57
|
-
createWeakMapType,
|
|
58
|
-
createWeakSetType,
|
|
59
|
-
createDateTimeFormatType,
|
|
60
|
-
createNumberFormatType,
|
|
61
|
-
};
|