diff --git a/runtime/pointers.ts b/runtime/pointers.ts index 14f6e23f..8c6145af 100644 --- a/runtime/pointers.ts +++ b/runtime/pointers.ts @@ -2119,7 +2119,13 @@ export class Pointer extends Ref { this.id = id ?? Pointer.getUniquePointerID(this) // set id this.#is_placeholder = false; // after id change // first time actual visible pointer - for (let l of Pointer.pointer_add_listeners) l(this); + for (const l of Pointer.pointer_add_listeners) l(this); + // pointer for id listeners + if (Pointer.pointer_for_id_created_listeners.has(this.id)) { + for (const l of Pointer.pointer_for_id_created_listeners.get(this.id)!) l(this); + Pointer.pointer_for_id_created_listeners.delete(this.id) + } + } // set id if not set initially set @@ -2129,6 +2135,7 @@ export class Pointer extends Ref { // if (!this.is_placeholder && this.id !== undefined && !Pointer.#local_pointers.has(this)) { // // console.log("TODO: pointer transfer map") // } + // is id transfer for placeholder, trigger value init if (typeof id == "string") { // convert string to buffer @@ -2271,7 +2278,6 @@ export class Pointer extends Ref { * @param v initial value */ protected initializeValue(v:RefOrValue, is_transform?:boolean) { - let val = Ref.collapseValue(v,true,true); if (typeof val == "symbol" && Symbol.keyFor(val) !== undefined) { diff --git a/types/function-utils.ts b/types/function-utils.ts index dfaedfd5..07685ab5 100644 --- a/types/function-utils.ts +++ b/types/function-utils.ts @@ -1,3 +1,4 @@ +import { LazyPointer } from "../runtime/lazy-pointer.ts"; import { callWithMetadata, callWithMetadataAsync, getMeta } from "../utils/caller_metadata.ts"; import { RuntimeError } from "./errors.ts"; @@ -134,12 +135,48 @@ const isArrowFunction = (fnSrc:string) => { return !!fnSrc.match(/^(async\s+)?\([^)]*\)\s*=>/) } +function resolveLazyDependencies(deps:Record) { + for (const [key, value] of Object.entries(deps)) { + if (value instanceof LazyPointer) value.onLoad((v) => { + deps[key] = v + }); + } +} + +function assertLazyDependenciesResolved(deps:Record) { + for (const [key, value] of Object.entries(deps)) { + // TODO non js-Function specific error + if (value instanceof LazyPointer) throw new Error("Cannot call , dependency variable '"+key+"' is not yet initialized") + } +} + +/** + * Create a new function from JS source code with injected dependency variables + * Also resolves LazyPointer dependencies + * @param source + * @param dependencies + * @returns + */ +export function createFunctionWithDependencyInjectionsResolveLazyPointers(source: string, dependencies: Record): ((...args:unknown[]) => unknown) { + let fn: Function|undefined; + + const intermediateFn = (...args:any[]) => { + if (!fn) { + assertLazyDependenciesResolved(dependencies); + fn = createFunctionWithDependencyInjections(source, dependencies) + } + return fn(...args) + } + resolveLazyDependencies(dependencies) + return intermediateFn; +} /** * Create a new function from JS source code with injected dependency variables * @param source * @param dependencies * @returns + * @deprecated use createFunctionWithDependencyInjectionsResolveLazyPointers */ export function createFunctionWithDependencyInjections(source: string, dependencies: Record): ((...args:unknown[]) => unknown) { const hasThis = Object.keys(dependencies).includes('this'); diff --git a/types/js-function.ts b/types/js-function.ts index ba02cf56..bf3c25c8 100644 --- a/types/js-function.ts +++ b/types/js-function.ts @@ -5,7 +5,7 @@ import { LazyPointer } from "../runtime/lazy-pointer.ts"; import { Pointer } from "../runtime/pointers.ts"; import { Runtime } from "../runtime/runtime.ts"; -import { ExtensibleFunction, getDeclaredExternalVariables, getDeclaredExternalVariablesAsync, createFunctionWithDependencyInjections, getSourceWithoutUsingDeclaration, Callable } from "./function-utils.ts"; +import { ExtensibleFunction, getDeclaredExternalVariables, getDeclaredExternalVariablesAsync, getSourceWithoutUsingDeclaration, Callable, createFunctionWithDependencyInjectionsResolveLazyPointers } from "./function-utils.ts"; export type JSTransferableFunctionOptions = { @@ -32,32 +32,15 @@ export class JSTransferableFunction extends ExtensibleFunction { if (origin !== Runtime.endpoint && !Runtime.trustedEndpoints.get(origin)?.includes("remote-js-execution")) { throw new Error("Cannot execute js:Function, origin "+origin+" has no permission to execute js source code on this endpoint"); } - this.assertLazyDependenciesResolved(); - if (this.deps.this) return intermediateFn.apply(this.deps.this, args) - else return intermediateFn(...args) + return intermediateFn(...args) } super(fn); - this.resolveLazyDependencies(); // make sure LazyPointer deps are resolved this.#fn = fn; } this.source = source; } - private resolveLazyDependencies() { - for (const [key, value] of Object.entries(this.deps)) { - if (value instanceof LazyPointer) value.onLoad((v) => this.deps[key] = v); - } - } - - #resolved = false; - private assertLazyDependenciesResolved() { - if (this.#resolved) return true; - for (const [key, value] of Object.entries(this.deps)) { - if (value instanceof LazyPointer) throw new Error("Cannot call , dependency variable '"+key+"' is not yet initialized") - } - this.#resolved = true; - } call(...args:any[]) { return this.#fn(...args) @@ -110,7 +93,7 @@ export class JSTransferableFunction extends ExtensibleFunction { } static #createTransferableFunction(source: string, dependencies: Record, flags?: string[], options?:JSTransferableFunctionOptions) { - const intermediateFn = createFunctionWithDependencyInjections(source, dependencies); + const intermediateFn = createFunctionWithDependencyInjectionsResolveLazyPointers(source, dependencies); return new JSTransferableFunction(intermediateFn, dependencies, source, flags, options); }