UNPKG

@webqit/quantum-js

Version:

Runtime extension to JavaScript that let's us do Imperative Reactive Programming (IRP) in the very language.

83 lines (72 loc) 3.62 kB
/** * @imports */ import Observer from '@webqit/observer'; import { _$functionArgs } from './util.js'; import { $eval } from './runtime/index.js'; import AbstractQuantumScript from './AbstractQuantumScript.js'; import State from './runtime/State.js'; /** -------------- APIs */ export { Observer, State } export let QuantumFunction; export function AsyncQuantumFunction( ...args ) { const { source, params } = _$functionArgs( args ); const compiledFunction = $eval( 'async-function', parseCompileCallback, source, params ); if ( !( compiledFunction instanceof Promise ) ) return compiledFunction; // Introduce a wrapper function that awaits main function const wrapperFunction = async function( ...args ) { return ( await compiledFunction ).call( this, ...args ); } Object.defineProperty( wrapperFunction, 'toString', { value: async function( ...args ) { return ( await compiledFunction ).toString( ...args ) } } ) return wrapperFunction; } export const QuantumAsyncFunction = AsyncQuantumFunction; // For backwards compat export let QuantumScript; export class AsyncQuantumScript extends AbstractQuantumScript { static sourceType = 'async-script'; static parseCompileCallback = parseCompileCallback; } export const QuantumAsyncScript = AsyncQuantumScript; // For backwards compat export class QuantumModule extends AbstractQuantumScript { static sourceType = 'module'; static parseCompileCallback = parseCompileCallback; } /** -------------- parse-compile */ function parseCompileCallback( ...args ) { const params = typeof args[ args.length - 1 ] === 'object' ? args.pop() : {}; const source = args.pop() || ''; // $qCompiler has been loaded sync? if ( globalThis.webqit?.$qCompiler ) { const { parse, compile } = globalThis.webqit.$qCompiler; const ast = parse( source, params.parserParams ); return compile( ast, params.compilerParams ); } // Load and run $qCompiler async - in the background? globalThis.webqit = globalThis.webqit || {}; if ( !globalThis.webqit.$qCompilerWorker ) { const customUrl = document.querySelector( 'meta[name="$q-compiler-url"]' ); const compilerUrls = ( customUrl?.content.split( ',' ) || [] ).concat( 'https://unpkg.com/@webqit/quantum-js/dist/compiler.js' ); const workerScriptText = ` const compilerUrls = [ '${ compilerUrls.join( `','` ) }' ]; ( function importScript() { try { importScripts( compilerUrls.shift().trim() ) } catch( e ) { if ( compilerUrls.length ) { importScript(); } } } )(); const { parse, compile } = globalThis.webqit.$qCompiler; globalThis.onmessage = e => { const { source, params } = e.data; const ast = parse( source, params.parserParams ); const { toString, ...compilation } = compile( ast, params.compilerParams ); e.ports[ 0 ]?.postMessage( compilation ); };`; globalThis.webqit.$qCompilerWorker = new Worker( `data:text/javascript;base64,${ btoa( workerScriptText ) }` ); } return new Promise( res => { let messageChannel = new MessageChannel; webqit.$qCompilerWorker.postMessage( { source, params }, [ messageChannel.port2 ] ); messageChannel.port1.onmessage = e => { const { ...compilation } = e.data; Object.defineProperty( compilation, 'toString', { value: base64 => base64 === 'base64' ? compilation.compiledSourceBase64 : compilation.compiledSource } ); res( compilation ); } } ); }