json-as 1.2.0 → 1.2.2-beta.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.
Files changed (80) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/.github/FUNDING.yml +0 -1
  4. package/.github/dependabot.yml +0 -11
  5. package/.github/workflows/benchmark.yml +0 -72
  6. package/.github/workflows/release-package.yml +0 -47
  7. package/.github/workflows/tests.yml +0 -25
  8. package/.prettierignore +0 -9
  9. package/.prettierrc.json +0 -7
  10. package/.trunk/configs/.markdownlint.yaml +0 -2
  11. package/.trunk/configs/.shellcheckrc +0 -7
  12. package/.trunk/configs/.yamllint.yaml +0 -7
  13. package/.trunk/trunk.yaml +0 -37
  14. package/CHANGELOG.md +0 -330
  15. package/SECURITY.md +0 -32
  16. package/asconfig.json +0 -7
  17. package/assembly/__benches__/abc.bench.ts +0 -28
  18. package/assembly/__benches__/large.bench.ts +0 -238
  19. package/assembly/__benches__/lib/bench.ts +0 -85
  20. package/assembly/__benches__/medium.bench.ts +0 -128
  21. package/assembly/__benches__/small.bench.ts +0 -46
  22. package/assembly/__benches__/throughput.ts +0 -172
  23. package/assembly/__benches__/vec3.bench.ts +0 -37
  24. package/assembly/__tests__/arbitrary.spec.ts +0 -35
  25. package/assembly/__tests__/array.spec.ts +0 -145
  26. package/assembly/__tests__/bool.spec.ts +0 -12
  27. package/assembly/__tests__/box.spec.ts +0 -27
  28. package/assembly/__tests__/custom.spec.ts +0 -56
  29. package/assembly/__tests__/date.spec.ts +0 -36
  30. package/assembly/__tests__/enum.spec.ts +0 -35
  31. package/assembly/__tests__/float.spec.ts +0 -42
  32. package/assembly/__tests__/generics.spec.ts +0 -49
  33. package/assembly/__tests__/hierarchy.spec.ts +0 -61
  34. package/assembly/__tests__/integer.spec.ts +0 -26
  35. package/assembly/__tests__/lib/index.ts +0 -41
  36. package/assembly/__tests__/map.spec.ts +0 -7
  37. package/assembly/__tests__/namespace.spec.ts +0 -63
  38. package/assembly/__tests__/null.spec.ts +0 -12
  39. package/assembly/__tests__/raw.spec.ts +0 -23
  40. package/assembly/__tests__/resolving.spec.ts +0 -55
  41. package/assembly/__tests__/staticarray.spec.ts +0 -12
  42. package/assembly/__tests__/string.spec.ts +0 -30
  43. package/assembly/__tests__/struct.spec.ts +0 -163
  44. package/assembly/__tests__/test.spec.ts +0 -3
  45. package/assembly/__tests__/types.spec.ts +0 -27
  46. package/assembly/__tests__/types.ts +0 -98
  47. package/assembly/test.tmp.ts +0 -133
  48. package/bench/abc.bench.ts +0 -25
  49. package/bench/large.bench.ts +0 -127
  50. package/bench/lib/bench.d.ts +0 -27
  51. package/bench/lib/bench.js +0 -53
  52. package/bench/lib/chart.ts +0 -217
  53. package/bench/medium.bench.ts +0 -68
  54. package/bench/runners/assemblyscript.js +0 -34
  55. package/bench/small.bench.ts +0 -34
  56. package/bench/throughput.ts +0 -87
  57. package/bench/tsconfig.json +0 -13
  58. package/bench/vec3.bench.ts +0 -30
  59. package/bench.ts +0 -18
  60. package/ci/bench/lib/bench.ts +0 -42
  61. package/ci/bench/runners/assemblyscript.js +0 -29
  62. package/ci/run-bench.as.sh +0 -63
  63. package/publish.sh +0 -78
  64. package/run-bench.as.sh +0 -60
  65. package/run-bench.js.sh +0 -36
  66. package/run-tests.sh +0 -51
  67. package/scripts/build-chart01.ts +0 -38
  68. package/scripts/build-chart02.ts +0 -38
  69. package/scripts/build-chart03.ts +0 -139
  70. package/scripts/build-chart05.ts +0 -47
  71. package/scripts/generate-as-class.ts +0 -50
  72. package/scripts/lib/bench-utils.ts +0 -308
  73. package/transform/src/builder.ts +0 -1375
  74. package/transform/src/index.ts +0 -1486
  75. package/transform/src/linkers/alias.ts +0 -58
  76. package/transform/src/linkers/custom.ts +0 -32
  77. package/transform/src/linkers/imports.ts +0 -22
  78. package/transform/src/types.ts +0 -300
  79. package/transform/src/util.ts +0 -128
  80. package/transform/src/visitor.ts +0 -530
