@nudojs/cli 0.2.1 → 0.3.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/dist/{chunk-3HCPXPEW.js → chunk-YDM4HHQ4.js} +1783 -1421
- package/dist/evaluator-api.d.ts +12 -1
- package/dist/evaluator-api.js +52 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +366 -3572
- package/package.json +23 -11
- package/CHANGELOG.md +0 -41
- 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/builtin-intl.ts +0 -17
- package/src/builtins/builtin-map.ts +0 -174
- package/src/builtins/builtin-promise.ts +0 -116
- package/src/builtins/builtin-reflect.ts +0 -30
- package/src/builtins/builtin-regexp.ts +0 -34
- package/src/builtins/builtin-set.ts +0 -131
- package/src/builtins/builtin-symbol.ts +0 -16
- package/src/builtins/builtin-url.ts +0 -58
- package/src/builtins/builtin-weak.ts +0 -22
- package/src/builtins/builtin-web.ts +0 -111
- package/src/builtins/index.ts +0 -61
- package/src/config.ts +0 -32
- package/src/env-loader.ts +0 -174
- package/src/evaluator-api.ts +0 -36
- package/src/evaluator.ts +0 -5623
- package/src/index.ts +0 -931
- package/src/narrowing.ts +0 -537
- package/src/resolve-npm.ts +0 -63
- package/tsconfig.json +0 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nudojs/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "CLI and evaluator API for the Nudo type inference engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,14 +12,24 @@
|
|
|
12
12
|
"dts",
|
|
13
13
|
"abstract-interpretation"
|
|
14
14
|
],
|
|
15
|
-
"main": "
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
16
17
|
"exports": {
|
|
17
|
-
".":
|
|
18
|
-
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./evaluator": {
|
|
23
|
+
"types": "./dist/evaluator-api.d.ts",
|
|
24
|
+
"default": "./dist/evaluator-api.js"
|
|
25
|
+
}
|
|
19
26
|
},
|
|
20
27
|
"bin": {
|
|
21
|
-
"nudo": "
|
|
28
|
+
"nudo": "./dist/index.js"
|
|
22
29
|
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
23
33
|
"repository": {
|
|
24
34
|
"type": "git",
|
|
25
35
|
"url": "git+https://github.com/nudojs/nudo.git",
|
|
@@ -33,13 +43,15 @@
|
|
|
33
43
|
"registry": "https://registry.npmjs.org"
|
|
34
44
|
},
|
|
35
45
|
"dependencies": {
|
|
36
|
-
"
|
|
37
|
-
"@nudojs/
|
|
38
|
-
"@nudojs/
|
|
39
|
-
"@nudojs/env": "0.2.
|
|
40
|
-
"@nudojs/
|
|
46
|
+
"commander": "^13.0.0",
|
|
47
|
+
"@nudojs/core": "0.3.1",
|
|
48
|
+
"@nudojs/parser": "0.3.1",
|
|
49
|
+
"@nudojs/env": "0.2.2",
|
|
50
|
+
"@nudojs/service": "0.3.1",
|
|
51
|
+
"@nudojs/harvester": "0.2.1"
|
|
41
52
|
},
|
|
42
53
|
"scripts": {
|
|
43
|
-
"build": "tsup
|
|
54
|
+
"build": "tsup",
|
|
55
|
+
"build:lib": "tsup src/evaluator-api.ts --format esm --dts"
|
|
44
56
|
}
|
|
45
57
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# nudo
|
|
2
|
-
|
|
3
|
-
## 0.2.1
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- 0fd0718: Merge the three environment packages into one: `@nudojs/env-es`, `@nudojs/env-web`, `@nudojs/env-node` are replaced by a single `@nudojs/env` package with subpath exports `@nudojs/env/es`, `@nudojs/env/web`, `@nudojs/env/node`.
|
|
8
|
-
|
|
9
|
-
Move agent-facing tools from the standalone MCP server into the language server: `@nudojs/mcp` is removed. `@nudojs/lsp` now exposes `nudo.whatIf`, `nudo.suggestCase`, `nudo.trace`, `nudo.selectCase`, and `nudo.getActiveCases` via `workspace/executeCommand` (custom-request aliases `nudo/whatIf` etc. included), adds pull-mode diagnostics, and works on files that are not open in the editor (disk fallback). `nudo.whatIf` now actually applies the given type bindings — previously they were ignored. AI agents connect through any LSP↔MCP bridge (cclsp, mcpls, agent-lsp) or a native LSP client; an installable agent skill ships at `packages/lsp/agent-skill/SKILL.md`.
|
|
10
|
-
|
|
11
|
-
- Updated dependencies [0fd0718]
|
|
12
|
-
- @nudojs/env@0.2.0
|
|
13
|
-
- @nudojs/service@0.2.1
|
|
14
|
-
|
|
15
|
-
## 0.2.0
|
|
16
|
-
|
|
17
|
-
### Minor Changes
|
|
18
|
-
|
|
19
|
-
- 6c38283: docs and ci
|
|
20
|
-
- 9f7f819: fix pkg info
|
|
21
|
-
- c175f71: version
|
|
22
|
-
|
|
23
|
-
### Patch Changes
|
|
24
|
-
|
|
25
|
-
- Updated dependencies [6c38283]
|
|
26
|
-
- Updated dependencies [9f7f819]
|
|
27
|
-
- Updated dependencies [c175f71]
|
|
28
|
-
- @nudojs/core@0.2.0
|
|
29
|
-
- @nudojs/parser@0.2.0
|
|
30
|
-
|
|
31
|
-
## 0.1.0
|
|
32
|
-
|
|
33
|
-
### Minor Changes
|
|
34
|
-
|
|
35
|
-
- Conceptual design and basic implementation.
|
|
36
|
-
|
|
37
|
-
### Patch Changes
|
|
38
|
-
|
|
39
|
-
- Updated dependencies
|
|
40
|
-
- @nudojs/core@0.1.0
|
|
41
|
-
- @nudojs/parser@0.1.0
|
package/examples/real-world.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @nudo:case "success" ({ status: 200, data: { name: "Alice", email: "alice@example.com" } })
|
|
3
|
-
* @nudo:case "not-found" ({ status: 404, error: "User not found" })
|
|
4
|
-
* @nudo:case "symbolic" (T.object)
|
|
5
|
-
*/
|
|
6
|
-
function handleUserResponse(response) {
|
|
7
|
-
if (response.status === 200) {
|
|
8
|
-
const user = response.data;
|
|
9
|
-
return { success: true, name: user.name, email: user.email };
|
|
10
|
-
}
|
|
11
|
-
if (response.status === 404) {
|
|
12
|
-
return { success: false, error: response.error };
|
|
13
|
-
}
|
|
14
|
-
return { success: false, error: "Unknown error" };
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @nudo:case "admin" ({ role: "admin", permissions: ["read", "write", "delete"] })
|
|
19
|
-
* @nudo:case "user" ({ role: "user", permissions: ["read"] })
|
|
20
|
-
* @nudo:case "guest" ({ role: "guest" })
|
|
21
|
-
*/
|
|
22
|
-
function checkAccess(user) {
|
|
23
|
-
switch (user.role) {
|
|
24
|
-
case "admin":
|
|
25
|
-
return { allowed: true, level: "full" };
|
|
26
|
-
case "user":
|
|
27
|
-
return { allowed: true, level: "limited" };
|
|
28
|
-
case "guest":
|
|
29
|
-
return { allowed: false, level: "none" };
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @nudo:case "complete" ({ name: "Task 1", dueDate: "2025-01-01", priority: "high" })
|
|
35
|
-
* @nudo:case "no-date" ({ name: "Task 2", priority: "low" })
|
|
36
|
-
* @nudo:case "symbolic" (T.object)
|
|
37
|
-
*/
|
|
38
|
-
function formatTask(task) {
|
|
39
|
-
const name = task.name ?? "Untitled";
|
|
40
|
-
const date = task.dueDate?.slice(0, 10) ?? "No due date";
|
|
41
|
-
const priority = task.priority || "medium";
|
|
42
|
-
return `${name} (${priority}) - ${date}`;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @nudo:case "string-array" (["hello", "world"])
|
|
47
|
-
* @nudo:case "number-array" ([1, 2, 3])
|
|
48
|
-
* @nudo:case "mixed" ([1, "two", true])
|
|
49
|
-
*/
|
|
50
|
-
function firstElement(arr) {
|
|
51
|
-
if (!Array.isArray(arr)) return null;
|
|
52
|
-
if (arr.length === 0) return null;
|
|
53
|
-
return arr[0];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @nudo:case "http" ({ protocol: "http", host: "example.com", port: 80 })
|
|
58
|
-
* @nudo:case "https" ({ protocol: "https", host: "secure.com", port: 443 })
|
|
59
|
-
*/
|
|
60
|
-
function buildUrl(config) {
|
|
61
|
-
if ("protocol" in config && "host" in config) {
|
|
62
|
-
const port = config.port ? `:${config.port}` : "";
|
|
63
|
-
return `${config.protocol}://${config.host}${port}`;
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Real-world scenario validation script
|
|
3
|
-
* Tests all new features against realistic JavaScript patterns
|
|
4
|
-
*/
|
|
5
|
-
import { parse, extractDirectives, type CaseDirective } from "@nudojs/parser";
|
|
6
|
-
import { typeValueToString, createEnvironment } from "@nudojs/core";
|
|
7
|
-
import { evaluateFunctionFull } from "../src/evaluator.js";
|
|
8
|
-
|
|
9
|
-
const realWorldCode = `
|
|
10
|
-
/**
|
|
11
|
-
* @nudo:case "success" ({ status: 200, data: { name: "Alice", email: "alice@example.com" } })
|
|
12
|
-
* @nudo:case "not-found" ({ status: 404, error: "User not found" })
|
|
13
|
-
* @nudo:case "symbolic" (T.object)
|
|
14
|
-
*/
|
|
15
|
-
function handleUserResponse(response) {
|
|
16
|
-
if (response.status === 200) {
|
|
17
|
-
const user = response.data;
|
|
18
|
-
return { success: true, name: user.name, email: user.email };
|
|
19
|
-
}
|
|
20
|
-
if (response.status === 404) {
|
|
21
|
-
return { success: false, error: response.error };
|
|
22
|
-
}
|
|
23
|
-
return { success: false, error: "Unknown error" };
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @nudo:case "admin" ({ role: "admin", permissions: ["read", "write", "delete"] })
|
|
28
|
-
* @nudo:case "user" ({ role: "user", permissions: ["read"] })
|
|
29
|
-
* @nudo:case "guest" ({ role: "guest" })
|
|
30
|
-
*/
|
|
31
|
-
function checkAccess(user) {
|
|
32
|
-
switch (user.role) {
|
|
33
|
-
case "admin":
|
|
34
|
-
return { allowed: true, level: "full" };
|
|
35
|
-
case "user":
|
|
36
|
-
return { allowed: true, level: "limited" };
|
|
37
|
-
case "guest":
|
|
38
|
-
return { allowed: false, level: "none" };
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @nudo:case "complete" ({ name: "Task 1", dueDate: "2025-01-01", priority: "high" })
|
|
44
|
-
* @nudo:case "no-date" ({ name: "Task 2", priority: "low" })
|
|
45
|
-
* @nudo:case "symbolic" (T.object)
|
|
46
|
-
*/
|
|
47
|
-
function formatTask(task) {
|
|
48
|
-
const name = task.name ?? "Untitled";
|
|
49
|
-
const date = task.dueDate?.slice(0, 10) ?? "No due date";
|
|
50
|
-
const priority = task.priority || "medium";
|
|
51
|
-
return \`\${name} (\${priority}) - \${date}\`;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @nudo:case "string-array" (["hello", "world"])
|
|
56
|
-
* @nudo:case "number-array" ([1, 2, 3])
|
|
57
|
-
* @nudo:case "mixed" ([1, "two", true])
|
|
58
|
-
*/
|
|
59
|
-
function firstElement(arr) {
|
|
60
|
-
if (!Array.isArray(arr)) return null;
|
|
61
|
-
if (arr.length === 0) return null;
|
|
62
|
-
return arr[0];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @nudo:case "http" ({ protocol: "http", host: "example.com", port: 80 })
|
|
67
|
-
* @nudo:case "https" ({ protocol: "https", host: "secure.com", port: 443 })
|
|
68
|
-
*/
|
|
69
|
-
function buildUrl(config) {
|
|
70
|
-
if ("protocol" in config && "host" in config) {
|
|
71
|
-
const port = config.port ? \`:\${config.port}\` : "";
|
|
72
|
-
return \`\${config.protocol}://\${config.host}\${port}\`;
|
|
73
|
-
}
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
`;
|
|
77
|
-
|
|
78
|
-
console.log("=== Real-World Scenario Validation ===\n");
|
|
79
|
-
|
|
80
|
-
// Test 1: Full inference pipeline
|
|
81
|
-
console.log("1. Full Inference Pipeline");
|
|
82
|
-
console.log("-".repeat(40));
|
|
83
|
-
const ast = parse(realWorldCode);
|
|
84
|
-
const directives = extractDirectives(ast);
|
|
85
|
-
const env = createEnvironment();
|
|
86
|
-
|
|
87
|
-
console.log(`Functions found: ${directives.length}`);
|
|
88
|
-
for (const fn of directives) {
|
|
89
|
-
const caseDirectives = fn.directives.filter((d): d is CaseDirective => d.kind === "case");
|
|
90
|
-
console.log(`\n ${fn.name}:`);
|
|
91
|
-
for (const dir of caseDirectives) {
|
|
92
|
-
const r = evaluateFunctionFull(fn.node, dir.args, env);
|
|
93
|
-
const argsStr = dir.args.map(typeValueToString).join(", ");
|
|
94
|
-
console.log(` Case "${dir.name}": (${argsStr}) => ${typeValueToString(r.value)}`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Test 2: Discriminated union narrowing
|
|
99
|
-
console.log("\n2. Discriminated Union Narrowing (response.status)");
|
|
100
|
-
console.log("-".repeat(40));
|
|
101
|
-
const handleResponseFn = directives.find(d => d.name === "handleUserResponse");
|
|
102
|
-
if (handleResponseFn) {
|
|
103
|
-
const caseDir = handleResponseFn.directives.find((d): d is CaseDirective => d.kind === "case" && d.name === "success");
|
|
104
|
-
if (caseDir) {
|
|
105
|
-
const r = evaluateFunctionFull(handleResponseFn.node, caseDir.args, env);
|
|
106
|
-
console.log(`handleUserResponse("success") => ${typeValueToString(r.value)}`);
|
|
107
|
-
const hasNarrowing = typeValueToString(r.value).includes("success") && typeValueToString(r.value).includes("name");
|
|
108
|
-
console.log(` Narrowing works: ${hasNarrowing ? "YES" : "NO"}`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Test 3: Switch statement narrowing
|
|
113
|
-
console.log("\n3. Switch Statement Narrowing (user.role)");
|
|
114
|
-
console.log("-".repeat(40));
|
|
115
|
-
const checkAccessFn = directives.find(d => d.name === "checkAccess");
|
|
116
|
-
if (checkAccessFn) {
|
|
117
|
-
const caseDirectives = checkAccessFn.directives.filter((d): d is CaseDirective => d.kind === "case");
|
|
118
|
-
for (const dir of caseDirectives) {
|
|
119
|
-
const r = evaluateFunctionFull(checkAccessFn.node, dir.args, env);
|
|
120
|
-
console.log(`checkAccess("${dir.name}") => ${typeValueToString(r.value)}`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Test 4: Optional chaining + nullish coalescing
|
|
125
|
-
console.log("\n4. Optional Chaining + Nullish Coalescing");
|
|
126
|
-
console.log("-".repeat(40));
|
|
127
|
-
const formatTaskFn = directives.find(d => d.name === "formatTask");
|
|
128
|
-
if (formatTaskFn) {
|
|
129
|
-
const caseDirectives = formatTaskFn.directives.filter((d): d is CaseDirective => d.kind === "case");
|
|
130
|
-
for (const dir of caseDirectives) {
|
|
131
|
-
const r = evaluateFunctionFull(formatTaskFn.node, dir.args, env);
|
|
132
|
-
console.log(`formatTask("${dir.name}") => ${typeValueToString(r.value)}`);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Test 5: Array.isArray narrowing
|
|
137
|
-
console.log("\n5. Array.isArray Narrowing");
|
|
138
|
-
console.log("-".repeat(40));
|
|
139
|
-
const firstElementFn = directives.find(d => d.name === "firstElement");
|
|
140
|
-
if (firstElementFn) {
|
|
141
|
-
const caseDirectives = firstElementFn.directives.filter((d): d is CaseDirective => d.kind === "case");
|
|
142
|
-
for (const dir of caseDirectives) {
|
|
143
|
-
const r = evaluateFunctionFull(firstElementFn.node, dir.args, env);
|
|
144
|
-
console.log(`firstElement("${dir.name}") => ${typeValueToString(r.value)}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Test 6: in operator narrowing
|
|
149
|
-
console.log("\n6. 'in' Operator Narrowing");
|
|
150
|
-
console.log("-".repeat(40));
|
|
151
|
-
const buildUrlFn = directives.find(d => d.name === "buildUrl");
|
|
152
|
-
if (buildUrlFn) {
|
|
153
|
-
const caseDirectives = buildUrlFn.directives.filter((d): d is CaseDirective => d.kind === "case");
|
|
154
|
-
for (const dir of caseDirectives) {
|
|
155
|
-
const r = evaluateFunctionFull(buildUrlFn.node, dir.args, env);
|
|
156
|
-
console.log(`buildUrl("${dir.name}") => ${typeValueToString(r.value)}`);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
console.log("\n=== Validation Complete ===");
|
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { parse, extractDirectives, type CaseDirective } from "@nudojs/parser";
|
|
3
|
-
import { typeValueToString, createEnvironment, T } 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({ name: fn.name, caseName: dir.name, result: typeValueToString(result.value) });
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return results;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
describe("Built-in Symbol API", () => {
|
|
23
|
-
it("Symbol.for(key) should return symbol", () => {
|
|
24
|
-
const results = runTest(`
|
|
25
|
-
// @nudo:case "for" ()
|
|
26
|
-
function fn() {
|
|
27
|
-
return Symbol.for("key");
|
|
28
|
-
}
|
|
29
|
-
`);
|
|
30
|
-
expect(results[0].result).toBe("symbol");
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("Symbol.iterator should return symbol", () => {
|
|
34
|
-
const results = runTest(`
|
|
35
|
-
// @nudo:case "iterator" ()
|
|
36
|
-
function fn() {
|
|
37
|
-
return Symbol.iterator;
|
|
38
|
-
}
|
|
39
|
-
`);
|
|
40
|
-
expect(results[0].result).toBe("symbol");
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("Symbol.asyncIterator should return symbol", () => {
|
|
44
|
-
const results = runTest(`
|
|
45
|
-
// @nudo:case "asyncIterator" ()
|
|
46
|
-
function fn() {
|
|
47
|
-
return Symbol.asyncIterator;
|
|
48
|
-
}
|
|
49
|
-
`);
|
|
50
|
-
expect(results[0].result).toBe("symbol");
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("Symbol.toStringTag should return symbol", () => {
|
|
54
|
-
const results = runTest(`
|
|
55
|
-
// @nudo:case "toStringTag" ()
|
|
56
|
-
function fn() {
|
|
57
|
-
return Symbol.toStringTag;
|
|
58
|
-
}
|
|
59
|
-
`);
|
|
60
|
-
expect(results[0].result).toBe("symbol");
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("Symbol.hasInstance should return symbol", () => {
|
|
64
|
-
const results = runTest(`
|
|
65
|
-
// @nudo:case "hasInstance" ()
|
|
66
|
-
function fn() {
|
|
67
|
-
return Symbol.hasInstance;
|
|
68
|
-
}
|
|
69
|
-
`);
|
|
70
|
-
expect(results[0].result).toBe("symbol");
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
describe("Built-in Reflect API", () => {
|
|
75
|
-
it("Reflect.has(obj, key) should return boolean", () => {
|
|
76
|
-
const results = runTest(`
|
|
77
|
-
// @nudo:case "has" ()
|
|
78
|
-
function fn() {
|
|
79
|
-
return Reflect.has({ a: 1 }, "a");
|
|
80
|
-
}
|
|
81
|
-
`);
|
|
82
|
-
expect(results[0].result).toBe("boolean");
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("Reflect.get(obj, key) should return unknown", () => {
|
|
86
|
-
const results = runTest(`
|
|
87
|
-
// @nudo:case "get" ()
|
|
88
|
-
function fn() {
|
|
89
|
-
return Reflect.get({ a: 1 }, "a");
|
|
90
|
-
}
|
|
91
|
-
`);
|
|
92
|
-
expect(results[0].result).toBe("unknown");
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("Reflect.set(obj, key, value) should return boolean", () => {
|
|
96
|
-
const results = runTest(`
|
|
97
|
-
// @nudo:case "set" ()
|
|
98
|
-
function fn() {
|
|
99
|
-
return Reflect.set({}, "a", 1);
|
|
100
|
-
}
|
|
101
|
-
`);
|
|
102
|
-
expect(results[0].result).toBe("boolean");
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it("Reflect.deleteProperty(obj, key) should return boolean", () => {
|
|
106
|
-
const results = runTest(`
|
|
107
|
-
// @nudo:case "deleteProperty" ()
|
|
108
|
-
function fn() {
|
|
109
|
-
return Reflect.deleteProperty({ a: 1 }, "a");
|
|
110
|
-
}
|
|
111
|
-
`);
|
|
112
|
-
expect(results[0].result).toBe("boolean");
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it("Reflect.ownKeys(obj) should list known own keys, string[] otherwise", () => {
|
|
116
|
-
const results = runTest(`
|
|
117
|
-
// @nudo:case "ownKeys" ()
|
|
118
|
-
function fn() {
|
|
119
|
-
return Reflect.ownKeys({ a: 1, b: 2 });
|
|
120
|
-
}
|
|
121
|
-
`);
|
|
122
|
-
expect(results[0].result).toBe('["a", "b"]');
|
|
123
|
-
|
|
124
|
-
const symbolic = runTest(`
|
|
125
|
-
// @nudo:case "ownKeys-symbolic" (obj)
|
|
126
|
-
function fn(obj) {
|
|
127
|
-
return Reflect.ownKeys(obj);
|
|
128
|
-
}
|
|
129
|
-
`);
|
|
130
|
-
expect(symbolic[0].result).toBe("string[]");
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it("Reflect.getPrototypeOf(obj) should return {} | null", () => {
|
|
134
|
-
const results = runTest(`
|
|
135
|
-
// @nudo:case "getPrototypeOf" ()
|
|
136
|
-
function fn() {
|
|
137
|
-
return Reflect.getPrototypeOf({});
|
|
138
|
-
}
|
|
139
|
-
`);
|
|
140
|
-
expect(results[0].result).toContain("{}");
|
|
141
|
-
expect(results[0].result).toContain("null");
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
describe("Built-in Intl API", () => {
|
|
146
|
-
it("new Intl.DateTimeFormat() instance", () => {
|
|
147
|
-
const results = runTest(`
|
|
148
|
-
// @nudo:case "new-datetimeformat" ()
|
|
149
|
-
function fn() {
|
|
150
|
-
const fmt = new Intl.DateTimeFormat();
|
|
151
|
-
return fmt;
|
|
152
|
-
}
|
|
153
|
-
`);
|
|
154
|
-
expect(results[0].result).toContain("DateTimeFormat");
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it("new Intl.DateTimeFormat().format() should return string", () => {
|
|
158
|
-
const results = runTest(`
|
|
159
|
-
// @nudo:case "format" ()
|
|
160
|
-
function fn() {
|
|
161
|
-
const fmt = new Intl.DateTimeFormat();
|
|
162
|
-
return fmt.format();
|
|
163
|
-
}
|
|
164
|
-
`);
|
|
165
|
-
expect(results[0].result).toBe("string");
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it("new Intl.NumberFormat() instance", () => {
|
|
169
|
-
const results = runTest(`
|
|
170
|
-
// @nudo:case "new-numberformat" ()
|
|
171
|
-
function fn() {
|
|
172
|
-
const fmt = new Intl.NumberFormat();
|
|
173
|
-
return fmt;
|
|
174
|
-
}
|
|
175
|
-
`);
|
|
176
|
-
expect(results[0].result).toContain("NumberFormat");
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it("new Intl.NumberFormat().format() should return string", () => {
|
|
180
|
-
const results = runTest(`
|
|
181
|
-
// @nudo:case "format" ()
|
|
182
|
-
function fn() {
|
|
183
|
-
const fmt = new Intl.NumberFormat();
|
|
184
|
-
return fmt.format();
|
|
185
|
-
}
|
|
186
|
-
`);
|
|
187
|
-
expect(results[0].result).toBe("string");
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
describe("Built-in WeakMap API", () => {
|
|
192
|
-
it("new WeakMap() should return WeakMap instance", () => {
|
|
193
|
-
const results = runTest(`
|
|
194
|
-
// @nudo:case "new-weakmap" ()
|
|
195
|
-
function fn() {
|
|
196
|
-
const wm = new WeakMap();
|
|
197
|
-
return wm;
|
|
198
|
-
}
|
|
199
|
-
`);
|
|
200
|
-
expect(results[0].result).toContain("WeakMap");
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it("weakMap.get() should return unknown", () => {
|
|
204
|
-
const results = runTest(`
|
|
205
|
-
// @nudo:case "get" ()
|
|
206
|
-
function fn() {
|
|
207
|
-
const wm = new WeakMap();
|
|
208
|
-
return wm.get({});
|
|
209
|
-
}
|
|
210
|
-
`);
|
|
211
|
-
expect(results[0].result).toBe("unknown");
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it("weakMap.set() should return WeakMap instance", () => {
|
|
215
|
-
const results = runTest(`
|
|
216
|
-
// @nudo:case "set" ()
|
|
217
|
-
function fn() {
|
|
218
|
-
const wm = new WeakMap();
|
|
219
|
-
return wm.set({}, "value");
|
|
220
|
-
}
|
|
221
|
-
`);
|
|
222
|
-
expect(results[0].result).toContain("WeakMap");
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it("weakMap.has() should return boolean", () => {
|
|
226
|
-
const results = runTest(`
|
|
227
|
-
// @nudo:case "has" ()
|
|
228
|
-
function fn() {
|
|
229
|
-
const wm = new WeakMap();
|
|
230
|
-
return wm.has({});
|
|
231
|
-
}
|
|
232
|
-
`);
|
|
233
|
-
expect(results[0].result).toBe("boolean");
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it("weakMap.delete() should return boolean", () => {
|
|
237
|
-
const results = runTest(`
|
|
238
|
-
// @nudo:case "delete" ()
|
|
239
|
-
function fn() {
|
|
240
|
-
const wm = new WeakMap();
|
|
241
|
-
return wm.delete({});
|
|
242
|
-
}
|
|
243
|
-
`);
|
|
244
|
-
expect(results[0].result).toBe("boolean");
|
|
245
|
-
});
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
describe("Built-in WeakSet API", () => {
|
|
249
|
-
it("new WeakSet() should return WeakSet instance", () => {
|
|
250
|
-
const results = runTest(`
|
|
251
|
-
// @nudo:case "new-weakset" ()
|
|
252
|
-
function fn() {
|
|
253
|
-
const ws = new WeakSet();
|
|
254
|
-
return ws;
|
|
255
|
-
}
|
|
256
|
-
`);
|
|
257
|
-
expect(results[0].result).toContain("WeakSet");
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it("weakSet.add() should return WeakSet instance", () => {
|
|
261
|
-
const results = runTest(`
|
|
262
|
-
// @nudo:case "add" ()
|
|
263
|
-
function fn() {
|
|
264
|
-
const ws = new WeakSet();
|
|
265
|
-
return ws.add({});
|
|
266
|
-
}
|
|
267
|
-
`);
|
|
268
|
-
expect(results[0].result).toContain("WeakSet");
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it("weakSet.has() should return boolean", () => {
|
|
272
|
-
const results = runTest(`
|
|
273
|
-
// @nudo:case "has" ()
|
|
274
|
-
function fn() {
|
|
275
|
-
const ws = new WeakSet();
|
|
276
|
-
return ws.has({});
|
|
277
|
-
}
|
|
278
|
-
`);
|
|
279
|
-
expect(results[0].result).toBe("boolean");
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it("weakSet.delete() should return boolean", () => {
|
|
283
|
-
const results = runTest(`
|
|
284
|
-
// @nudo:case "delete" ()
|
|
285
|
-
function fn() {
|
|
286
|
-
const ws = new WeakSet();
|
|
287
|
-
return ws.delete({});
|
|
288
|
-
}
|
|
289
|
-
`);
|
|
290
|
-
expect(results[0].result).toBe("boolean");
|
|
291
|
-
});
|
|
292
|
-
});
|