HS-prep: WebSocket + RPC proxy mock
This commit is contained in:
@@ -528,9 +528,62 @@ class HsIntersectionObserver {
|
||||
}
|
||||
globalThis.IntersectionObserver = HsIntersectionObserver;
|
||||
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.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;
|
||||
globalThis.console = { log: () => {}, error: () => {}, warn: () => {}, info: () => {}, debug: () => {} }; // suppress ALL console noise
|
||||
const _log = _origLog; // keep reference for our own output
|
||||
|
||||
Reference in New Issue
Block a user