diff --git a/init.ts b/init.ts index adb31cd3..cc9d945c 100644 --- a/init.ts +++ b/init.ts @@ -101,7 +101,22 @@ export async function init() { // init persistent subscriber cache (async () => { - Runtime.subscriber_cache = (await Storage.loadOrCreate("Datex.Runtime.SUBSCRIBER_CACHE", ()=>new Map())).setAutoDefault(Set); + try { + Runtime.subscriber_cache = (await Storage.loadOrCreate( + "Datex.Runtime.SUBSCRIBER_CACHE", + () => new Map(), + {onlyLocalPointers: true} + )).setAutoDefault(Set); + } + catch (e) { + logger.debug("resetting subscriber cache (" + e?.message + ")") + Runtime.subscriber_cache = (await Storage.loadOrCreate( + "Datex.Runtime.SUBSCRIBER_CACHE", + () => new Map(), + undefined, + true + )).setAutoDefault(Set); + } })() diff --git a/network/supranet.ts b/network/supranet.ts index e7eea059..88636915 100644 --- a/network/supranet.ts +++ b/network/supranet.ts @@ -313,6 +313,7 @@ export class Supranet { return `@@${buffer2hex(new Uint8Array(id.buffer))}`; } + public static async getLocalEndpointAndKeys():Promise<[Endpoint|UnresolvedEndpointProperty, Crypto.ExportedKeySet]> { let endpoint: Endpoint|UnresolvedEndpointProperty; @@ -339,8 +340,11 @@ export class Supranet { return [endpoint, await this.getKeysOrGenerateNew()]; } + /** + * Create new anonymous endpoint or load from "datex-endpoint" cookie + */ private static createAndSaveNewEndpoint(){ - const endpoint = Endpoint.get(this.createEndpointId()); + const endpoint = Endpoint.getFromCookie() ?? Endpoint.get(Endpoint.createNewID()); endpoint_config.endpoint = endpoint; endpoint_config.save(); return endpoint; diff --git a/runtime/pointers.ts b/runtime/pointers.ts index 4919637a..393f245e 100644 --- a/runtime/pointers.ts +++ b/runtime/pointers.ts @@ -1151,6 +1151,14 @@ export class Pointer extends Ref { const id_string = Pointer.normalizePointerId(id); + // only load if local pointer id + if (SCOPE?.exec_conditions?.onlyLocalPointers) { + const origin = Pointer.getOriginFromPointerId(id_string); + if (origin !== LOCAL_ENDPOINT && origin !== Runtime.endpoint) { + throw new Error("Tried to load non-local pointer"); + } + } + if (SCOPE) { // recursive pointer loading! TODO if (this.loading_pointers.get(id_string)?.scopeList.has(SCOPE)) { @@ -1205,10 +1213,11 @@ export class Pointer extends Ref { let priority:number; for ([source,priority] of this.#pointer_sources) { try { - stored = await source.getPointer(pointer.id, !SCOPE); + stored = await source.getPointer(pointer.id, !SCOPE, SCOPE?.exec_conditions?.onlyLocalPointers??false); } catch (e) { - logger.error("pointer source error:",e) + this.loading_pointers.delete(id_string); + throw e; } if (stored != NOT_EXISTING) break; } @@ -1320,7 +1329,6 @@ export class Pointer extends Ref { // intentionally not loaded else if (only_load_local) { this.loading_pointers.delete(id_string); - pointer.delete(); throw new PointerError("Pointer $"+id_string+" was not found locally", SCOPE); } diff --git a/runtime/runtime.ts b/runtime/runtime.ts index 66115cba..41e5c69e 100644 --- a/runtime/runtime.ts +++ b/runtime/runtime.ts @@ -36,7 +36,7 @@ import { Function as DatexFunction } from "../types/function.ts"; import { Storage } from "../runtime/storage.ts"; import { Observers } from "../utils/observers.ts"; import { BinaryCode } from "../compiler/binary_codes.ts"; -import type { compile_info, datex_meta, datex_scope, dxb_header, routing_info } from "../utils/global_types.ts"; +import type { ExecConditions, compile_info, datex_meta, datex_scope, dxb_header, routing_info } from "../utils/global_types.ts"; import { Markdown } from "../types/markdown.ts"; import { Type } from "../types/type.ts"; import { Tuple } from "../types/tuple.ts"; @@ -73,6 +73,7 @@ import type { Blockchain } from "../network/blockchain_adapter.ts"; import { AutoMap } from "../utils/auto_map.ts"; import { Supranet } from "../network/supranet.ts"; import { sendDatexViaHTTPChannel } from "../network/datex-http-channel.ts"; +import { setCookie } from "../utils/cookies.ts"; const mime = client_type === "deno" ? (await import("https://deno.land/x/mimetypes@v1.0.0/mod.ts")).mime : null; @@ -744,10 +745,11 @@ export class Runtime { * @param dxb_base64 DATEX Data Binary (without header) as Base64 string * @returns evaluated DATEX result */ - public static decodeValueBase64(dxb_base64:string, outer_serialized=false):Promise { + public static decodeValueBase64(dxb_base64:string, outer_serialized=false, conditions?:ExecConditions):Promise { // create scope const scope = Runtime.createNewInitialScope(); scope.outer_serialized = outer_serialized; + scope.exec_conditions = conditions; // set dxb as scope buffer Runtime.updateScope(scope, base64ToArrayBuffer(dxb_base64), {end_of_scope:true, sender:Runtime.endpoint}) // execute scope @@ -759,10 +761,11 @@ export class Runtime { * @param dxb DATEX Data Binary (without header) * @returns evaluated DATEX result */ - public static decodeValue(dxb:ArrayBuffer, outer_serialized=false):Promise { + public static decodeValue(dxb:ArrayBuffer, outer_serialized=false, conditions?:ExecConditions):Promise { // create scope const scope = Runtime.createNewInitialScope(); scope.outer_serialized = outer_serialized; + scope.exec_conditions = conditions; // set dxb as scope buffer Runtime.updateScope(scope, dxb, {end_of_scope:true, sender:Runtime.endpoint}) // execute scope @@ -1077,7 +1080,7 @@ export class Runtime { * Handles beforeunload (sending GOODBYE) * @param endpoint */ - static addActiveEndpoint(endpoint:Endpoint) { + static setActiveEndpoint(endpoint:Endpoint) { let endpoints:string[] = []; try { endpoints = JSON.parse(localStorage['active_endpoints']) as string[] @@ -1122,6 +1125,11 @@ export class Runtime { } localStorage['active_endpoints'] = JSON.stringify(endpoints) + + // update endpoint cookie + const endpointName = endpoint.toString(); + // TODO: store signed endpoint validation cookie + if (client_type == "browser") setCookie("datex-endpoint", endpointName); } static getActiveLocalStorageEndpoints() { @@ -1144,7 +1152,7 @@ export class Runtime { public static init(endpoint?:Endpoint) { // save all currently active endpoints for shared local storage (multiple tabs) - if (endpoint && endpoint != LOCAL_ENDPOINT && client_type == "browser") this.addActiveEndpoint(endpoint) + if (endpoint && endpoint != LOCAL_ENDPOINT && client_type == "browser") this.setActiveEndpoint(endpoint) if (endpoint) Runtime.endpoint = endpoint; @@ -1941,6 +1949,9 @@ export class Runtime { else if (header.type == ProtocolDataType.UPDATE) { // ignore } + else if (header.type == ProtocolDataType.GOODBYE) { + console.error("Error in GOODBYE message:",e) + } else { logger.error("Invalid proctocol data type: " + ProtocolDataTypesMap[header.type]??header.type) } diff --git a/runtime/storage-locations/deno-kv.ts b/runtime/storage-locations/deno-kv.ts index 4f39e2ce..ad9e9eab 100644 --- a/runtime/storage-locations/deno-kv.ts +++ b/runtime/storage-locations/deno-kv.ts @@ -7,6 +7,7 @@ import { AsyncStorageLocation } from "../storage.ts"; import { ptr_cache_path } from "../cache_path.ts"; import { client_type } from "../../utils/constants.ts"; import { normalizePath } from "../../utils/normalize-path.ts"; +import { ExecConditions } from "../../utils/global_types.ts"; const denoKvDir = new URL("./deno-kv/", ptr_cache_path); // @ts-ignore global Deno @@ -37,10 +38,10 @@ export class DenoKVStorageLocation extends AsyncStorageLocation { await this.set(itemDB!, key, Compiler.encodeValue(value)); return true; } - async getItem(key: string): Promise { + async getItem(key: string, conditions?: ExecConditions): Promise { const result = await this.get(itemDB!, key); if (result == null) return NOT_EXISTING; - else return Runtime.decodeValue(result); + else return Runtime.decodeValue(result, false, conditions); } hasItem(key:string) { @@ -81,10 +82,10 @@ export class DenoKVStorageLocation extends AsyncStorageLocation { await this.set(pointerDB!, pointer.id, Compiler.encodeValue(pointer, inserted_ptrs, true, false, true)); return inserted_ptrs; } - async getPointerValue(pointerId: string, outer_serialized: boolean): Promise { + async getPointerValue(pointerId: string, outer_serialized: boolean, conditions?: ExecConditions): Promise { const result = await this.get(pointerDB!, pointerId); if (result == null) return NOT_EXISTING; - else return Runtime.decodeValue(result, outer_serialized); + else return Runtime.decodeValue(result, outer_serialized, conditions); } async removePointer(pointerId: string): Promise { await pointerDB!.delete([pointerId]); diff --git a/runtime/storage-locations/indexed-db.ts b/runtime/storage-locations/indexed-db.ts index 62acbce1..aea89a1a 100644 --- a/runtime/storage-locations/indexed-db.ts +++ b/runtime/storage-locations/indexed-db.ts @@ -6,6 +6,7 @@ import { NOT_EXISTING } from "../constants.ts"; import { AsyncStorageLocation, site_suffix } from "../storage.ts"; import localforage from "../../lib/localforage/localforage.js"; +import { ExecConditions } from "../../utils/global_types.ts"; // db based storage for DATEX value caching (IndexDB in the browser) const datex_item_storage = localforage.createInstance({name: "dxitem::"+site_suffix}); @@ -14,9 +15,10 @@ const datex_pointer_storage = localforage.createIn export class IndexedDBStorageLocation extends AsyncStorageLocation { - name = "INDEXED_DB" + supportsExecConditions = true + isSupported() { return !!globalThis.indexedDB; } @@ -25,10 +27,10 @@ export class IndexedDBStorageLocation extends AsyncStorageLocation { await datex_item_storage.setItem(key, Compiler.encodeValue(value)); // value to buffer (no header) return true; } - async getItem(key: string): Promise { + async getItem(key: string, conditions: ExecConditions): Promise { const buffer = await datex_item_storage.getItem(key); if (buffer == null) return NOT_EXISTING; - else return Runtime.decodeValue(buffer); + else return Runtime.decodeValue(buffer, false, conditions); } async hasItem(key:string) { @@ -68,10 +70,10 @@ export class IndexedDBStorageLocation extends AsyncStorageLocation { await datex_pointer_storage.setItem(pointer.id, Compiler.encodeValue(pointer, inserted_ptrs, true, false, true)); return inserted_ptrs; } - async getPointerValue(pointerId: string, outer_serialized: boolean): Promise { + async getPointerValue(pointerId: string, outer_serialized: boolean, conditions: ExecConditions): Promise { const buffer = await datex_pointer_storage.getItem(pointerId); if (buffer == null) return NOT_EXISTING; - return Runtime.decodeValue(buffer, outer_serialized); + return Runtime.decodeValue(buffer, outer_serialized, conditions); } async removePointer(pointerId: string): Promise { await datex_pointer_storage.removeItem(pointerId); diff --git a/runtime/storage-locations/local-storage.ts b/runtime/storage-locations/local-storage.ts index 7014f7f9..48c911bb 100644 --- a/runtime/storage-locations/local-storage.ts +++ b/runtime/storage-locations/local-storage.ts @@ -6,10 +6,12 @@ import { NOT_EXISTING } from "../constants.ts"; import { base64ToArrayBuffer } from "../../utils/utils.ts"; import { arrayBufferToBase64 } from "../../datex_all.ts"; import { localStorage } from "./local-storage-compat.ts"; +import type { ExecConditions } from "../../utils/global_types.ts"; export class LocalStorageLocation extends SyncStorageLocation { name = "LOCAL_STORAGE" + supportsExecConditions = true isSupported() { return !!localStorage; @@ -25,10 +27,10 @@ export class LocalStorageLocation extends SyncStorageLocation { return true; } - getItem(key: string) { + getItem(key: string, conditions?: ExecConditions) { const base64 = localStorage.getItem(Storage.item_prefix+key); if (base64==null) return NOT_EXISTING; - else return Runtime.decodeValueBase64(base64); + else return Runtime.decodeValueBase64(base64, false, conditions); } *getItemKeys() { @@ -68,10 +70,10 @@ export class LocalStorageLocation extends SyncStorageLocation { localStorage.setItem(Storage.pointer_prefix+pointer.id, Compiler.encodeValueBase64(pointer, inserted_ptrs, true, false, true)); // serialized pointer return inserted_ptrs; } - async getPointerValue(pointerId: string, outer_serialized: boolean): Promise { + async getPointerValue(pointerId: string, outer_serialized: boolean, conditions?: ExecConditions): Promise { const base64 = localStorage.getItem(Storage.pointer_prefix+pointerId); if (base64 == null) return NOT_EXISTING; - return await Runtime.decodeValueBase64(base64, outer_serialized); + return await Runtime.decodeValueBase64(base64, outer_serialized, conditions); } removePointer(pointerId: string): void { localStorage.removeItem(Storage.pointer_prefix+pointerId); diff --git a/runtime/storage.ts b/runtime/storage.ts index fad97073..b960ce58 100644 --- a/runtime/storage.ts +++ b/runtime/storage.ts @@ -1,7 +1,7 @@ // deno-lint-ignore-file no-namespace import { Runtime } from "../runtime/runtime.ts"; -import type { PointerSource } from "../utils/global_types.ts"; +import type { ExecConditions, PointerSource } from "../utils/global_types.ts"; import { logger } from "../utils/global_values.ts"; import { client_type } from "../utils/constants.ts"; import { NOT_EXISTING } from "./constants.ts"; @@ -31,13 +31,14 @@ export const site_suffix = (()=>{ export interface StorageLocation { name: string isAsync: boolean + supportsExecConditions?: boolean isSupported(): boolean onAfterExit?(): void // called when deno process exits onAfterSnapshot?(isExit: boolean): void // called after a snapshot was saved to the storage (e.g. triggered by interval or exit event) setItem(key:string, value:unknown): Promise|boolean - getItem(key:string): Promise|unknown + getItem(key:string, conditions?:ExecConditions): Promise|unknown hasItem(key:string):Promise|boolean removeItem(key:string): Promise|void getItemValueDXB(key:string): Promise|ArrayBuffer|null @@ -45,7 +46,7 @@ export interface StorageLocation> | Generator setPointer(pointer:Pointer, partialUpdateKey: unknown|typeof NOT_EXISTING): Promise>|Set - getPointerValue(pointerId:string, outer_serialized:boolean):Promise|unknown + getPointerValue(pointerId:string, outer_serialized:boolean, conditions?:ExecConditions):Promise|unknown removePointer(pointerId:string):Promise|void hasPointer(pointerId:string):Promise|boolean getPointerIds(): Promise> | Generator @@ -63,7 +64,7 @@ export abstract class SyncStorageLocation implements StorageLocation|unknown + abstract getItem(key:string, conditions?:ExecConditions): Promise|unknown abstract hasItem(key:string): boolean abstract getItemKeys(): Generator @@ -72,7 +73,7 @@ export abstract class SyncStorageLocation implements StorageLocation, partialUpdateKey: unknown|typeof NOT_EXISTING): Set> - abstract getPointerValue(pointerId: string, outer_serialized:boolean): unknown + abstract getPointerValue(pointerId: string, outer_serialized:boolean, conditions?:ExecConditions): unknown abstract getPointerIds(): Generator abstract removePointer(pointerId: string): void @@ -91,7 +92,7 @@ export abstract class AsyncStorageLocation implements StorageLocation - abstract getItem(key:string): Promise + abstract getItem(key:string, conditions?:ExecConditions): Promise abstract hasItem(key:string): Promise abstract getItemKeys(): Promise> @@ -100,7 +101,7 @@ export abstract class AsyncStorageLocation implements StorageLocation abstract setPointer(pointer: Pointer, partialUpdateKey: unknown|typeof NOT_EXISTING): Promise>> - abstract getPointerValue(pointerId: string, outer_serialized:boolean): Promise + abstract getPointerValue(pointerId: string, outer_serialized:boolean, conditions?:ExecConditions): Promise abstract getPointerIds(): Promise> abstract removePointer(pointerId: string): Promise @@ -574,7 +575,7 @@ export class Storage { * @param outer_serialized if true, the outer value type is not evaluated and only the serialized value is returned * @returns value from pointer storage */ - public static async getPointer(pointer_id:string, pointerify?:boolean, bind?:any, location?:StorageLocation):Promise { + public static async getPointer(pointer_id:string, pointerify?:boolean, bind?:any, location?:StorageLocation, conditions?: ExecConditions):Promise { if (this.#dirty) { displayFatalError('storage-unrecoverable'); @@ -584,22 +585,22 @@ export class Storage { // try to find pointer at a storage location for (const loc of (location!=undefined ? [location] : this.getLocationPriorityOrder(pointer_id))) { if (loc==undefined) continue; - const val = await this.getPointerFromLocation(pointer_id, pointerify, bind, loc); + const val = await this.getPointerFromLocation(pointer_id, pointerify, bind, loc, conditions); if (val !== NOT_EXISTING) return val; } return NOT_EXISTING } - private static async getPointerFromLocation(pointer_id:string, pointerify: boolean|undefined, bind:any|undefined, location:StorageLocation) { - const val = await this.getPointerAsync(location, pointer_id, pointerify, bind); + private static async getPointerFromLocation(pointer_id:string, pointerify: boolean|undefined, bind:any|undefined, location:StorageLocation, conditions?: ExecConditions) { + const val = await this.getPointerAsync(location, pointer_id, pointerify, bind, conditions); if (val == NOT_EXISTING) return NOT_EXISTING; await this.initPointerFromTrustedLocation(pointer_id, location) return val; } - private static async getPointerAsync(location:StorageLocation, pointer_id:string, pointerify?:boolean, bind?:any) { + private static async getPointerAsync(location:StorageLocation, pointer_id:string, pointerify?:boolean, bind?:any, conditions?: ExecConditions) { let pointer:Pointer|undefined; if (pointerify && (pointer = Pointer.get(pointer_id))?.value_initialized) { @@ -608,7 +609,7 @@ export class Storage { // load from storage - let val = await location.getPointerValue(pointer_id, !!bind); + let val = await location.getPointerValue(pointer_id, !!bind, conditions); if (val == NOT_EXISTING) return NOT_EXISTING; @@ -768,7 +769,7 @@ export class Storage { await Promise.all(promises); } - public static async getItem(key:string, location?:StorageLocation|undefined/* = this.#primary_location*/):Promise { + public static async getItem(key:string, location?:StorageLocation|undefined/* = this.#primary_location*/, conditions?: ExecConditions):Promise { if (this.#dirty) { displayFatalError('storage-unrecoverable'); @@ -781,7 +782,7 @@ export class Storage { // try to find item at a storage location for (const loc of (location!=undefined ? [location] : this.getLocationPriorityOrder(key))) { if (loc==undefined) continue; - const val = await this.getItemFromLocation(key, loc); + const val = await this.getItemFromLocation(key, loc, conditions); if (val!==NOT_EXISTING) return val; } @@ -789,9 +790,11 @@ export class Storage { } - public static async getItemFromLocation(key:string, location:StorageLocation/* = this.#primary_location*/):Promise { + public static async getItemFromLocation(key:string, location:StorageLocation/* = this.#primary_location*/, conditions?: ExecConditions):Promise { - const val = await location.getItem(key); + if (!location.supportsExecConditions && conditions) throw new Error(`Storage Location ${location.name} does not support exec conditions`); + + const val = await location.getItem(key, conditions); if (val == NOT_EXISTING) return NOT_EXISTING; Storage.cache.set(key, val); @@ -863,12 +866,12 @@ export class Storage { } // load saved state - public static async loadOrCreate(id:string|number, create?:()=>Promise|T):Promise> { + public static async loadOrCreate(id:string|number, create?:()=>Promise|T, conditions?: ExecConditions, override = false):Promise> { const state_name = this.state_prefix+id.toString(); // already has a saved state - if (await this.hasItem(state_name)) { - return await this.getItem(state_name) + if (!override && await this.hasItem(state_name)) { + return await this.getItem(state_name, undefined, conditions) } // create state else if (create){ @@ -923,8 +926,8 @@ globalThis.reset = Storage.clearAndReload // proxy for Storage class DatexStoragePointerSource implements PointerSource { - getPointer(pointer_id:string, pointerify?:boolean) { - return Storage.getPointer(pointer_id, pointerify) + getPointer(pointer_id:string, pointerify?:boolean, localOnly?: boolean) { + return Storage.getPointer(pointer_id, pointerify, undefined, undefined, localOnly ? {onlyLocalPointers: true} : undefined) } syncPointer(pointer:Pointer) { return Storage.syncPointer(pointer) diff --git a/types/addressing.ts b/types/addressing.ts index e47eed87..ef580a76 100644 --- a/types/addressing.ts +++ b/types/addressing.ts @@ -11,6 +11,7 @@ import { logger } from "../utils/global_values.ts"; import { Datex } from "../mod.ts"; import { ProtocolDataType } from "../compiler/protocol_types.ts"; import { ESCAPE_SEQUENCES } from "../utils/logger.ts"; +import { deleteCookie, getCookie } from "../utils/cookies.ts"; type target_prefix_person = "@"; type target_prefix_id = "@@"; @@ -470,6 +471,25 @@ export class Endpoint extends Target { return val; } + /** + * Get endpoint id from "datex-endpoint" cookies. + * Deletes the cookie if not a valid endpoint and returns null + * @returns + */ + public static getFromCookie() { + const cookieEndpoint = getCookie("datex-endpoint"); + if (cookieEndpoint) { + try { + const endpoint = Target.get(cookieEndpoint) as Endpoint; + logger.debug("loaded endpoint from 'datex-endpoint' cookie: " + endpoint) + return endpoint + } + catch { + deleteCookie("datex-endpoint") + } + } + return null; + } public static createNewID():filter_target_name_id{ const id = new DataView(new ArrayBuffer(16)); diff --git a/utils/cookies.ts b/utils/cookies.ts new file mode 100644 index 00000000..47f3ebf6 --- /dev/null +++ b/utils/cookies.ts @@ -0,0 +1,38 @@ +import { client_type } from "./constants.ts"; + + +export function deleteCookie(name: string) { + if (client_type !== "browser") { + throw new Error("cannot delete cookies for non-browser environment"); + } + document.cookie = name +'=; Path=/; Domain=' + location.host + '; Expires=Thu, 01 Jan 1970 00:00:01 GMT;'; +} + + +export function setCookie(name: string, value: string, expDays?: number) { + if (client_type !== "browser") { + throw new Error("cannot set cookies for non-browser environment"); + } + + value = encodeURIComponent(value) + let expiryDate = new Date("Fri, 31 Dec 9999 21:10:10 GMT"); + if (expDays) { + expiryDate = new Date(); + expiryDate.setTime(expiryDate.getTime() + (expDays * 24 * 60 * 60 * 1000)); + } + const expires = "expires=" + expiryDate.toUTCString() + ";"; + document.cookie = name + "=" + value + "; " + expires + " path=/;" +} + +export function getCookie(name: string) { + if (client_type !== "browser") return; + + const cname = name + "="; + const cookies = decodeURIComponent(document.cookie); + const cookieArray = cookies.split('; '); + let res: string|undefined; + cookieArray.forEach(val => { + if (val.indexOf(cname) === 0) res = val.substring(cname.length); + }) + return res; +} \ No newline at end of file diff --git a/utils/debug-cookie.ts b/utils/debug-cookie.ts index e8336573..302f0611 100644 --- a/utils/debug-cookie.ts +++ b/utils/debug-cookie.ts @@ -1,4 +1,4 @@ -import { client_type } from "../utils/constants.ts"; +import { getCookie, setCookie } from "./cookies.ts"; export function hasDebugCookie() { return getCookie("datex-debug") == "true"; @@ -12,33 +12,5 @@ export function debugMode(enable = true) { } -function setCookie(name: string, value: string, expDays?: number) { - if (client_type !== "browser") { - throw new Error("cannot set cookies for non-browser environment"); - } - - value = encodeURIComponent(value) - let expiryDate = new Date("Fri, 31 Dec 9999 21:10:10 GMT"); - if (expDays) { - expiryDate = new Date(); - expiryDate.setTime(expiryDate.getTime() + (expDays * 24 * 60 * 60 * 1000)); - } - const expires = "expires=" + expiryDate.toUTCString() + ";"; - document.cookie = name + "=" + value + "; " + expires + " path=/; SameSite=None; Secure;"; -} - -function getCookie(name: string) { - if (client_type !== "browser") return; - - const cname = name + "="; - const cookies = decodeURIComponent(document.cookie); - const cookieArray = cookies.split('; '); - let res: string|undefined; - cookieArray.forEach(val => { - if (val.indexOf(cname) === 0) res = val.substring(cname.length); - }) - return res; -} - // @ts-ignore globalThis.debugMode = debugMode; \ No newline at end of file diff --git a/utils/global_types.ts b/utils/global_types.ts index 1c8d307e..8c547547 100644 --- a/utils/global_types.ts +++ b/utils/global_types.ts @@ -14,10 +14,15 @@ export type Return = Promise|T|void; // export type Return = Promise>|T|void|DatexResponse; export interface PointerSource { - getPointer(pointer_id:string, pointerify?:boolean): Promise|any|typeof NOT_EXISTING + getPointer(pointer_id:string, pointerify?:boolean, localOnly?: boolean): Promise|any|typeof NOT_EXISTING syncPointer?(pointer:Pointer):Promise|void } +export type ExecConditions = { + onlyLocalPointers?: boolean // if true, throws an error if local pointers are accessed +} + + export type datex_sub_scope = { result?: any, // 'global' sub scope variable (-> return value), corresponds to __scope_global internal variable @@ -176,6 +181,8 @@ export type datex_scope = { outer_serialized?: boolean, // if true, the outer value is not casted to a type, just the serialized value is returned + exec_conditions?: ExecConditions + meta: datex_meta, remote: {insert?:object, sign?:boolean, encrypt?:boolean, eos?:boolean, type?:ProtocolDataType, timeout?:number|bigint}, // outgoing remote configuration diff --git a/windows/window-com-interface.ts b/windows/window-com-interface.ts index 9c2e9319..eaacae3e 100644 --- a/windows/window-com-interface.ts +++ b/windows/window-com-interface.ts @@ -31,7 +31,6 @@ export class WindowCommunicationInterface extends CommonInterface<[Window, strin this.parentDocument = this.initial_arguments[0]; this.otherOrigin = this.initial_arguments[1] ?? new URL(document.referrer).origin; this.logger.info("initializing as child window, parent window origin: " + this.otherOrigin) - } else { this.logger.error("no Window provided for WindowCommunicationInterface");