From 885867c499a9464ef8b81f2dd6a9457ceb2a2e4e Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 31 Jul 2025 11:58:24 +0300 Subject: [PATCH 1/5] CoroutineLocalValue.getAndSet --- incremental/compat/src/arkts/utils.ts | 6 ++++++ incremental/compat/src/typescript/utils.ts | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/incremental/compat/src/arkts/utils.ts b/incremental/compat/src/arkts/utils.ts index ec855ec898..c7b90072fa 100644 --- a/incremental/compat/src/arkts/utils.ts +++ b/incremental/compat/src/arkts/utils.ts @@ -40,10 +40,16 @@ export function launchJob(task: () => void): Promise { } export class CoroutineLocalValue { + static readonly SUPPORTED = true private map = new containers.ConcurrentHashMap get(): T | undefined { return this.map.get(CoroutineExtras.getWorkerId()) } + getAndSet(value: T | undefined): T | undefined { + const result = this.get() + this.set(value) + return result + } set(value: T | undefined) { if (value) { this.map.set(CoroutineExtras.getWorkerId(), value) diff --git a/incremental/compat/src/typescript/utils.ts b/incremental/compat/src/typescript/utils.ts index 1169707fa5..b31284f548 100644 --- a/incremental/compat/src/typescript/utils.ts +++ b/incremental/compat/src/typescript/utils.ts @@ -42,10 +42,16 @@ export function launchJob(task: () => void): Promise { } export class CoroutineLocalValue { + static readonly SUPPORTED = false private value: T | undefined = undefined get(): T | undefined { return this.value } + getAndSet(value: T | undefined): T | undefined { + const result = this.value + this.value = value + return result + } set(value: T | undefined) { this.value = value } -- Gitee From 907f9c650eedaeec6b7b2af78d32f17f784a41b6 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 31 Jul 2025 12:01:24 +0300 Subject: [PATCH 2/5] stateCreating to safe namedStateCreating --- incremental/runtime/src/states/State.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/incremental/runtime/src/states/State.ts b/incremental/runtime/src/states/State.ts index e232031029..fa7533c403 100644 --- a/incremental/runtime/src/states/State.ts +++ b/incremental/runtime/src/states/State.ts @@ -631,7 +631,7 @@ class ParameterImpl implements StateEx, MutableState { } export /* Improve:HQ private as public*/ class StateManagerImpl implements StateManager { - private stateCreating: string | undefined = undefined + private readonly namedStateCreating = new CoroutineLocalValue() private readonly statesNamed: Map = new Map() private readonly statesCreated: Set = new Set() private readonly dirtyScopes: Set = new Set() @@ -791,7 +791,7 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State * except for computable scopes used for animation. */ get dependency(): Dependency | undefined { - if (this.stateCreating === undefined) { + if (this.namedStateCreating.get() === undefined) { const scope = this.current if (scope?.once == false && (scope?.nodeRef === undefined || this.external === undefined)) { return scope @@ -847,9 +847,9 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State let state = global ? this.getNamedState(name) : scope?.getNamedState(name) if (state) return state // named state is already exist this.checkForStateCreating() - this.stateCreating = name + this.namedStateCreating.set(name) let initial = create() - this.stateCreating = undefined + this.namedStateCreating.set(undefined) state = new StateImpl(this, initial, global, equivalent, tracker, name) if (global) this.statesNamed.set(name, state) else if (scope) scope.setNamedState(name, state) @@ -901,7 +901,7 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State } checkForStateCreating(): void { - const name = this.stateCreating + const name = this.namedStateCreating.get() if (name === undefined) return const scope = this.current throw new Error(scope -- Gitee From 3e256d9b9d73f8f564b0256cc1c6969ce4149ebe Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 31 Jul 2025 13:26:30 +0300 Subject: [PATCH 3/5] external to safe externalControlledScope --- incremental/runtime/src/states/State.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/incremental/runtime/src/states/State.ts b/incremental/runtime/src/states/State.ts index fa7533c403..aed5c16812 100644 --- a/incremental/runtime/src/states/State.ts +++ b/incremental/runtime/src/states/State.ts @@ -636,7 +636,7 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State private readonly statesCreated: Set = new Set() private readonly dirtyScopes: Set = new Set() current: ManagedScope | undefined = undefined - external: Dependency | undefined = undefined + readonly externalControlledScope = new CoroutineLocalValue() updateNeeded: boolean = false frozen: boolean = false private readonly callbacks = markableQueue() @@ -793,11 +793,11 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State get dependency(): Dependency | undefined { if (this.namedStateCreating.get() === undefined) { const scope = this.current - if (scope?.once == false && (scope?.nodeRef === undefined || this.external === undefined)) { + if (scope?.once == false && (scope?.nodeRef === undefined || this.externalControlledScope.get() === undefined)) { return scope } } - return this.external + return this.externalControlledScope.get() } scope(id: KoalaCallsiteKey, paramCount: int32): IncrementalScope { @@ -1396,15 +1396,14 @@ class ControlledScopeImpl implements Dependency, ControlledScope { enter(): void { const manager = this.manager if (manager === undefined) throw new Error("ControlledScope is already disposed") - this.old = manager.external - manager.external = this + this.old = manager.externalControlledScope.getAndSet(this) } leave(): void { const manager = this.manager if (manager === undefined) throw new Error("ControlledScope is already disposed") - if (manager.external !== this) throw new Error("ControlledScope is not valid") - manager.external = this.old + if (manager.externalControlledScope.get() !== this) throw new Error("ControlledScope is not valid") + manager.externalControlledScope.set(this.old) this.old = undefined this._states?.reset() } -- Gitee From 2c3936c76d9c97590c463289cc6bd9190eab4d5b Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 31 Jul 2025 13:54:00 +0300 Subject: [PATCH 4/5] current to safe currentManagedScope --- incremental/runtime/src/states/State.ts | 35 +++++++++++++------------ 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/incremental/runtime/src/states/State.ts b/incremental/runtime/src/states/State.ts index aed5c16812..84a4cfdde8 100644 --- a/incremental/runtime/src/states/State.ts +++ b/incremental/runtime/src/states/State.ts @@ -635,7 +635,7 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State private readonly statesNamed: Map = new Map() private readonly statesCreated: Set = new Set() private readonly dirtyScopes: Set = new Set() - current: ManagedScope | undefined = undefined + readonly currentManagedScope = new CoroutineLocalValue() readonly externalControlledScope = new CoroutineLocalValue() updateNeeded: boolean = false frozen: boolean = false @@ -648,6 +648,10 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State private childManager: Array = new Array() private parentManager: StateManagerImpl | undefined = undefined + get current(): ManagedScope | undefined { + return this.currentManagedScope.get() + } + get currentScopeId(): KoalaCallsiteKey | undefined { return this.current?.id } @@ -734,10 +738,10 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State scope.node = node scope.nodeRef = node scope.dependencies = new StateToScopes() - this.current = scope // to attach named states to this scope + const prevScope = this.currentManagedScope.getAndSet(scope) // to attach named states to this scope scope.setNamedState(CONTEXT_ROOT_SCOPE, new StateImpl>(this, scope, false)) scope.setNamedState(CONTEXT_ROOT_NODE, new StateImpl(this, node, false)) - this.current = undefined + this.currentManagedScope.set(prevScope) return scope } @@ -946,7 +950,7 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State StateManagerLocal.set(context) builder(context); StateManagerLocal.set(old) - context.current = undefined + context.currentManagedScope.set(undefined) if (complete) { complete(); } @@ -1008,7 +1012,7 @@ class ScopeImpl implements ManagedScope, IncrementalScope, Computa private statesNamed: Map | undefined = undefined private statesCreated: Array | undefined = undefined - private scopeInternal: ManagedScope | undefined = undefined + private prevScope: ManagedScope | undefined = undefined private incremental: ManagedScope | undefined = undefined private child: ManagedScope | undefined = undefined @@ -1133,10 +1137,10 @@ class ScopeImpl implements ManagedScope, IncrementalScope, Computa } else if (create) { // create node within a scope scope._once = true - manager.current = scope + manager.currentManagedScope.set(scope) if (this.nodeRef === undefined) throw new Error("prohibited to add nodes into computable state") scope.node = create() - manager.current = this + manager.currentManagedScope.set(this) } scope.nodeRef = scope.node ?? this.nodeRef scope._once = once == true @@ -1162,14 +1166,13 @@ class ScopeImpl implements ManagedScope, IncrementalScope, Computa } const manager = this.manager if (manager === undefined) throw new Error("unexpected") - const scope = manager.current - manager.current = undefined // allow to dispose children during recomputation + const prevScope = manager.currentManagedScope.getAndSet(undefined) // allow to dispose children during recomputation while (child != last) { if (child === undefined) throw new Error("unexpected") this.recycleOrDispose(child!!) child = child.next } - manager.current = scope + manager.currentManagedScope.getAndSet(prevScope) } increment(count: uint32, skip: boolean): void { @@ -1199,8 +1202,7 @@ class ScopeImpl implements ManagedScope, IncrementalScope, Computa this.nodeCount = 0 const manager = this.manager if (manager) { - this.scopeInternal = manager.current - manager.current = this + this.prevScope = manager.currentManagedScope.getAndSet(this) } return false } else { @@ -1212,7 +1214,7 @@ class ScopeImpl implements ManagedScope, IncrementalScope, Computa recache(newValue?: Value): Value { const manager = this.manager if (manager) { - manager.current = this.scopeInternal + manager.currentManagedScope.set(this.prevScope) this._states?.reset() } const oldValue = this.myValue @@ -1318,8 +1320,7 @@ class ScopeImpl implements ManagedScope, IncrementalScope, Computa this.manager = undefined this._states = this._states?.clear() this.dependencies = this.dependencies?.clear() - const scope = manager.current - manager.current = this + const prevScope = manager.currentManagedScope.getAndSet(this) try { this.myCleanup?.(this.myValue) } catch (cause) { @@ -1335,7 +1336,7 @@ class ScopeImpl implements ManagedScope, IncrementalScope, Computa this.parentScope = undefined this.node = undefined this.nodeRef = undefined - this.scopeInternal = undefined + this.prevScope = undefined const statesCreated = this.statesCreated if (statesCreated) { disposeContentBackward(statesCreated) @@ -1346,7 +1347,7 @@ class ScopeImpl implements ManagedScope, IncrementalScope, Computa disposeContentBackward(params) this.params = undefined } - manager.current = scope + manager.currentManagedScope.set(prevScope) this.myModified = false if (error) throw error } -- Gitee From 6428f577eb6c8ea9b340fefbac29ed1704a07486 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 31 Jul 2025 17:03:29 +0300 Subject: [PATCH 5/5] frozen to safe frozenStates --- arkoala-arkts/arkui/src/ArkUIEntry.ets | 9 ------ arkoala-arkts/arkui/src/Storage.ets | 2 +- .../ets-harness/src/EtsHarnessApplication.ts | 3 -- arkoala/arkui-common/src/Storage.ts | 2 +- incremental/runtime/src/memo/entry.ts | 3 -- incremental/runtime/src/states/State.ts | 15 ++++++++-- .../arkoala-arkts/arkui/src/Application.ets | 6 ---- .../libarkts/native/src/generated/bridges.cc | 30 ++++++++++++++++++- .../src/generated/Es2pandaNativeModule.ts | 9 ++++++ .../src/generated/peers/ScriptFunction.ts | 8 +++++ 10 files changed, 61 insertions(+), 26 deletions(-) diff --git a/arkoala-arkts/arkui/src/ArkUIEntry.ets b/arkoala-arkts/arkui/src/ArkUIEntry.ets index 9015daf17d..26f1b6626d 100644 --- a/arkoala-arkts/arkui/src/ArkUIEntry.ets +++ b/arkoala-arkts/arkui/src/ArkUIEntry.ets @@ -95,10 +95,7 @@ export function createUiDetachedBuilderRoot( manager: StateManager ): ComputableState { const node = manager.updatableNode(peerFactory(), (context: StateContext) => { - const frozen = manager.frozen - manager.frozen = true memoEntry(context, 0, builder) - manager.frozen = frozen }) detachedRoots.set(node.value.peer.ptr, node) detachedStateManager.set(new WeakRef(manager), new WeakRef>(node)) @@ -112,10 +109,7 @@ export function createUiDetachedRoot( ): PeerNode { const manager = GlobalStateManager.instance const node = manager.updatableNode(peerFactory(), (context: StateContext) => { - const frozen = manager.frozen - manager.frozen = true memoEntry(context, 0, builder) - manager.frozen = frozen }) detachedRoots.set(node.value.peer.ptr, node) return node.value @@ -329,10 +323,7 @@ export class Application implements UserApplicationControl { ): ComputableState { const peer = PeerNode.generateRootPeer() return manager.updatableNode(peer, (context: StateContext) => { - const frozen = manager.frozen - manager.frozen = true memoEntry(context, 0, () => { Routed(builder) }) - manager.frozen = frozen }) } diff --git a/arkoala-arkts/arkui/src/Storage.ets b/arkoala-arkts/arkui/src/Storage.ets index d55dc78479..85f5fe6963 100644 --- a/arkoala-arkts/arkui/src/Storage.ets +++ b/arkoala-arkts/arkui/src/Storage.ets @@ -788,7 +788,7 @@ class StorageProp implements SubscribedAbstractProperty { const entry = this.map.entryOrCreate(this.name, value) if (entry.modified) { value = entry.get() - if (this.map.manager.frozen) { + if (this.map.manager.currentScopeId !== undefined) { this.map.manager.scheduleCallback(() => { this.set(value) }) } else { this.set(value) diff --git a/arkoala-arkts/ets-harness/src/EtsHarnessApplication.ts b/arkoala-arkts/ets-harness/src/EtsHarnessApplication.ts index 1f3cf6a3b5..f79cc4b6ea 100644 --- a/arkoala-arkts/ets-harness/src/EtsHarnessApplication.ts +++ b/arkoala-arkts/ets-harness/src/EtsHarnessApplication.ts @@ -65,10 +65,7 @@ function createMemoRoot( ): ComputableState { const peer = PeerNode.generateRootPeer() const node = manager.updatableNode(peer, (context: StateContext) => { - const frozen = manager.frozen - manager.frozen = true memoEntry(context, 0, builder) - manager.frozen = frozen }) node.value return node diff --git a/arkoala/arkui-common/src/Storage.ts b/arkoala/arkui-common/src/Storage.ts index ea378ccaf1..1a326c1aa2 100644 --- a/arkoala/arkui-common/src/Storage.ts +++ b/arkoala/arkui-common/src/Storage.ts @@ -869,7 +869,7 @@ class StorageProp extends SubscribedAbstractProperty { const entry = this.map.entryOrCreate(this.name, value) if (entry.state.modified) { value = entry.state.value - if (this.map.manager.frozen) { + if (this.map.manager.currentScopeId !== undefined) { this.map.manager.scheduleCallback(() => { this.set(value) }) } else { this.state.value = value diff --git a/incremental/runtime/src/memo/entry.ts b/incremental/runtime/src/memo/entry.ts index 3080bcc2a2..dc837aac93 100644 --- a/incremental/runtime/src/memo/entry.ts +++ b/incremental/runtime/src/memo/entry.ts @@ -34,10 +34,7 @@ export function memoRoot( ): ComputableState { return manager.updatableNode(node, (context: StateContext) => { RuntimeProfiler.instance?.buildRootEnter() - const frozen = manager.frozen - manager.frozen = true // states are frozen during recomposition memoEntry1(context, 0, update, node) - manager.frozen = frozen RuntimeProfiler.instance?.buildRootExit() }) } diff --git a/incremental/runtime/src/states/State.ts b/incremental/runtime/src/states/State.ts index 84a4cfdde8..a0462530e4 100644 --- a/incremental/runtime/src/states/State.ts +++ b/incremental/runtime/src/states/State.ts @@ -93,6 +93,7 @@ export interface StateManager extends StateContext { updatableNode(node: Node, update: (context: StateContext) => void, cleanup?: () => void): ComputableState scheduleCallback(callback: () => void): void callCallbacks(): void + /** @deprecated */ frozen: boolean reset(): void } @@ -353,7 +354,9 @@ export /* Improve:HQ private as public*/ class StateImpl implements Obser get value(): Value { this.onAccess() const manager = this.manager - return manager === undefined || manager.frozen ? this.snapshot : this.current(manager.journal) + if (!manager || manager.frozen) return this.snapshot + if (manager.current?.nodeRef) return this.snapshot + return this.current(manager.journal) } set value(value: Value) { @@ -638,7 +641,7 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State readonly currentManagedScope = new CoroutineLocalValue() readonly externalControlledScope = new CoroutineLocalValue() updateNeeded: boolean = false - frozen: boolean = false + private readonly frozenStates = new CoroutineLocalValue() private readonly callbacks = markableQueue() readonly journal: Journal = new Journal() @@ -648,6 +651,14 @@ export /* Improve:HQ private as public*/ class StateManagerImpl implements State private childManager: Array = new Array() private parentManager: StateManagerImpl | undefined = undefined + set frozen(flag: boolean) { + this.frozenStates.set(flag) + } + + get frozen(): boolean { + return this.frozenStates.get() == true + } + get current(): ManagedScope | undefined { return this.currentManagedScope.get() } diff --git a/subset/arkoala-arkts/arkui/src/Application.ets b/subset/arkoala-arkts/arkui/src/Application.ets index 16221500cd..8f689fd5f3 100644 --- a/subset/arkoala-arkts/arkui/src/Application.ets +++ b/subset/arkoala-arkts/arkui/src/Application.ets @@ -87,10 +87,7 @@ export function createUiDetachedRoot( ): PeerNode { const manager = GlobalStateManager.instance const node = manager.updatableNode(peerFactory(), (context: StateContext) => { - const frozen = manager.frozen - manager.frozen = true memoEntry(context, 0, builder ) - manager.frozen = frozen }) detachedRoots.set(node.value.peer.ptr, node) return node.value @@ -169,10 +166,7 @@ export class Application { ): ComputableState { const peer = PeerNode.generateRootPeer() return manager.updatableNode(peer, (context: StateContext) => { - const frozen = manager.frozen - manager.frozen = true memoEntry(context, 0, () => { Routed(builder) } ) - manager.frozen = frozen }) } diff --git a/ui2abc/libarkts/native/src/generated/bridges.cc b/ui2abc/libarkts/native/src/generated/bridges.cc index adf27ac393..498f344633 100644 --- a/ui2abc/libarkts/native/src/generated/bridges.cc +++ b/ui2abc/libarkts/native/src/generated/bridges.cc @@ -17,7 +17,7 @@ /* * THIS FILE IS AUTOGENERATED BY arktscgen v2.1.9-arktscgen-8. DO NOT EDIT MANUALLY! - * es2panda c2e49f679ddaf2ddd5970f5d5294b73fe9164283(2025-07-28) sdk v1.5.0-dev.39026 + * es2panda 988bd1919fa3e4afed7765898f69b33e7930a3aa(2025-07-31) sdk v1.5.0-dev.39495 */ KNativePointer impl_CreateNumberLiteral(KNativePointer context, KInt value) @@ -4281,6 +4281,34 @@ KUInt impl_ScriptFunctionFormalParamsLengthConst(KNativePointer context, KNative } KOALA_INTEROP_2(ScriptFunctionFormalParamsLengthConst, KUInt, KNativePointer, KNativePointer); +void impl_ScriptFunctionSetAsyncPairMethod(KNativePointer context, KNativePointer receiver, KNativePointer asyncPairFunction) +{ + const auto _context = reinterpret_cast(context); + const auto _receiver = reinterpret_cast(receiver); + const auto _asyncPairFunction = reinterpret_cast(asyncPairFunction); + GetImpl()->ScriptFunctionSetAsyncPairMethod(_context, _receiver, _asyncPairFunction); + return ; +} +KOALA_INTEROP_V3(ScriptFunctionSetAsyncPairMethod, KNativePointer, KNativePointer, KNativePointer); + +KNativePointer impl_ScriptFunctionAsyncPairMethodConst(KNativePointer context, KNativePointer receiver) +{ + const auto _context = reinterpret_cast(context); + const auto _receiver = reinterpret_cast(receiver); + auto result = GetImpl()->ScriptFunctionAsyncPairMethodConst(_context, _receiver); + return (void*)result; +} +KOALA_INTEROP_2(ScriptFunctionAsyncPairMethodConst, KNativePointer, KNativePointer, KNativePointer); + +KNativePointer impl_ScriptFunctionAsyncPairMethod(KNativePointer context, KNativePointer receiver) +{ + const auto _context = reinterpret_cast(context); + const auto _receiver = reinterpret_cast(receiver); + auto result = GetImpl()->ScriptFunctionAsyncPairMethod(_context, _receiver); + return result; +} +KOALA_INTEROP_2(ScriptFunctionAsyncPairMethod, KNativePointer, KNativePointer, KNativePointer); + void impl_ScriptFunctionEmplaceReturnStatements(KNativePointer context, KNativePointer receiver, KNativePointer returnStatements) { const auto _context = reinterpret_cast(context); diff --git a/ui2abc/libarkts/src/generated/Es2pandaNativeModule.ts b/ui2abc/libarkts/src/generated/Es2pandaNativeModule.ts index e916648c73..53714b00b5 100644 --- a/ui2abc/libarkts/src/generated/Es2pandaNativeModule.ts +++ b/ui2abc/libarkts/src/generated/Es2pandaNativeModule.ts @@ -1343,6 +1343,15 @@ export class Es2pandaNativeModule { _ScriptFunctionFormalParamsLengthConst(context: KNativePointer, receiver: KNativePointer): KUInt { throw new Error("This methods was not overloaded by native module initialization") } + _ScriptFunctionSetAsyncPairMethod(context: KNativePointer, receiver: KNativePointer, asyncPairFunction: KNativePointer): void { + throw new Error("This methods was not overloaded by native module initialization") + } + _ScriptFunctionAsyncPairMethodConst(context: KNativePointer, receiver: KNativePointer): KNativePointer { + throw new Error("This methods was not overloaded by native module initialization") + } + _ScriptFunctionAsyncPairMethod(context: KNativePointer, receiver: KNativePointer): KNativePointer { + throw new Error("This methods was not overloaded by native module initialization") + } _ScriptFunctionEmplaceReturnStatements(context: KNativePointer, receiver: KNativePointer, returnStatements: KNativePointer): void { throw new Error("This methods was not overloaded by native module initialization") } diff --git a/ui2abc/libarkts/src/generated/peers/ScriptFunction.ts b/ui2abc/libarkts/src/generated/peers/ScriptFunction.ts index deeab37c08..475cc9607c 100644 --- a/ui2abc/libarkts/src/generated/peers/ScriptFunction.ts +++ b/ui2abc/libarkts/src/generated/peers/ScriptFunction.ts @@ -216,6 +216,14 @@ export class ScriptFunction extends AstNode { return global.generatedEs2panda._ScriptFunctionFormalParamsLengthConst(global.context, this.peer) } /** @deprecated */ + setAsyncPairMethod(asyncPairFunction?: ScriptFunction): this { + global.generatedEs2panda._ScriptFunctionSetAsyncPairMethod(global.context, this.peer, passNode(asyncPairFunction)) + return this + } + get asyncPairMethod(): ScriptFunction | undefined { + return unpackNode(global.generatedEs2panda._ScriptFunctionAsyncPairMethod(global.context, this.peer)) + } + /** @deprecated */ emplaceReturnStatements(returnStatements?: ReturnStatement): this { global.generatedEs2panda._ScriptFunctionEmplaceReturnStatements(global.context, this.peer, passNode(returnStatements)) return this -- Gitee