APL
Dyalog v20.0
Uiua
0.x
Kap
2026-06-20
');
iframeDoc.close();
return new Promise((resolve, reject) => {
// Setup Module config in the iframe BEFORE loading the script
// (same pattern as J loader)
iframe.contentWindow.Module = {
locateFile: function(path, prefix) {
return wasmBaseUrl + path;
},
onRuntimeInitialized: function() {
try {
console.log('[BQN] WASM runtime initialized');
const Module = iframe.contentWindow.Module;
// Wrap C functions
cbqn_runLine = Module.cwrap('cbqn_runLine', null, ['string', 'number']);
bqnModule = Module;
bqnReady = true;
bqnLoading = false;
console.log('[BQN] CBQN WASM loaded successfully!');
resolve(true);
} catch (error) {
console.error('[BQN] Error wrapping functions:', error);
bqnLoadError = error;
bqnLoading = false;
reject(error);
}
},
onAbort: function(what) {
console.error('[BQN] WASM initialization aborted:', what);
bqnLoadError = new Error(what || 'CBQN WASM initialization aborted');
bqnLoading = false;
reject(bqnLoadError);
},
// Capture stdout - cbqn_runLine sends formatted results here
print: function(text) {
stdoutBuf += text + '\n';
},
// Capture stderr - cbqn_runLine sends error messages here
printErr: function(text) {
stderrBuf += text + '\n';
}
};
// Load the script with absolute URL
const script = iframeDoc.createElement('script');
script.src = wasmBaseUrl + 'BQN.js';
script.onerror = function(e) {
console.error('[BQN] Failed to load BQN.js:', e);
bqnLoadError = new Error('Failed to load CBQN WASM script');
bqnLoading = false;
reject(bqnLoadError);
};
iframeDoc.head.appendChild(script);
});
} catch (error) {
console.error('[BQN] WASM loading failed:', error);
bqnLoadError = error;
bqnLoading = false;
return false;
}
})();
return bqnLoadPromise;
}
async function evalBQN(code) {
if (!bqnReady) {
if (!bqnLoading && !bqnLoadError) {
loadBQN().catch(() => {});
}
if (bqnLoadError) {
return {
success: false,
output: `CBQN failed to load: ${bqnLoadError.message}\n\nCheck browser console (F12) for details.`
};
}
// Wait for loading to complete
const startWait = Date.now();
const maxWait = 15000; // 15 second timeout
while (!bqnReady && !bqnLoadError && (Date.now() - startWait) < maxWait) {
await new Promise(r => setTimeout(r, 100));
}
if (!bqnReady) {
if (bqnLoadError) {
return {
success: false,
output: `CBQN failed to load: ${bqnLoadError.message}`
};
}
return {
success: false,
output: 'CBQN WASM loading...'
};
}
}
// Clear output buffers
stdoutBuf = '';
stderrBuf = '';
try {
// Use cbqn_runLine which has built-in error catching via CATCH/setjmp.
// It prints formatted results to stdout and errors to stderr.
// cbqn_runLine expects the code string and its byte length.
const encoder = new TextEncoder();
const encoded = encoder.encode(code);
cbqn_runLine(code, encoded.length);
const stdout = stdoutBuf.replace(/\n$/, '');
const stderr = stderrBuf.replace(/\n$/, '');
if (stderr) {
// Error output present - extract the error message
// CBQN stderr format: "Error:
