@idlizer/arktscgen 2.1.10-arktscgen-5 → 2.1.10-arktscgen-6

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 (39) hide show
  1. package/build/libarkts-copy/generator/options.json5 +24 -47
  2. package/build/libarkts-copy/native/meson.build +25 -9
  3. package/build/libarkts-copy/native/meson_options.txt +9 -3
  4. package/build/libarkts-copy/native/mingw.cross +2 -0
  5. package/build/libarkts-copy/native/src/bridges.cc +20 -81
  6. package/build/libarkts-copy/native/src/common.cc +127 -49
  7. package/build/libarkts-copy/native/src/memoryTracker.cc +42 -35
  8. package/build/libarkts-copy/package.json +12 -10
  9. package/build/libarkts-copy/src/Es2pandaNativeModule.ts +10 -63
  10. package/build/libarkts-copy/src/arkts-api/AbstractVisitor.ts +9 -3
  11. package/build/libarkts-copy/src/arkts-api/ImportStorage.ts +2 -4
  12. package/build/libarkts-copy/src/arkts-api/ProgramProvider.ts +14 -5
  13. package/build/libarkts-copy/src/arkts-api/class-by-peer.ts +19 -1
  14. package/build/libarkts-copy/src/arkts-api/index.ts +0 -1
  15. package/build/libarkts-copy/src/arkts-api/node-cache.ts +12 -3
  16. package/build/libarkts-copy/src/arkts-api/node-utilities/ObjectExpression.ts +1 -1
  17. package/build/libarkts-copy/src/arkts-api/node-utilities/ScriptFunction.ts +4 -4
  18. package/build/libarkts-copy/src/arkts-api/peers/AstNode.ts +0 -16
  19. package/build/libarkts-copy/src/arkts-api/peers/Config.ts +1 -1
  20. package/build/libarkts-copy/src/arkts-api/peers/Context.ts +10 -9
  21. package/build/libarkts-copy/src/arkts-api/plugins.ts +110 -5
  22. package/build/libarkts-copy/src/arkts-api/static/global.ts +1 -1
  23. package/build/libarkts-copy/src/arkts-api/static/profiler.ts +1 -1
  24. package/build/libarkts-copy/src/arkts-api/utilities/performance.ts +2 -1
  25. package/build/libarkts-copy/src/arkts-api/utilities/private.ts +4 -9
  26. package/build/libarkts-copy/src/arkts-api/utilities/public.ts +41 -9
  27. package/build/libarkts-copy/src/arkts-api/visitor.ts +4 -25
  28. package/build/libarkts-copy/src/checkSdk.ts +1 -1
  29. package/build/libarkts-copy/src/index.ts +1 -1
  30. package/build/libarkts-copy/src/memo-node-cache.ts +143 -0
  31. package/build/libarkts-copy/src/plugin-utils.ts +19 -12
  32. package/build/libarkts-copy/src/reexport-for-generated.ts +2 -0
  33. package/build/libarkts-copy/src/tracer.ts +2 -2
  34. package/build/libarkts-copy/src/ts-api/factory/nodeFactory.ts +2 -2
  35. package/build/libarkts-copy/src/ts-api/utilities/private.ts +2 -2
  36. package/build/libarkts-copy/src/utils.ts +10 -14
  37. package/lib/index.js +5316 -10427
  38. package/package.json +9 -7
  39. package/build/libarkts-copy/src/arkts-api/peers/DiagnosticKind.ts +0 -23
@@ -19,6 +19,7 @@ import { ExternalSource } from './peers/ExternalSource';
19
19
  import { KNativePointer, nullptr } from '@koalaui/interop';
20
20
  import { global } from './static/global';
21
21
  import { RunTransformerHooks } from '../plugin-utils';
22
+ import { Context } from './peers/Context';
22
23
 
