HS-prep: WebSocket + RPC proxy mock
This commit is contained in:
@@ -528,9 +528,62 @@ class HsIntersectionObserver {
|
|||||||
}
|
}
|
||||||
globalThis.IntersectionObserver = HsIntersectionObserver;
|
globalThis.IntersectionObserver = HsIntersectionObserver;
|
||||||
globalThis.IntersectionObserverEntry = class {};
|
globalThis.IntersectionObserverEntry = class {};
|
||||||
globalThis.navigator={userAgent:'node'}; globalThis.location={href:'http://localhost/',pathname:'/',search:'',hash:''};
|
globalThis.navigator={userAgent:'node'}; globalThis.location={href:'http://localhost/',pathname:'/',search:'',hash:'',protocol:'http:',host:'localhost',hostname:'localhost',port:''};
|
||||||
globalThis.history={pushState(){},replaceState(){},back(){},forward(){}};
|
globalThis.history={pushState(){},replaceState(){},back(){},forward(){}};
|
||||||
globalThis.getSelection=()=>({toString:()=>(globalThis.__test_selection||'')});
|
globalThis.getSelection=()=>({toString:()=>(globalThis.__test_selection||'')});
|
||||||
|
// HsWebSocket — cluster-36 WebSocket mock. Records every constructed socket
|
||||||
|
// in globalThis.__hs_ws_created so tests can assert on URLs and sent frames.
|
||||||
|
// Tests may override globalThis.WebSocket before activating hyperscript.
|
||||||
|
globalThis.__hs_ws_created = [];
|
||||||
|
globalThis.WebSocket = function HsWebSocket(url) {
|
||||||
|
const sock = {
|
||||||
|
url,
|
||||||
|
onmessage: null,
|
||||||
|
_listeners: {},
|
||||||
|
_sent: [],
|
||||||
|
send(msg) { sock._sent.push(msg); },
|
||||||
|
addEventListener(t, h) { (sock._listeners[t] = sock._listeners[t] || []).push(h); },
|
||||||
|
removeEventListener(t, h) { const a = sock._listeners[t]; if (a) { const i = a.indexOf(h); if (i >= 0) a.splice(i, 1); } },
|
||||||
|
close() { (sock._listeners['close'] || []).forEach(h => { try { h({}); } catch(_) {} }); }
|
||||||
|
};
|
||||||
|
globalThis.__hs_ws_created.push(sock);
|
||||||
|
return sock;
|
||||||
|
};
|
||||||
|
// _hs_make_rpc_proxy — cluster-36 RPC proxy factory. Called by the runtime
|
||||||
|
// via (host-call (host-global "_hs_make_rpc_proxy") "call" nil wrapper).
|
||||||
|
// wrapper is the SX dict: {raw, url, timeout, pending, ...}
|
||||||
|
// Returns an ES6 Proxy whose property accesses dispatch RPC calls.
|
||||||
|
function _hsRpcCall(wrapper, fnName, args, timeoutMs) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const iid = String(Math.random()).slice(2) + String(Date.now());
|
||||||
|
if (!wrapper.pending) wrapper.pending = {};
|
||||||
|
wrapper.pending[iid] = { resolve, reject };
|
||||||
|
const raw = wrapper.raw;
|
||||||
|
const msg = JSON.stringify({ iid, function: fnName, args });
|
||||||
|
raw.send(msg);
|
||||||
|
const ms = timeoutMs === undefined ? (typeof wrapper.timeout === 'number' ? wrapper.timeout : 0) : timeoutMs;
|
||||||
|
if (ms !== Infinity && typeof ms === 'number') {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (wrapper.pending && wrapper.pending[iid]) {
|
||||||
|
delete wrapper.pending[iid];
|
||||||
|
reject('Timed out');
|
||||||
|
}
|
||||||
|
}, ms);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function _hs_make_rpc_proxy(wrapper, overrides) {
|
||||||
|
overrides = overrides || {};
|
||||||
|
return new Proxy({}, {
|
||||||
|
get(_, name) {
|
||||||
|
if (['then', 'catch', 'length', 'toJSON'].includes(name)) return null;
|
||||||
|
if (name === 'noTimeout') return _hs_make_rpc_proxy(wrapper, Object.assign({}, overrides, { timeout: Infinity }));
|
||||||
|
if (name === 'timeout') return function(n) { return _hs_make_rpc_proxy(wrapper, Object.assign({}, overrides, { timeout: n })); };
|
||||||
|
return function(...args) { return _hsRpcCall(wrapper, name, args, overrides.timeout); };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
globalThis._hs_make_rpc_proxy = { call: _hs_make_rpc_proxy };
|
||||||
const _origLog = console.log;
|
const _origLog = console.log;
|
||||||
globalThis.console = { log: () => {}, error: () => {}, warn: () => {}, info: () => {}, debug: () => {} }; // suppress ALL console noise
|
globalThis.console = { log: () => {}, error: () => {}, warn: () => {}, info: () => {}, debug: () => {} }; // suppress ALL console noise
|
||||||
const _log = _origLog; // keep reference for our own output
|
const _log = _origLog; // keep reference for our own output
|
||||||
|
|||||||
Reference in New Issue
Block a user