From 78b2e037c36566c3593cf93a1e433c7c063e49fd Mon Sep 17 00:00:00 2001 From: benStre Date: Sun, 21 Jan 2024 13:28:17 +0100 Subject: [PATCH 1/3] add DATEX WeakRefs (std:WeakRef) --- runtime/pointers.ts | 11 ++++------- runtime/runtime.ts | 37 ++++++++++++++++++++++++++++++++++++- types/type.ts | 5 +++++ 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/runtime/pointers.ts b/runtime/pointers.ts index b5b51a32..512e580d 100644 --- a/runtime/pointers.ts +++ b/runtime/pointers.ts @@ -2277,10 +2277,7 @@ export class Pointer extends Ref { this.val = v; return this; } - } - - - + } override get val():T { if (this.#garbage_collected) throw new PointerError("Pointer was garbage collected"); @@ -2288,7 +2285,7 @@ export class Pointer extends Ref { throw new PointerError("Cannot get value of uninitialized pointer") } // deref and check if not garbage collected - if (!this.is_persistent && !this.is_js_primitive && super.val instanceof WeakRef) { + if (!this.is_persistent && !this.is_js_primitive && super.val instanceof WeakRef && this.type !== Type.std.WeakRef) { const val = super.val.deref(); // seems to be garbage collected if (val === undefined && this.#loaded && !this.#is_js_primitive) { @@ -2316,7 +2313,7 @@ export class Pointer extends Ref { throw new PointerError("Cannot get value of uninitialized pointer") } // deref and check if not garbage collected - if (!this.is_persistent && !this.is_js_primitive && super.current_val instanceof WeakRef) { + if (!this.is_persistent && !this.is_js_primitive && super.current_val instanceof WeakRef && this.type !== Type.std.WeakRef) { const val = super.current_val.deref(); // seems to be garbage collected if (val === undefined && this.#loaded && !this.#is_js_primitive) { @@ -3384,7 +3381,7 @@ export class Pointer extends Ref { const res = JSInterface.createProxy(obj, this, this.type); if (res != INVALID && res != NOT_EXISTING) return res; // proxy created successfully - if (typeof obj == "symbol" || obj instanceof Stream || obj instanceof DatexFunction || obj instanceof JSTransferableFunction) { // no proxy needed?! + if (typeof obj == "symbol" || obj instanceof WeakRef || obj instanceof Stream || obj instanceof DatexFunction || obj instanceof JSTransferableFunction) { // no proxy needed?! return obj; } diff --git a/runtime/runtime.ts b/runtime/runtime.ts index 733e98e5..b1f8b1be 100644 --- a/runtime/runtime.ts +++ b/runtime/runtime.ts @@ -2224,7 +2224,6 @@ export class Runtime { let old_type = Type.ofValue(value); let old_value = value instanceof UnresolvedValue ? value[DX_VALUE] : value; - // already the right type if (old_type == type) return old_value; @@ -2232,6 +2231,7 @@ export class Runtime { // only handle std namespace / js:Object / js:Symbol if (type.namespace == "std" || type == Type.js.NativeObject || type == Type.js.Symbol) { + const uncollapsed_old_value = old_value if (old_value instanceof Pointer) old_value = old_value.val; // handle default casts @@ -2431,6 +2431,31 @@ export class Runtime { break; } + case Type.std.WeakRef: { + if (old_value === VOID) { + // empty weakref + new_value = new WeakRef(Symbol("EMPTY")); + new_value.deref = ()=>{}; + } + else if (typeof uncollapsed_old_value == "symbol" || typeof uncollapsed_old_value == "object" || typeof uncollapsed_old_value == "function") { + const ptr = Pointer.collapseValue(Pointer.createOrGet(uncollapsed_old_value)) + new_value = new WeakRef(ptr); + } + // pointer id -> resolve pointer + else if (typeof old_value == "string" && old_value.startsWith("$")) { + try { + const ptr = Pointer.collapseValue(await Pointer.load(old_value.slice(1))) + new_value = new WeakRef(ptr); + } + catch { + // pointer not found, empty weakref + new_value = new WeakRef(Symbol("EMPTY")); + new_value.deref = ()=>{}; + } + } + else new_value = INVALID; + break; + } case Type.std.time: { if (old_value === VOID) new_value = new Time(Date.now()); @@ -2627,6 +2652,16 @@ export class Runtime { // symbol if (typeof value == "symbol") return value.toString().slice(7,-1) || undefined + + // weakref + if (value instanceof WeakRef) { + const deref = value.deref(); + // empty weak ref + if (!deref) return VOID; + const ptr = Pointer.createOrGet(deref) + if (ptr) return "$"+ptr.id; + else throw new TypeError("Cannot serialize weakref to non-pointer value"); + } // directly return, cannot be overwritten if (value === VOID || value === null || value instanceof Endpoint || value instanceof Type) return value; diff --git a/types/type.ts b/types/type.ts index a6abb3a1..eb354931 100644 --- a/types/type.ts +++ b/types/type.ts @@ -784,6 +784,8 @@ export class Type extends ExtensibleFunction { if (value instanceof Disjunction) return >Type.std.Disjunction; if (value instanceof Negation) return >Type.std.Negation; + if (value instanceof WeakRef) return >Type.std.WeakRef; + // get type from DX_TYPE property if (value?.[DX_TYPE]) return value[DX_TYPE]; @@ -879,6 +881,7 @@ export class Type extends ExtensibleFunction { if (_forClass == Number || Number.isPrototypeOf(_forClass)) return >Type.std.decimal; if (_forClass == globalThis.Boolean || globalThis.Boolean.isPrototypeOf(_forClass)) return >Type.std.boolean; if (_forClass == Symbol || Symbol.isPrototypeOf(_forClass)) return >Type.js.Symbol; + if (_forClass == WeakRef || WeakRef.isPrototypeOf(_forClass)) return >Type.std.WeakRef; if (_forClass == ArrayBuffer || TypedArray.isPrototypeOf(_forClass)) return >Type.std.buffer; if (_forClass == Tuple || Tuple.isPrototypeOf(_forClass)) return >Type.std.Tuple; @@ -1032,6 +1035,8 @@ export class Type extends ExtensibleFunction { SecurityError: Type.get("std:DatexSecurityError"), AssertionError: Type.get("std:AssertionError"), + WeakRef: Type.get("std:WeakRef"), + Scope: Type.get("std:Scope"), Debugger: Type.get("std:Debugger"), From d7f673583347083a53dcb0e5d554f8afe6dec2e9 Mon Sep 17 00:00:00 2001 From: benStre Date: Mon, 22 Jan 2024 19:20:11 +0100 Subject: [PATCH 2/3] fix/workaround: unyt2 offline --- runtime/runtime.ts | 1 + types/addressing.ts | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/runtime/runtime.ts b/runtime/runtime.ts index b1f8b1be..3cca8e9f 100644 --- a/runtime/runtime.ts +++ b/runtime/runtime.ts @@ -1948,6 +1948,7 @@ export class Runtime { } let scope_map = sender_map?.get(sid); + // this is the next block or the only block (immediately closed) if (!scope_map || (scope_map.next == header.inc)) { diff --git a/types/addressing.ts b/types/addressing.ts index 5d2396b1..ccc1f835 100644 --- a/types/addressing.ts +++ b/types/addressing.ts @@ -410,7 +410,14 @@ export class Endpoint extends Target { // max allowed time for DATEX online ping response - static max_ping_response_time = 1000; + static max_ping_response_time = 2000; + static max_ping_response_time_unyt_node = 5000; + static unyt_nodes = [ + "@+unyt1", + "@+unyt2", + "@+unyt3" + ] + // online state cache reload time if currently online/offline static cache_life_offline = 3_000; static cache_life_online = 15_000; @@ -445,11 +452,24 @@ export class Endpoint extends Target { try { // ping - await Runtime.datexOut(['"ping"', [], {sign:false, encrypt:false}], this, undefined, true, false, undefined, false, undefined, Endpoint.max_ping_response_time); + await Runtime.datexOut( + ['"ping"', [], {sign:false, encrypt:false}], + this, + undefined, + true, + false, + undefined, + false, + undefined, + Endpoint.unyt_nodes.includes(this.main.toString()) ? + Endpoint.max_ping_response_time_unyt_node : + Endpoint.max_ping_response_time + ); resolve_online!(this.#current_online = true) } // could not reach endpoint - catch { + catch (e) { + console.warn("ping out failed " + this, e, new Date().getTime()) resolve_online!(this.#current_online = false) } From 1e83aad7405fc9b728ffe06e4af68888e7746a87 Mon Sep 17 00:00:00 2001 From: benStre Date: Mon, 22 Jan 2024 21:09:10 +0100 Subject: [PATCH 3/3] remove debug log --- runtime/pointers.ts | 10 ++++++++-- types/addressing.ts | 1 - 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/runtime/pointers.ts b/runtime/pointers.ts index 512e580d..1fd7c7ad 100644 --- a/runtime/pointers.ts +++ b/runtime/pointers.ts @@ -571,7 +571,7 @@ export class PointerProperty extends Ref { * @returns */ public static get>(parent: Parent|Pointer, key: Key, leak_js_properties = false): PointerProperty ? MV : Parent[Key&keyof Parent]> { - + console.warn("getpp",parent,key) if (Pointer.isRef(key)) throw new Error("Cannot use a reference as a pointer property key"); let pointer:Pointer; @@ -587,7 +587,13 @@ export class PointerProperty extends Ref { // get current pointer property public override get val():T { // this.handleBeforePrimitiveValueGet(); - return this.pointer.getProperty(this.key, this.#leak_js_properties); + const val = this.pointer.getProperty(this.key, this.#leak_js_properties); + if (this.pointer instanceof LazyPointer) return "lazy..." + else if (val === NOT_EXISTING) { + console.log(this) + throw new Error(`Property ${this.key} does not exist in ${this.pointer}`); + } + else return val; } public override get current_val():T { diff --git a/types/addressing.ts b/types/addressing.ts index ccc1f835..2f52f74e 100644 --- a/types/addressing.ts +++ b/types/addressing.ts @@ -469,7 +469,6 @@ export class Endpoint extends Target { } // could not reach endpoint catch (e) { - console.warn("ping out failed " + this, e, new Date().getTime()) resolve_online!(this.#current_online = false) }