@@ -1,58 +0,0 @@
1
- import { Node, Source, TypeDeclaration, TypeNode } from "assemblyscript/dist/assemblyscript.js";
2
- import { Visitor } from "../visitor.js";
3
- import { toString } from "../util.js";
4
-
5
- class AliasFinder extends Visitor {
6
- visitTypeDeclaration(node: TypeDeclaration, ref?: Node | null): void {
7
- TypeAlias.add(node.name.text, node.type);
8
- }
9
- }
10
-
11
- export class TypeAlias {
12
- public name: string;
13
- public type: TypeAlias | string;
14
-
15
- constructor(name: string, type: TypeAlias | string) {
16
- this.name = name;
17
- this.type = type;
18
- }
19
-
20
- getBaseType(type: TypeAlias | string = this.type): string {
21
- if (typeof type === "string") return type;
22
- return this.getBaseType(type.type);
23
- }
24
-
25
- static foundAliases: Map<string, string> = new Map<string, string>();
26
- static aliases: Map<string, TypeAlias> = new Map<string, TypeAlias>();
27
-
28
- static add(name: string, type: TypeNode): void {
29
- if (!TypeAlias.foundAliases.has(name)) {
30
- TypeAlias.foundAliases.set(name, toString(type));
31
- } else {
32
- const existingType = TypeAlias.foundAliases.get(name);
33
- if (existingType !== toString(type)) {
34
- throw new Error(`Type alias conflict for ${name}: "${existingType}" vs "${toString(type)}"`);
35
- }
36
- }
37
- }
38
-
39
- static getAliases(source: Source): TypeAlias[] {
40
- this.foundAliases.clear();
41
- this.aliases.clear();
42
-
43
- const finder = new AliasFinder();
44
- finder.visit(source);
45
-
46
- for (const [name, typeStr] of this.foundAliases) {
47
- this.aliases.set(name, new TypeAlias(name, typeStr));
48
- }
49
-
50
- for (const alias of this.aliases.values()) {
51
- if (typeof alias.type === "string" && this.aliases.has(alias.type)) {
52
- alias.type = this.aliases.get(alias.type)!;
53
- }
54
- }
55
-
56
- return [...this.aliases.values()];
57
- }
58
- }
@@ -1,32 +0,0 @@
1
- import { CallExpression, IdentifierExpression, Node, NodeKind, PropertyAccessExpression } from "assemblyscript/dist/assemblyscript.js";
2
- import { Visitor } from "../visitor.js";
3
-
4
- export class CustomTransform extends Visitor {
5
- static SN: CustomTransform = new CustomTransform();
6
- private modify: boolean = false;
7
- visitCallExpression(node: CallExpression) {
8
- super.visit(node.args, node);
9
- if (node.expression.kind != NodeKind.PropertyAccess || (node.expression as PropertyAccessExpression).property.text != "stringify") return;
10
- if ((node.expression as PropertyAccessExpression).expression.kind != NodeKind.Identifier || ((node.expression as PropertyAccessExpression).expression as IdentifierExpression).text != "JSON") return;
11
-
12
- if (this.modify) {
13
- (node.expression as PropertyAccessExpression).expression = Node.createPropertyAccessExpression(Node.createIdentifierExpression("JSON", node.expression.range), Node.createIdentifierExpression("internal", node.expression.range), node.expression.range);
14
- }
15
- this.modify = true;
16
-
17
- // console.log(toString(node));
18
- // console.log(SimpleParser.parseStatement("JSON.internal.stringify").expression.expression)
19
- }
20
- static visit(node: Node | Node[], ref: Node | null = null): void {
21
- if (!node) return;
22
- CustomTransform.SN.modify = true;
23
- CustomTransform.SN.visit(node, ref);
24
- CustomTransform.SN.modify = false;
25
- }
26
- static hasCall(node: Node | Node[]): boolean {
27
- if (!node) return false;
28
- CustomTransform.SN.modify = false;
29
- CustomTransform.SN.visit(node);
30
- return CustomTransform.SN.modify;
31
- }
32
- }
@@ -1,22 +0,0 @@
1
- import { ImportStatement, Node, Source } from "assemblyscript/dist/assemblyscript.js";
2
- import { Visitor } from "../visitor.js";
3
-
4
- class ImportGetter extends Visitor {
5
- static SN: ImportGetter = new ImportGetter();
6
-
7
- private imports: ImportStatement[] = [];
8
-
9
- visitImportStatement(node: ImportStatement, ref?: Node | null): void {
10
- this.imports.push(node);
11
- }
12
-
13
- static getImports(source: Source): ImportStatement[] {
14
- ImportGetter.SN.imports = [];
15
- ImportGetter.SN.visit(source);
16
- return ImportGetter.SN.imports;
17
- }
18
- }
19
-
20
- export function getImports(source: Source): ImportStatement[] {
21
- return ImportGetter.getImports(source);
22
- }
@@ -1,300 +0,0 @@
1
- import { ClassDeclaration, Expression, FieldDeclaration, Source, NodeKind, Node, NamespaceDeclaration, DeclarationStatement, TypeName, Parser, ImportStatement, CommonFlags, EnumDeclaration } from "assemblyscript/dist/assemblyscript.js";
2
- import { TypeAlias } from "./linkers/alias.js";
3
- import { stripNull } from "./index.js";
4
-
5
- export enum PropertyFlags {
6
- OmitNull,
7
- OmitIf,
8
- Raw,
9
- Custom,
10
- }
11
-
12
- export class Property {
13
- public name: string = "";
14
- public alias: string | null = null;
15
- public type: string = "";
16
- public value: string | null = null;
17
- public flags: Map<PropertyFlags, Expression | null> = new Map<PropertyFlags, Expression | null>();
18
- public node!: FieldDeclaration;
19
- public byteSize: number = 0;
20
- public _generic: boolean = false;
21
- public _custom: boolean = false;
22
- public parent: Schema;
23
- set custom(value: boolean) {
24
- this._custom = value;
25
- }
26
- get custom(): boolean {
27
- if (this._custom) return true;
28
- if (this.parent.node.isGeneric && this.parent.node.typeParameters.some((p) => p.name.text == this.type)) {
29
- // console.log("Custom (Generic): " + this.name);
30
- // this._generic = true;
31
- this._custom = true;
32
- return true;
33
- }
34
-
35
- for (const dep of this.parent.deps) {
36
- if (this.name == dep.name && dep.custom) {
37
- // console.log("Custom (Dependency): " + this.name);
38
- this._custom = true;
39
- return true;
40
- }
41
- }
42
- return false;
43
- }
44
- set generic(value: boolean) {
45
- this._generic = value;
46
- }
47
- get generic(): boolean {
48
- if (this._generic) return true;
49
- if (this.parent.node.isGeneric && this.parent.node.typeParameters.some((p) => p.name.text == stripNull(this.type))) {
50
- // console.log("Generic: " + this.name);
51
- this._generic = true;
52
- return true;
53
- }
54
- return false;
55
- }
56
- }
57
-
58
- export class Schema {
59
- public static: boolean = true;
60
- public name: string = "";
61
- public members: Property[] = [];
62
- public parent: Schema | null = null;
63
- public node!: ClassDeclaration;
64
- public needsLink: string | null = null;
65
- public byteSize: number = 0;
66
- public deps: Schema[] = [];
67
- private _custom: boolean = false;
68
-
69
- set custom(value: boolean) {
70
- this._custom = value;
71
- }
72
- get custom(): boolean {
73
- if (this._custom) return true;
74
- if (this.parent) return this.parent.custom;
75
- }
76
- }
77
-
78
- export class SourceSet {
79
- private sources: Record<string, Src> = {};
80
-
81
- /**
82
- * Get a stored source from the set, or create a new one and store it if it
83
- * didn't exist.
84
- * @param source AssemblyScript Source
85
- * @returns Source object
86
- */
87
- get(source: Source): Src {
88
- let src = this.sources[source.internalPath];
89
- if (!src) {
90
- src = new Src(source, this);
91
- this.sources[source.internalPath] = src;
92
- }
93
- return src;
94
- }
95
- }
96
-
97
- export class Src {
98
- public internalPath: string;
99
- public normalizedPath: string;
100
- public schemas: Schema[];
101
- public aliases: TypeAlias[];
102
- public exports: Schema[];
103
- public imports: ImportStatement[] = [];
104
- private nodeMap: Map<Node, NamespaceDeclaration[]> = new Map<Node, NamespaceDeclaration[]>();
105
- private classes: Record<string, ClassDeclaration> = {};
106
- private enums: Record<string, EnumDeclaration> = {};
107
-
108
- constructor(
109
- source: Source,
110
- private sourceSet: SourceSet,
111
- ) {
112
- this.internalPath = source.internalPath;
113
- this.normalizedPath = source.normalizedPath;
114
- this.aliases = TypeAlias.getAliases(source);
115
- this.traverse(source.statements, []);
116
- }
117
-
118
- /**
119
- * Traverse source nodes and finds all classes and imports, and which namespaces they exist under.
120
- * @param nodes Nodes to traverse.
121
- * @param path The current path of namespace declarations leading to the nodes.
122
- */
123
- private traverse(nodes: Node[], path: NamespaceDeclaration[]) {
124
- for (let node of nodes) {
125
- switch (node.kind) {
126
- case NodeKind.NamespaceDeclaration:
127
- const namespaceDeclaration = node as NamespaceDeclaration;
128
- this.traverse(namespaceDeclaration.members, [...path, namespaceDeclaration]);
129
- break;
130
- case NodeKind.ClassDeclaration:
131
- const classDeclaration = node as ClassDeclaration;
132
- this.classes[this.qualifiedName(classDeclaration, path)] = classDeclaration;
133
- break;
134
- case NodeKind.EnumDeclaration:
135
- const enumDeclaration = node as EnumDeclaration;
136
- this.enums[this.qualifiedName(enumDeclaration, path)] = enumDeclaration;
137
- break;
138
- case NodeKind.Import:
139
- const importStatement = node as ImportStatement;
140
- this.imports.push(importStatement);
141
- break;
142
- }
143
- this.nodeMap.set(node, path);
144
- }
145
- }
146
-
147
- /**
148
- * Get the qualified name (eg. "Namespace.BaseObject") for a class.
149
- * @param node Class declaration.
150
- * @returns Qualified name
151
- */
152
- getQualifiedName(node: DeclarationStatement): string {
153
- return this.qualifiedName(node, this.nodeMap.get(node));
154
- }
155
-
156
- /**
157
- * Get a class declaration by its qualified name.
158
- * @param qualifiedName Qualified named (eg. "Namespace.BaseObject")
159
- * @returns Class declaration or null if not found.
160
- */
161
- getClass(qualifiedName: string): ClassDeclaration | null {
162
- return this.classes[qualifiedName] || null;
163
- }
164
-
165
- /**
166
- * Get an enum declaration by its qualified name.
167
- * @param qualifiedName Qualified name (eg. "Namespace.MyEnum")
168
- * @returns Enum declaration or null if not found.
169
- */
170
- getEnum(qualifiedName: string): EnumDeclaration | null {
171
- return this.enums[qualifiedName] || null;
172
- }
173
-
174
- /**
175
- * Get imported class from other sources in the parser.
176
- * @param qualifiedName Qualified name of class.
177
- * @param parser AssemblyScript parser.
178
- * @returns Class declaration or null if not found.
179
- */
180
- getImportedClass(qualifiedName: string, parser: Parser): ClassDeclaration | null {
181
- for (const stmt of this.imports) {
182
- const externalSource = parser.sources.filter((src) => src.internalPath != this.internalPath).find((src) => src.internalPath == stmt.internalPath);
183
- if (!externalSource) continue;
184
-
185
- const source = this.sourceSet.get(externalSource);
186
- const classDeclaration = source.getClass(qualifiedName);
187
- if (classDeclaration && classDeclaration.flags & CommonFlags.Export) {
188
- return classDeclaration;
189
- }
190
- }
191
- return null;
192
- }
193
-
194
- /**
195
- * Get imported enum from other sources in the parser.
196
- * @param qualifiedName Qualified name of enum.
197
- * @param parser AssemblyScript parser.
198
- * @returns Enum declaration or null if not found.
199
- */
200
- getImportedEnum(qualifiedName: string, parser: Parser): EnumDeclaration | null {
201
- for (const stmt of this.imports) {
202
- const externalSource = parser.sources.filter((src) => src.internalPath != this.internalPath).find((src) => src.internalPath == stmt.internalPath);
203
- if (!externalSource) continue;
204
-
205
- const source = this.sourceSet.get(externalSource);
206
- const enumDeclaration = source.getEnum(qualifiedName);
207
- if (enumDeclaration && enumDeclaration.flags & CommonFlags.Export) {
208
- return enumDeclaration;
209
- }
210
- }
211
- return null;
212
- }
213
-
214
- /**
215
- * Gets a unique path string to the node by combining the internalPath with
216
- * the qualified name of the node.
217
- * @param node DeclarationStatement
218
- */
219
- getFullPath(node: DeclarationStatement): string {
220
- return this.internalPath + "/" + this.getQualifiedName(node);
221
- }
222
-
223
- /**
224
- * Resolved the qualified name of the extended class for a class
225
- * declaration.
226
- * @param classDeclaration Class declaration that extends another class.
227
- * @returns Qualified name of the extended class, or empty string if not extending any class.
228
- */
229
- resolveExtendsName(classDeclaration: ClassDeclaration): string {
230
- const parents = this.nodeMap.get(classDeclaration);
231
- if (!classDeclaration.extendsType || !parents) {
232
- return "";
233
- }
234
-
235
- const name = classDeclaration.extendsType.name.identifier.text;
236
- const extendsName = this.getIdentifier(classDeclaration.extendsType.name);
237
-
238
- // Reverse walk to find first class or namespace that matches the first part
239
- // of type name.
240
- for (let i = parents.length - 1; i >= 0; i--) {
241
- const parent = parents[i];
242
- for (let node of parent.members) {
243
- if (name == this.getNamespaceOrClassName(node)) {
244
- // Add namespace path to the extendsName.
245
- return (
246
- parents
247
- .slice(0, i + 1)
248
- .map((p) => p.name.text)
249
- .join(".") +
250
- "." +
251
- extendsName
252
- );
253
- }
254
- }
255
- }
256
- // No matching class or namespace found. Just use the extendsName.
257
- return extendsName;
258
- }
259
-
260
- /**
261
- * Get the qualified name (eg "Namespace.BaseObject") of a class.
262
- * @param node Class declaration.
263
- * @param parents Array of namespace parents.
264
- * @returns Qualified name
265
- */
266
- private qualifiedName(node: DeclarationStatement, parents: NamespaceDeclaration[]): string {
267
- return parents?.length ? parents.map((p) => p.name.text).join(".") + "." + node.name.text : node.name.text;
268
- }
269
-
270
- /**
271
- * Checks if the node is either a namespace or class, and returns the simple
272
- * name of the node.
273
- * @param node Node to check
274
- * @returns Name of namespace or class, or empty string if other type of node.
275
- */
276
- private getNamespaceOrClassName(node: Node): string {
277
- switch (node.kind) {
278
- case NodeKind.NamespaceDeclaration:
279
- return (node as DeclarationStatement).name.text;
280
- case NodeKind.ClassDeclaration:
281
- return (node as DeclarationStatement).name.text;
282
- }
283
- return "";
284
- }
285
-
286
- /**
287
- * Get the full name (eg. "Namespace.Base") of a type name such as an
288
- * extendedType.
289
- * @param typeName Type name
290
- * @returns Full name
291
- */
292
- private getIdentifier(typeName: TypeName): string {
293
- let names = [];
294
- while (typeName) {
295
- names.push(typeName.identifier.text);
296
- typeName = typeName.next;
297
- }
298
- return names.join(".");
299
- }
300
- }
@@ -1,128 +0,0 @@
1
- // Taken from https://github.com/as-pect/visitor-as/blob/master/src/simpleParser.ts
2
- import { Parser, Tokenizer, Source, SourceKind, Expression, Statement, NamespaceDeclaration, ClassDeclaration, DeclarationStatement, Range, Node, NodeKind } from "assemblyscript/dist/assemblyscript.js";
3
- import { ASTBuilder } from "./builder.js";
4
- import * as path from "path";
5
-
6
- export class SimpleParser {
7
- private static get parser(): Parser {
8
- return new Parser();
9
- }
10
-
11
- private static getTokenizer(s: string, file: string = "index.ts"): Tokenizer {
12
- return new Tokenizer(new Source(SourceKind.User, file, s));
13
- }
14
-
15
- static parseExpression(s: string): Expression {
16
- const res = this.parser.parseExpression(this.getTokenizer(s));
17
- if (res == null) {
18
- throw new Error("Failed to parse the expression: '" + s + "'");
19
- }
20
- return res;
21
- }
22
-
23
- static parseStatement(s: string, topLevel = false): Statement {
24
- const res = this.parser.parseStatement(this.getTokenizer(s), topLevel);
25
- if (res == null) {
26
- throw new Error("Failed to parse the statement: '" + s + "'");
27
- }
28
- return res;
29
- }
30
-
31
- static parseTopLevelStatement(s: string, namespace?: NamespaceDeclaration | null): Statement {
32
- const res = this.parser.parseTopLevelStatement(this.getTokenizer(s), namespace);
33
- if (res == null) {
34
- throw new Error("Failed to parse the top level statement: '" + s + "'");
35
- }
36
- return res;
37
- }
38
-
39
- static parseClassMember(s: string, _class: ClassDeclaration): DeclarationStatement {
40
- let res = this.parser.parseClassMember(this.getTokenizer(s, _class.range.source.normalizedPath), _class);
41
- if (res == null) {
42
- throw new Error("Failed to parse the class member: '" + s + "'");
43
- }
44
- return <DeclarationStatement>res;
45
- }
46
- }
47
-
48
- let isStdlibRegex = /\~lib\/(?:array|arraybuffer|atomics|builtins|crypto|console|compat|dataview|date|diagnostics|error|function|iterator|map|math|number|object|process|reference|regexp|set|staticarray|string|symbol|table|typedarray|vector|rt\/?|bindings\/|shared\/typeinfo)|util\/|uri|polyfills|memory/;
49
-
50
- export function isStdlib(s: Source | { range: Range }): boolean {
51
- let source = s instanceof Source ? s : s.range.source;
52
- return isStdlibRegex.test(source.internalPath);
53
- }
54
-
55
- export function toString(node: Node): string {
56
- return ASTBuilder.build(node);
57
- }
58
-
59
- export function replaceRef(node: Node, replacement: Node | Node[], ref: Node | Node[] | null): void {
60
- if (!node || !ref) return;
61
- const nodeExpr = stripExpr(node);
62
-
63
- if (Array.isArray(ref)) {
64
- for (let i = 0; i < ref.length; i++) {
65
- if (stripExpr(ref[i]) === nodeExpr) {
66
- if (Array.isArray(replacement)) ref.splice(i, 1, ...replacement);
67
- else ref.splice(i, 1, replacement);
68
- return; // Exit early after replacement
69
- }
70
- }
71
- } else if (typeof ref === "object") {
72
- for (const key of Object.keys(ref)) {
73
- const current = ref[key] as Node | Node[];
74
- if (Array.isArray(current)) {
75
- for (let i = 0; i < current.length; i++) {
76
- if (stripExpr(current[i]) === nodeExpr) {
77
- if (Array.isArray(replacement)) current.splice(i, 1, ...replacement);
78
- else current.splice(i, 1, replacement);
79
- return;
80
- }
81
- }
82
- } else if (stripExpr(current) === nodeExpr) {
83
- ref[key] = replacement;
84
- return;
85
- }
86
- }
87
- }
88
- }
89
-
90
- export function cloneNode(input: Node | Node[] | null, seen = new WeakMap(), path = ""): Node | Node[] | null {
91
- if (input === null || typeof input !== "object") return input;
92
-
93
- if (Array.isArray(input)) {
94
- return input.map((item, index) => cloneNode(item, seen, `${path}[${index}]`)) as Node | Node[] | null;
95
- }
96
-
97
- if (seen.has(input)) return seen.get(input);
98
-
99
- const prototype = Object.getPrototypeOf(input);
100
- const clone = Array.isArray(input) ? [] : Object.create(prototype);
101
- seen.set(input, clone);
102
-
103
- for (const key of Reflect.ownKeys(input)) {
104
- const value = input[key];
105
- const newPath = path ? `${path}.${String(key)}` : String(key);
106
-
107
- if (newPath.endsWith(".source")) {
108
- clone[key] = value;
109
- } else if (value && typeof value === "object") {
110
- clone[key] = cloneNode(value, seen, newPath);
111
- } else {
112
- clone[key] = value;
113
- }
114
- }
115
-
116
- return clone as Node | Node[] | null;
117
- }
118
-
119
- export function stripExpr(node: Node): Node {
120
- if (!node) return node;
121
- if (node.kind == NodeKind.Expression) return node["expression"];
122
- return node;
123
- }
124
-
125
- export function removeExtension(filePath: string): string {
126
- const parsed = path.parse(filePath);
127
- return path.join(parsed.dir, parsed.name);
128
- }