23
24
  export interface CompilationOptions {
24
25
  readonly isProgramForCodegeneration: boolean;
@@ -62,16 +63,32 @@ export interface ProjectConfig {
62
63
  isUi2abc?: boolean;
63
64
  }
64
65
 
65
- export interface PluginContext {
66
+ export interface PluginContextBase {
66
67
  setParameter<V>(name: string, value: V): void;
67
68
  parameter<V>(name: string): V | undefined;
68
69
  }
69
70
 
70
- export class PluginContextImpl implements PluginContext {
71
- map = new Map<string, object | undefined>();
71
+ export interface PluginContext extends PluginContextBase {
72
+ /**
73
+ * @deprecated
74
+ */
75
+ setArkTSProgram(program: Program): void
72
76
 
73
- private ast: ETSModule | undefined = undefined;
74
- private projectConfig: ProjectConfig | undefined = undefined;
77
+ /**
78
+ * @deprecated
79
+ */
80
+ getArkTSProgram(): Program | undefined
81
+
82
+ setCodingFilePath(codingFilePath: string): void
83
+
84
+ getCodingFilePath(): string | undefined
85
+
86
+ isCoding(): boolean
87
+ }
88
+
89
+
90
+ export class PluginContextBaseImpl implements PluginContextBase {
91
+ map = new Map<string, object | undefined>();
75
92
 
76
93
  parameter<V>(name: string): V | undefined {
77
94
  return this.map.get(name) as V | undefined;
@@ -79,9 +96,38 @@ export class PluginContextImpl implements PluginContext {
79
96
  setParameter<V>(name: string, value: V): void {
80
97
  this.map.set(name, value as object);
81
98
  }
99
+ }
100
+
101
+ // Temporary hack to use plugin context's parameters when compiling with driver
102
+ export function extendPluginContext(context: PluginContextImpl) {
103
+ if (typeof context.setParameter == "function") {
104
+ return
105
+ }
106
+ const pluginContextBaseImpl = new PluginContextBaseImpl()
107
+ context.map = pluginContextBaseImpl.map
108
+ context.setParameter = pluginContextBaseImpl.setParameter
109
+ context.parameter = pluginContextBaseImpl.parameter
110
+ }
111
+
112
+ export class PluginContextImpl extends PluginContextBaseImpl implements PluginContext {
113
+ private ast: ETSModule | undefined;
114
+ private projectConfig: ProjectConfig | undefined;
115
+
116
+ private program: Program | undefined;
117
+ private codingFilePath: string | undefined;
118
+
119
+ setContextPtr(ptr: KNativePointer): void {
120
+ if (!global.compilerContext) {
121
+ global.compilerContext = new Context(ptr);
122
+ } else {
123
+ global.compilerContext.peer = ptr;
124
+ }
125
+ }
126
+
82
127
  getContextPtr(): KNativePointer {
83
128
  return global.compilerContext?.peer ?? nullptr;
84
129
  }
130
+
85
131
  public setProjectConfig(projectConfig: ProjectConfig): void {
86
132
  this.projectConfig = projectConfig;
87
133
  }
@@ -102,14 +148,73 @@ export class PluginContextImpl implements PluginContext {
102
148
  public getArkTSAst(): ETSModule | undefined {
103
149
  return this.ast;
104
150
  }
151
+
152
+ /**
153
+ * @deprecated
154
+ */
155
+ public setArkTSProgram(program: Program): void {
156
+ this.program = program;
157
+ }
158
+
159
+ /**ProjectConfig
160
+ * @deprecated
161
+ */
162
+ public getArkTSProgram(): Program | undefined {
163
+ return this.program;
164
+ }
165
+
166
+ public setCodingFilePath(codingFilePath: string): void {
167
+ this.codingFilePath = codingFilePath;
168
+ }
169
+
170
+ public getCodingFilePath(): string | undefined {
171
+ return this.codingFilePath;
172
+ }
173
+
174
+ public isCoding(): boolean {
175
+ return this.codingFilePath !== undefined;
176
+ }
105
177
  }
106
178
 
179
+ export type PluginHandlerFunction = () => void;
180
+
181
+ export type PluginHandlerObject = {
182
+ order: 'pre' | 'post' | undefined;
183
+ handler: PluginHandlerFunction;
184
+ };
185
+
186
+ export type PluginHandler = PluginHandlerFunction | PluginHandlerObject;
187
+
107
188
  export type ProgramTransformer = (
108
189
  program: Program,
109
190
  compilationOptions: CompilationOptions,
110
191
  context: PluginContext
111
192
  ) => void;
112
193
 
194
+ export interface Plugins {
195
+ name: string;
196
+ afterNew?: PluginHandler;
197
+ parsed?: PluginHandler;
198
+ scopeInited?: PluginHandler;
199
+ checked?: PluginHandler;
200
+ lowered?: PluginHandler;
201
+ asmGenerated?: PluginHandler;
202
+ binGenerated?: PluginHandler;
203
+ clean?: PluginHandler;
204
+ }
205
+
206
+ export type PluginState = keyof Omit<Plugins, 'name'>;
207
+
208
+ export type PluginExecutor = {
209
+ name: string;
210
+ handler: PluginHandlerFunction;
211
+ };
212
+
213
+ export interface BuildConfig {
214
+ compileFiles: string[];
215
+ }
216
+
217
+
113
218
  export function defaultFilter(name: string): boolean {
114
219
  if (name.startsWith('std.')) return false;
115
220
  if (name.startsWith('escompat')) return false;
@@ -54,7 +54,7 @@ export class global {
54
54
  return global._config ?? throwError('Global.config not initialized');
55
55
  }
56
56
  public static configIsInitialized(): boolean {
57
- return global._config !== undefined && global._config !== nullptr;
57
+ return !!global._config && global._config !== nullptr;
58
58
  }
59
59
  public static resetConfig(): void {
60
60
  global._config = undefined;
@@ -80,7 +80,7 @@ export class Profiler implements PerformanceData {
80
80
  return this.pluginsByName[pluginName];
81
81
  }
82
82
 
83
- disableReport = false;
83
+ disableReport = true;
84
84
 
85
85
  nodeCreated() {
86
86
  this.createdNodes++;
@@ -13,6 +13,7 @@
13
13
  * limitations under the License.
14
14
  */
15
15
 
16
+ const { performance } = require('perf_hooks');
16
17
  import * as process from 'process';
17
18
  import { global as localGlobal } from '../static/global';
18
19
 
@@ -286,7 +287,7 @@ export class Performance {
286
287
  '[PERFORMANCE]',
287
288
  `External | ${context.startMemory.external.toFixed(2)} | ${(endMemory.external / (BYTES_PER_KIBIBYTE * BYTES_PER_KIBIBYTE)).toFixed(2)} | ${memoryDiff.external.toFixed(2)}`
288
289
  );
289
- if (endMemory.arrayBuffers !== undefined) {
290
+ if (!!endMemory.arrayBuffers) {
290
291
  console.log(
291
292
  `Array Buffers | ${context.startMemory.arrayBuffers.toFixed(2)} | ${((endMemory.arrayBuffers || 0) / (BYTES_PER_KIBIBYTE * BYTES_PER_KIBIBYTE)).toFixed(2)} | ${memoryDiff.arrayBuffers.toFixed(2)}`
292
293
  );
@@ -17,7 +17,6 @@ import { global } from '../static/global';
17
17
  import { isNumber, throwError } from '../../utils';
18
18
  import { KInt, KNativePointer as KPtr, KNativePointer, nullptr, withString, withStringArray } from '@koalaui/interop';
19
19
  import { NativePtrDecoder } from './nativePtrDecoder';
20
- //import { OptimizedNativePtrDecoder as NativePtrDecoder } from "./nativePtrDecoder"
21
20
  import {
22
21
  Es2pandaAstNodeType,
23
22
  Es2pandaModifierFlags,
@@ -71,13 +70,9 @@ export function acceptNativeObjectArrayResult<T extends ArktsObject>(
71
70
  arrayObject: KNativePointer,
72
71
  factory: (instance: KNativePointer) => T
73
72
  ): T[] {
74
- // For OptimizedNativePtrDecoder
75
- //const decoded = new NativePtrDecoder().decode(arrayObject)
76
- //return decoded.reduce((prev, curr) => {
77
- // prev.push(factory(curr))
78
- // return prev
79
- //}, [] as T[])
80
- return new NativePtrDecoder().decode(arrayObject).map(factory);
73
+ // OptimizedNativePtrDecoder:return decoded.reduce((prev, curr)=>{prev.push(factory(curr));return prev},[] as T[])
74
+ const decoded = new NativePtrDecoder().decode(arrayObject)
75
+ return decoded.map(factory);
81
76
  }
82
77
 
83
78
  export function unpackNonNullableNode<T extends AstNode>(peer: KNativePointer, typeHint?: Es2pandaAstNodeType): T {
@@ -112,7 +107,7 @@ export function unpackNodeArray<T extends AstNode>(nodesPtr: KNativePointer, typ
112
107
  }
113
108
 
114
109
  export function passNodeArray(nodes: readonly ArktsObject[] | undefined): BigUint64Array {
115
- return new BigUint64Array(nodes?.filter((it) => it.peer != undefined)?.map((node) => BigInt(node.peer)) ?? []);
110
+ return new BigUint64Array(nodes?.filter((it) => (!!it.peer))?.map((node) => BigInt(node.peer)) ?? []);
116
111
  }
117
112
 
118
113
  export function unpackString(peer: KNativePointer): string {
@@ -63,13 +63,13 @@ import {
63
63
  MemberExpression,
64
64
  isMethodDefinition,
65
65
  TypeNode,
66
+ DiagnosticKind
66
67
  } from '../../../generated';
67
68
  import { Config } from '../peers/Config';
68
69
  import { Context } from '../peers/Context';
69
70
  import { NodeCache } from '../node-cache';
70
71
  import { factory } from '../factory/nodeFactory';
71
72
  import { traceGlobal } from '../../tracer';
72
- import { DiagnosticKind } from '../peers/DiagnosticKind';
73
73
 
74
74
  /**
75
75
  * Improve: Replace or remove with better naming
@@ -78,11 +78,11 @@ import { DiagnosticKind } from '../peers/DiagnosticKind';
78
78
  */
79
79
  export function createETSModuleFromContext(): ETSModule {
80
80
  let program = global.generatedEs2panda._ContextProgram(global.context);
81
- if (program == nullptr) {
81
+ if (program === nullptr || program === null) {
82
82
  throw new Error(`Program is null for context ${global.context.toString(16)}`);
83
83
  }
84
84
  const ast = global.generatedEs2panda._ProgramAst(global.context, program);
85
- if (ast == nullptr) {
85
+ if (ast === nullptr || ast === null) {
86
86
  throw new Error(`AST is null for program ${program.toString(16)}`);
87
87
  }
88
88
  return new ETSModule(ast, Es2pandaAstNodeType.AST_NODE_TYPE_ETS_MODULE);
@@ -122,10 +122,19 @@ export function checkErrors() {
122
122
  traceGlobal(() => `Terminated due to compilation errors occured`);
123
123
  console.log(unpackString(global.generatedEs2panda._GetAllErrorMessages(global.context)));
124
124
  // global.es2panda._DestroyConfig(global.config)
125
- process.exit(1);
125
+ throw new Error(`Compilation error`)
126
126
  }
127
127
  }
128
128
 
129
+ function format(value: number): string {
130
+ return `${(value / 1024 / 1024 / 1024).toFixed(4)} GB`
131
+ }
132
+
133
+ // Improve: move to profiler
134
+ function dumpMemoryProfilerInfo(str: string) {
135
+ console.log(str, format(process.memoryUsage().rss));
136
+ }
137
+
129
138
  export function proceedToState(state: Es2pandaContextState): void {
130
139
  if (state <= global.es2panda._ContextState(global.context)) {
131
140
  return;
@@ -137,6 +146,9 @@ export function proceedToState(state: Es2pandaContextState): void {
137
146
  traceGlobal(() => `Proceeding to state ${Es2pandaContextState[state]}: done`);
138
147
  const after = Date.now();
139
148
  global.profiler.proceededToState(after - before);
149
+ if (state == Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED) {
150
+ dumpMemoryProfilerInfo("Memory usage (rss) after proceed to bin:")
151
+ }
140
152
  checkErrors();
141
153
  }
142
154
 
@@ -372,7 +384,7 @@ export function generateTsDeclarationsFromContext(
372
384
  recordFile: string,
373
385
  genAnnotations: boolean
374
386
  ): KInt {
375
- return global.es2panda._GenerateTsDeclarationsFromContext(
387
+ return global.generatedEs2panda._GenerateTsDeclarationsFromContext(
376
388
  global.context,
377
389
  passString(outputDeclEts),
378
390
  passString(outputEts),
@@ -451,7 +463,7 @@ export function createDiagnosticInfo(
451
463
  ...args: string[]
452
464
  ): DiagnosticInfo {
453
465
  return new DiagnosticInfo(
454
- global.es2panda._CreateDiagnosticInfo(
466
+ global.generatedEs2panda._CreateDiagnosticInfo(
455
467
  global.context,
456
468
  kind.peer,
457
469
  passStringArray(args),
@@ -469,7 +481,7 @@ export function createSuggestionInfo(
469
481
  ...args: string[]
470
482
  ): SuggestionInfo {
471
483
  return new SuggestionInfo(
472
- global.es2panda._CreateSuggestionInfo(
484
+ global.generatedEs2panda._CreateSuggestionInfo(
473
485
  global.context,
474
486
  kind.peer,
475
487
  passStringArray(args),
@@ -493,6 +505,26 @@ export function logDiagnosticWithSuggestion(diagnosticInfo: DiagnosticInfo, sugg
493
505
  global.generatedEs2panda._LogDiagnosticWithSuggestion(global.context, diagnosticInfo.peer, suggestionInfo.peer);
494
506
  }
495
507
 
496
- export function filterNodes(node: AstNode, filter: string): AstNode[] {
497
- return unpackNodeArray(global.es2panda._FilterNodes(global.context, passNode(node), filter));
508
+ export function filterNodes(node: AstNode, filter: string, deeperAfterMatch: boolean): AstNode[] {
509
+ return unpackNodeArray(global.es2panda._FilterNodes(global.context, passNode(node), filter, deeperAfterMatch));
510
+ }
511
+
512
+ export function filterNodesByType<T extends AstNode = AstNode>(node: AstNode, type: Es2pandaAstNodeType): T[] {
513
+ return unpackNodeArray(global.es2panda._FilterNodes2(global.context, passNode(node), type), type);
514
+ }
515
+
516
+ export function filterNodesByTypes(node: AstNode, types: Es2pandaAstNodeType[]): AstNode[] {
517
+ const typesArray = new Int32Array(types.length)
518
+ for (let i = 0; i < types.length; i++) {
519
+ typesArray[i] = types[i]
520
+ }
521
+ return unpackNodeArray(global.es2panda._FilterNodes3(global.context, passNode(node), typesArray, types.length));
522
+ }
523
+
524
+ export function MemInitialize() {
525
+ global.es2panda._MemInitialize()
526
+ }
527
+
528
+ export function MemFinalize() {
529
+ global.es2panda._MemFinalize()
498
530
  }
@@ -258,34 +258,17 @@ function visitETSTypeReferencePart(node: ETSTypeReferencePart, visitor: Visitor)
258
258
  function visitScriptFunction(node: ScriptFunction, visitor: Visitor): ScriptFunction {
259
259
  global.updateTracker.push();
260
260
  const newBody = nodeVisitor(node.body, visitor);
261
- const oldTypeParams = node.typeParams;
262
- const newTypeParams = nodeVisitor(oldTypeParams, visitor);
261
+ const newTypeParams = nodeVisitor(node.typeParams, visitor);
263
262
  const newParams: readonly Expression[] = nodesVisitor(node.params, visitor);
264
263
  const newReturnTypeAnnotation = nodeVisitor(node.returnTypeAnnotation, visitor);
265
264
  const newId = nodeVisitor(node.id, visitor);
266
265
  const newAnnotations: readonly AnnotationUsage[] = nodesVisitor(node.annotations, visitor);
267
266
  if (global.updateTracker.check()) {
268
- if (!isSameNativeObject(newTypeParams, oldTypeParams)) {
269
- const result = factory.createScriptFunction(
270
- newBody,
271
- newTypeParams,
272
- newParams,
273
- newReturnTypeAnnotation,
274
- node.hasReceiver,
275
- node.flags,
276
- node.modifierFlags,
277
- newId,
278
- newAnnotations,
279
- node.getSignaturePointer(),
280
- node.getPreferredReturnTypePointer()
281
- );
282
- result.onUpdate(node);
283
- return result;
284
- }
285
267
  node.setBody(newBody);
286
268
  node.setParams(newParams);
269
+ node.setTypeParams(newTypeParams);
287
270
  node.setReturnTypeAnnotation(newReturnTypeAnnotation);
288
- if (newId) node.setIdent(newId);
271
+ node.setIdent(newId);
289
272
  node.setAnnotations(newAnnotations);
290
273
  }
291
274
  return node;
@@ -314,7 +297,6 @@ function visitMethodDefinition(node: MethodDefinition, visitor: Visitor): Method
314
297
  node.setOverloads(newOverloads);
315
298
  newOverloads.forEach((it): void => {
316
299
  it.setBaseOverloadMethod(node);
317
- it.parent = node;
318
300
  });
319
301
  }
320
302
  return node;
@@ -538,7 +520,6 @@ function visitIfStatement(node: IfStatement, visitor: Visitor): IfStatement {
538
520
  return result;
539
521
  }
540
522
  node.setTest(newTest);
541
- if (newTest) newTest.parent = node;
542
523
  node.setAlternate(newAlternate);
543
524
  }
544
525
  return node;
@@ -828,7 +809,6 @@ function visitETSNewClassInstanceExpression(
828
809
  return result;
829
810
  }
830
811
  node.setArguments(newArguments);
831
- newArguments.forEach((it) => (it.parent = node));
832
812
  }
833
813
  return node;
834
814
  }
@@ -865,7 +845,7 @@ function visitForUpdateStatement(node: ForUpdateStatement, visitor: Visitor): Fo
865
845
  global.updateTracker.push();
866
846
  const newInit = nodeVisitor(node.init, visitor);
867
847
  const newTest = nodeVisitor(node.test, visitor);
868
- const newUpdate = nodeVisitor(node.update, visitor);
848
+ const newUpdate = nodeVisitor(node.updateExpression, visitor);
869
849
  const newBody = nodeVisitor(node.body, visitor);
870
850
  if (global.updateTracker.check()) {
871
851
  const result = factory.createForUpdateStatement(newInit, newTest, newUpdate, newBody);
@@ -922,7 +902,6 @@ function visitTSNonNullExpression(node: TSNonNullExpression, visitor: Visitor):
922
902
  const newExpr = nodeVisitor(node.expr, visitor);
923
903
  if (global.updateTracker.check()) {
924
904
  node.setExpr(newExpr);
925
- if (newExpr) newExpr.parent = node;
926
905
  }
927
906
  return node;
928
907
  }
@@ -31,7 +31,7 @@ export function checkSDK() {
31
31
  if (!version) reportErrorAndExit(`version is unknown`);
32
32
  const packageJsonOur = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json')).toString());
33
33
  const expectedVersion = packageJsonOur.config.panda_sdk_version;
34
- if (expectedVersion && expectedVersion != 'next' && version != expectedVersion)
34
+ if (expectedVersion && expectedVersion !== 'next' && version !== expectedVersion)
35
35
  console.log(`WARNING: Panda SDK version "${version}" doesn't match expected "${expectedVersion}"`);
36
36
  else console.log(`Using Panda ${version}`);
37
37
  }
@@ -38,10 +38,10 @@ export { GlobalContext } from './arkts-api/peers/Context';
38
38
  export * from './arkts-api/peers/ExternalSource';
39
39
  export * from './arkts-api/peers/ImportPathManager';
40
40
  export * from './arkts-api/peers/Options';
41
- export * from './arkts-api/peers/DiagnosticKind';
42
41
  export { global as arktsGlobal } from './arkts-api/static/global';
43
42
  export * from './arkts-api/static/globalUtils';
44
43
  export * as arkts from './arkts-api';
45
44
 
46
45
  export * from './plugin-utils';
47
46
  export * from './tracer';
47
+ export * from './memo-node-cache';
@@ -0,0 +1,143 @@
1
+ /*
2
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+
16
+ import { KNativePointer } from "@koalaui/interop";
17
+ import { AstNode, Es2pandaAstNodeType, factory, unpackString } from "./arkts-api";
18
+ import { global } from "./arkts-api/static/global";
19
+
20
+ // Improve: this should actually belong to plugin contexts, not to libarkts
21
+
22
+ export interface AstNodeCacheValue {
23
+ peer: KNativePointer;
24
+ type: Es2pandaAstNodeType;
25
+ metadata?: AstNodeCacheValueMetadata;
26
+ }
27
+
28
+ export interface AstNodeCacheValueMetadata {
29
+ callName?: string;
30
+ hasReceiver?: boolean;
31
+ isSetter?: boolean;
32
+ isGetter?: boolean;
33
+ forbidTypeRewrite?: boolean;
34
+ isWithinTypeParams?: boolean;
35
+ hasMemoSkip?: boolean;
36
+ hasMemoIntrinsic?: boolean;
37
+ hasMemoEntry?: boolean;
38
+ }
39
+
40
+ export class MemoNodeCache {
41
+ private _isCollected: boolean = false;
42
+ private cacheMap: Map<KNativePointer, AstNodeCacheValue>;
43
+ private static instance: MemoNodeCache;
44
+ static disableMemoNodeCache = false;
45
+
46
+ private constructor() {
47
+ this.cacheMap = new Map();
48
+ }
49
+
50
+ static getInstance(): MemoNodeCache {
51
+ if (!this.instance) {
52
+ this.instance = new MemoNodeCache();
53
+ }
54
+ if (this.disableMemoNodeCache) {
55
+ return this.instance
56
+ }
57
+
58
+ // Please provide the another way to force cache update on when node updates
59
+ wrapFuncWithNodeCache(this.instance, "updateArrowFunctionExpression")
60
+ wrapFuncWithNodeCache(this.instance, "updateBreakStatement")
61
+ wrapFuncWithNodeCache(this.instance, "updateCallExpression")
62
+ wrapFuncWithNodeCache(this.instance, "updateClassProperty")
63
+ wrapFuncWithNodeCache(this.instance, "updateETSFunctionType")
64
+ wrapFuncWithNodeCache(this.instance, "updateETSParameterExpression")
65
+ wrapFuncWithNodeCache(this.instance, "updateETSUnionType")
66
+ wrapFuncWithNodeCache(this.instance, "updateIdentifier")
67
+ wrapFuncWithNodeCache(this.instance, "updateMethodDefinition")
68
+ wrapFuncWithNodeCache(this.instance, "updateProperty")
69
+ wrapFuncWithNodeCache(this.instance, "updateReturnStatement")
70
+ wrapFuncWithNodeCache(this.instance, "updateScriptFunction")
71
+ wrapFuncWithNodeCache(this.instance, "updateTSTypeAliasDeclaration")
72
+ wrapFuncWithNodeCache(this.instance, "updateVariableDeclarator")
73
+
74
+ return this.instance;
75
+ }
76
+
77
+ collect(node: AstNode, metadata?: AstNodeCacheValueMetadata): void {
78
+ if (MemoNodeCache.disableMemoNodeCache) {
79
+ return
80
+ }
81
+ const peer = node.peer;
82
+ const type = global.generatedEs2panda._AstNodeTypeConst(global.context, node.peer);
83
+ let currMetadata: AstNodeCacheValueMetadata | undefined = metadata ?? {};
84
+ if (this.cacheMap.has(peer)) {
85
+ const oldMetadata = this.cacheMap.get(peer)!.metadata ?? {};
86
+ currMetadata = { ...oldMetadata, ...currMetadata };
87
+ }
88
+ currMetadata = Object.keys(currMetadata).length === 0 ? undefined : currMetadata;
89
+ this.cacheMap.set(peer, { peer, type, metadata: currMetadata });
90
+ this._isCollected = true;
91
+ }
92
+
93
+ refresh(original: AstNode, node: AstNode): void {
94
+ let metadata: AstNodeCacheValueMetadata | undefined;
95
+ if (this.has(original)) {
96
+ metadata = this.get(original)?.metadata;
97
+ this.cacheMap.delete(original.peer);
98
+ }
99
+ this.collect(node, metadata);
100
+ }
101
+
102
+ isCollected(): boolean {
103
+ return this._isCollected;
104
+ }
105
+
106
+ has(node: AstNode): boolean {
107
+ return this.cacheMap.has(node.peer);
108
+ }
109
+
110
+ get(node: AstNode): AstNodeCacheValue | undefined {
111
+ return this.cacheMap.get(node.peer);
112
+ }
113
+
114
+ clear(): void {
115
+ this.cacheMap.clear();
116
+ this._isCollected = false;
117
+ }
118
+
119
+ visualize(): void {
120
+ Array.from(this.cacheMap.values()).forEach(({ peer, type, metadata }) => {
121
+ const src = global.generatedEs2panda._AstNodeDumpEtsSrcConst(global.context, peer)
122
+ console.log(
123
+ `[NODE CACHE] ptr ${peer}, type: ${type}, metadata: ${JSON.stringify(metadata)}, node: `,
124
+ unpackString(src)
125
+ );
126
+ });
127
+ }
128
+ }
129
+
130
+ function wrapFuncWithNodeCache(cache: MemoNodeCache, funcName: keyof typeof factory) {
131
+ if ((funcName+"__orig") in factory) return;
132
+
133
+ let orig = factory[funcName] as any;
134
+ let wrapped = function (this: any, original: AstNode, ...args: any[]) {
135
+ let newNode = orig.call(this, original, ...args);
136
+ if (cache.has(original)) {
137
+ cache.refresh(original, newNode);
138
+ }
139
+ return newNode
140
+ };
141
+ (factory as any)[funcName] = wrapped as any;
142
+ (factory as any)[funcName+"__orig"] = orig as any;
143
+ }
@@ -53,7 +53,7 @@ export class DumpingHooks implements RunTransformerHooks {
53
53
  }
54
54
  }
55
55
  onProgramTransformStart(options: CompilationOptions, program: Program) {
56
- if (this.dumpAst) {
56
+ if (this.dumpAst && !program.absoluteName.includes("absolute-sdk-patched")) {
57
57
  console.log(`BEFORE ${this.pluginName}:`);
58
58
  dumpProgramSrcFormatted(program, true);
59
59
  }
@@ -61,7 +61,7 @@ export class DumpingHooks implements RunTransformerHooks {
61
61
  }
62
62
  onProgramTransformEnd(options: CompilationOptions, program: Program) {
63
63
  if (!options.isProgramForCodegeneration) arktsGlobal.profiler.transformDepEnded(this.state, this.pluginName);
64
- if (this.dumpAst) {
64
+ if (this.dumpAst && !program.absoluteName.includes("absolute-sdk-patched")) {
65
65
  console.log(`AFTER ${this.pluginName}:`);
66
66
  dumpProgramSrcFormatted(program, true);
67
67
  }
@@ -73,7 +73,8 @@ export function runTransformerOnProgram(
73
73
  options: CompilationOptions,
74
74
  transform: ProgramTransformer | undefined,
75
75
  pluginContext: PluginContext,
76
- hooks: RunTransformerHooks = {}
76
+ hooks: RunTransformerHooks = {},
77
+ stableDeps: boolean = false,
77
78
  ) {
78
79
  arktsGlobal.filePath = program.absoluteName;
79
80
 
@@ -82,14 +83,19 @@ export function runTransformerOnProgram(
82
83
  // Perform some additional actions before the transformation start
83
84
  hooks.onProgramTransformStart?.(options, program);
84
85
 
85
- // Save currently existing imports in the program
86
- const importStorage = new ImportStorage(program, options.state == Es2pandaContextState.ES2PANDA_STATE_PARSED);
86
+ if (stableDeps) {
87
+ // Run the plugin itself
88
+ transform?.(program, options, pluginContext);
89
+ } else {
90
+ // Save currently existing imports in the program
91
+ const importStorage = new ImportStorage(program, options.state === Es2pandaContextState.ES2PANDA_STATE_PARSED);
87
92
 
88
- // Run the plugin itself
89
- transform?.(program, options, pluginContext);
93
+ // Run the plugin itself
94
+ transform?.(program, options, pluginContext);
90
95
 
91
- // Update internal import information based on import modification by plugin
92
- importStorage.update();
96
+ // Update internal import information based on import modification by plugin
97
+ importStorage.update();
98
+ }
93
99
 
94
100
  // Perform some additional actions after the transformation end
95
101
  hooks.onProgramTransformEnd?.(options, program);
@@ -102,10 +108,11 @@ export function runTransformer(
102
108
  state: Es2pandaContextState,
103
109
  transform: ProgramTransformer | undefined,
104
110
  pluginContext: PluginContext,
105
- hooks: RunTransformerHooks = {}
111
+ hooks: RunTransformerHooks = {},
112
+ stableDeps: boolean = false,
106
113
  ) {
107
114
  // Program provider used to provide programs to transformer dynamically relative to inserted imports
108
- const provider = new ProgramProvider(prog);
115
+ const provider = new ProgramProvider(prog, stableDeps);
109
116
 
110
117
  // The first program provided by program provider is the main program
111
118
  let currentProgram = provider.next();
@@ -118,7 +125,7 @@ export function runTransformer(
118
125
  state,
119
126
  };
120
127
 
121
- runTransformerOnProgram(currentProgram, options, transform, pluginContext, hooks);
128
+ runTransformerOnProgram(currentProgram, options, transform, pluginContext, hooks, stableDeps);
122
129
 
123
130
  // The first program is always the main program
124
131
  isMainProgram = false;
@@ -14,6 +14,8 @@
14
14
  */
15
15
  export { KNativePointer } from '@koalaui/interop';
16
16
  export { AstNode } from './arkts-api/peers/AstNode';
17
+ export { Config } from './arkts-api/peers/Config';
18
+ export { Context, GlobalContext } from './arkts-api/peers/Context';
17
19
  export { ArktsObject, isSameNativeObject } from './arkts-api/peers/ArktsObject';
18
20
  export { NodeCache } from './arkts-api/node-cache';
19
21
  export {