HS: wip — parser every-fix, integration boot, test tooling expansion
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -169,6 +169,8 @@ class El {
|
||||
}
|
||||
return `<${tag}${attrs}>${inner}</${tag}>`;
|
||||
}
|
||||
get childElementCount() { return this.children.length; }
|
||||
toString() { return this.nodeType === 11 ? '[object DocumentFragment]' : '[object Object]'; }
|
||||
get firstElementChild() { return this.children[0]||null; }
|
||||
get lastElementChild() { return this.children[this.children.length-1]||null; }
|
||||
get nextElementSibling() { if(!this.parentElement)return null; const i=this.parentElement.children.indexOf(this); return this.parentElement.children[i+1]||null; }
|
||||
@@ -679,6 +681,10 @@ K.registerNative('hs-is-map?',a=>a[0] instanceof Map);
|
||||
// Upstream test fixtures: synchronous stubs matching OCaml run_tests.ml registrations
|
||||
globalThis.promiseAString = () => 'foo';
|
||||
globalThis.promiseAnInt = () => 42;
|
||||
globalThis.promiseAnIntIn = (n) => Promise.resolve(42);
|
||||
globalThis.promiseValueBackIn = (v, n) => Promise.resolve(v);
|
||||
globalThis.throwBar = function() { throw "bar"; };
|
||||
globalThis.identity = x => x;
|
||||
|
||||
// ── JS block execution support ─────────────────────────────────
|
||||
// Track promise states for synchronous introspection in hs-js-exec
|
||||
@@ -733,6 +739,57 @@ K.registerNative('host-hs-normalize-exc', a => {
|
||||
return val;
|
||||
});
|
||||
|
||||
// Like host-call-fn but propagates native JS exceptions via sentinel rather than swallowing them.
|
||||
// Also synchronously unwraps Promise.resolve() results so async tests work in sync env.
|
||||
K.registerNative('host-call-fn-raising', a => {
|
||||
const [fn, argList] = a;
|
||||
if (typeof fn !== 'function' && !(fn && fn.__sx_handle !== undefined)) return null;
|
||||
const callArgs = (argList && argList._type === 'list' && argList.items)
|
||||
? Array.from(argList.items)
|
||||
: (Array.isArray(argList) ? argList : []);
|
||||
function sxToJs(v) {
|
||||
if (v && v._type === 'list' && v.items) return Array.from(v.items).map(sxToJs);
|
||||
return v;
|
||||
}
|
||||
if (fn && fn.__sx_handle !== undefined) {
|
||||
try {
|
||||
const r = K.callFn(fn, callArgs);
|
||||
if (globalThis._driveAsync) globalThis._driveAsync(r);
|
||||
return r !== undefined ? r : null;
|
||||
} catch(e) {
|
||||
const msg = (e && e.message) || '';
|
||||
if (String(msg).includes('TIMEOUT')) throw e;
|
||||
globalThis.__hs_js_throw = String(e != null ? e : '');
|
||||
return '__hs_js_throw__';
|
||||
}
|
||||
}
|
||||
try {
|
||||
const v = fn.apply(null, callArgs.map(sxToJs));
|
||||
if (v === undefined) return null;
|
||||
if (v instanceof Promise) {
|
||||
const s = _promiseStates.get(v);
|
||||
if (s) {
|
||||
if (!s.ok) {
|
||||
globalThis.__hs_async_error = (s.value instanceof Error) ? {message: s.value.message} : s.value;
|
||||
return '__hs_async_error__';
|
||||
}
|
||||
return (s.value !== undefined && s.value !== null) ? s.value : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return v;
|
||||
} catch(e) {
|
||||
const msg = (e instanceof Error) ? e.message : String(e != null ? e : '');
|
||||
globalThis.__hs_js_throw = msg;
|
||||
return '__hs_js_throw__';
|
||||
}
|
||||
});
|
||||
K.registerNative('host-take-js-throw', a => {
|
||||
const v = globalThis.__hs_js_throw;
|
||||
globalThis.__hs_js_throw = null;
|
||||
return (v != null) ? String(v) : '';
|
||||
});
|
||||
|
||||
let _testDeadline = 0;
|
||||
// Mock fetch routes
|
||||
const _fetchRoutes = {
|
||||
@@ -761,6 +818,8 @@ const _fetchScripts = {
|
||||
{ "/test": { status: 200, body: "yay", contentType: "text/html" } },
|
||||
"can do a simple fetch w/ a custom conversion":
|
||||
{ "/test": { status: 200, body: "1.2" } },
|
||||
"can do a simple fetch w/ html":
|
||||
{ "/test": { status: 200, body: "<p>hello</p>", html: "<p>hello</p>", contentType: "text/html" } },
|
||||
};
|
||||
function _mockFetch(url) {
|
||||
const scriptRoutes = _fetchScripts[globalThis.__currentHsTestName];
|
||||
@@ -780,7 +839,7 @@ globalThis._driveAsync=function driveAsync(r,d){d=d||0;if(_testDeadline && Date.
|
||||
}
|
||||
else if(opName==='io-parse-text'){const resp=items&&items[1];doResume(resp&&resp._body?resp._body:typeof resp==='string'?resp:'');}
|
||||
else if(opName==='io-parse-json'){const resp=items&&items[1];try{doResume(JSON.parse(typeof resp==='string'?resp:resp&&resp._json?resp._json:'{}'));}catch(e){doResume(null);}}
|
||||
else if(opName==='io-parse-html'){const frag=new El('fragment');frag.nodeType=11;doResume(frag);}
|
||||
else if(opName==='io-parse-html'){const resp=items&&items[1];const htmlStr=resp&&(resp._html||resp._body)?String(resp._html||resp._body):'';const frag=new El('fragment');frag.nodeType=11;if(htmlStr)frag._setInnerHTML(htmlStr);doResume(frag);}
|
||||
else if(opName==='io-settle')doResume(null);
|
||||
else if(opName==='io-wait-event'){
|
||||
const target=items&&items[1];
|
||||
|
||||
Reference in New Issue
Block a user