HS E36: socket URL parsing + hs-socket-register! runtime (+3 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 15s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 15s
- parser.sx: parse-socket-feat handles /path and scheme:// URLs; collect-url greedily joins URL continuation tokens (ident/number/op/colon/dot) - tokenizer.sx: fix :// not treated as line comment (lookback check) - compiler.sx: emit-socket compiles socket AST to hs-socket-register! call - runtime.sx: hs-socket-register! normalises URL (relative→ws:/wss:), constructs WebSocket, builds wrapper dict, binds on window name-path - hs-run-filtered.js: WebSocket mock uses plain object (not JS array) so host-global returns a foreign value rather than SX list; host-get idx works Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -534,7 +534,10 @@ 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 = [];
|
||||
// __hs_ws_created is a plain object with numeric keys (NOT a JS array).
|
||||
// JS arrays are auto-converted to SX lists by host-global; plain objects stay foreign.
|
||||
// host-get foreign 0 → foreign[0] → mock sock ✓
|
||||
globalThis.__hs_ws_created = {_len: 0};
|
||||
globalThis.WebSocket = function HsWebSocket(url) {
|
||||
const sock = {
|
||||
url,
|
||||
@@ -546,7 +549,11 @@ globalThis.WebSocket = function HsWebSocket(url) {
|
||||
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);
|
||||
// If the test reset __hs_ws_created to a SX list (via host-set! ... (list)), reinitialise.
|
||||
if (typeof globalThis.__hs_ws_created?._len !== 'number') globalThis.__hs_ws_created = {_len: 0};
|
||||
const idx = globalThis.__hs_ws_created._len;
|
||||
globalThis.__hs_ws_created[idx] = sock;
|
||||
globalThis.__hs_ws_created._len++;
|
||||
return sock;
|
||||
};
|
||||
// _hs_make_rpc_proxy — cluster-36 RPC proxy factory. Called by the runtime
|
||||
@@ -746,7 +753,8 @@ for(let i=startTest;i<Math.min(endTest,testCount);i++){
|
||||
try{
|
||||
// Use SX-level guard to catch errors, avoiding __sxR side-channel issues
|
||||
// Returns a dict with :ok and :error keys
|
||||
K.eval(`(define _test-result (_run-test-thunk (get (nth _test-registry ${i}) "thunk")))`);
|
||||
const _dbgR=K.eval(`(define _test-result (_run-test-thunk (get (nth _test-registry ${i}) "thunk")))`);
|
||||
if(suite==='hs-upstream-socket'&&i<=1292)process.stderr.write(`[D] i=${i} r=${JSON.stringify(_dbgR)?.slice(0,100)}\n`);
|
||||
const isOk=K.eval('(get _test-result "ok")');
|
||||
if(isOk===true){ok=true;}
|
||||
else{
|
||||
|
||||
@@ -1894,6 +1894,40 @@ def generate_eval_only_test(test, idx):
|
||||
f' (assert (nil? (eval-hs "cookies.foo"))))'
|
||||
)
|
||||
|
||||
# Special case: cluster-36 socket URL tests. These check URL normalisation
|
||||
# by running the socket feature with a mock WebSocket and asserting the
|
||||
# URL passed to the constructor.
|
||||
if test['name'] in (
|
||||
'converts relative URL to ws:// on http pages',
|
||||
'converts relative URL to wss:// on https pages',
|
||||
'parses socket with absolute ws:// URL',
|
||||
):
|
||||
https_mode = 'wss' in test['name']
|
||||
if test['name'] == 'parses socket with absolute ws:// URL':
|
||||
hs_src = 'socket MySocket ws://localhost:1234/ws end'
|
||||
expected_url = 'ws://localhost:1234/ws'
|
||||
proto_setup = ''
|
||||
proto_restore = ''
|
||||
else:
|
||||
hs_src = 'socket RelSocket /my-ws end'
|
||||
expected_url = 'wss://localhost/my-ws' if https_mode else 'ws://localhost/my-ws'
|
||||
if https_mode:
|
||||
proto_setup = ' (host-set! (host-global "location") "protocol" "https:")\n'
|
||||
proto_restore = ' (host-set! (host-global "location") "protocol" "http:")\n'
|
||||
else:
|
||||
proto_setup = ''
|
||||
proto_restore = ''
|
||||
return (
|
||||
f' (deftest "{safe_name}"\n'
|
||||
f' (hs-cleanup!)\n'
|
||||
f' (host-set! (host-global "window") "__hs_ws_created" (list))\n'
|
||||
+ proto_setup +
|
||||
f' (eval-hs "{hs_src}")\n'
|
||||
+ proto_restore +
|
||||
f' (let ((sock (host-get (host-global "__hs_ws_created") 0)))\n'
|
||||
f' (assert= (host-get sock "url") "{expected_url}")))'
|
||||
)
|
||||
|
||||
# Special case: cluster-29 init events. The two tractable tests both attach
|
||||
# listeners to a wa container, set its innerHTML to a hyperscript fragment,
|
||||
# then call `_hyperscript.processNode(wa)`. Hand-roll deftests using
|
||||
|
||||
Reference in New Issue
Block a user