UNPKG

@nent/core

Version:

Functional elements to add routing, data-binding, dynamic HTML, declarative actions, audio, video, and so much more. Supercharge static HTML files into web apps without script or builds.

225 lines (210 loc) 6.78 kB
/*! * NENT 2022 */ import { c as consoleError } from './index-916ca544.js'; import { s as state } from './factory-acbf0d3d.js'; import { resolveTokens, hasToken } from './tokens-78f8cdbe.js'; import { r as removeLineFeeds, t as toBoolean } from './strings-47d55561.js'; import { r as requireValue } from './values-ddfac998.js'; import { b as warnIf } from './logging-5a93c8af.js'; const isInstanceOf = (value, className) => { const C = globalThis[className]; return C != null && value instanceof C; }; const getTransferables = (value) => { if (value != null) { if ( isInstanceOf(value, "ArrayBuffer") || isInstanceOf(value, "MessagePort") || isInstanceOf(value, "ImageBitmap") || isInstanceOf(value, "OffscreenCanvas") ) { return [value]; } if (typeof value === "object") { if (value.constructor === Object) { value = Object.values(value); } if (Array.isArray(value)) { return value.flatMap(getTransferables); } return getTransferables(value.buffer); } } return []; }; let pendingIds = 0; let callbackIds = 0; const pending = new Map(); const callbacks = new Map(); const createWorker = (workerPath, workerName, workerMsgId) => { const worker = new Worker(workerPath, {name:workerName}); worker.addEventListener('message', ({data}) => { if (data) { const workerMsg = data[0]; const id = data[1]; const value = data[2]; if (workerMsg === workerMsgId) { const err = data[3]; const [resolve, reject, callbackIds] = pending.get(id); pending.delete(id); if (err) { const errObj = (err.isError) ? Object.assign(new Error(err.value.message), err.value) : err.value; consoleError(errObj); reject(errObj); } else { if (callbackIds) { callbackIds.forEach(id => callbacks.delete(id)); } resolve(value); } } else if (workerMsg === workerMsgId + '.cb') { try { callbacks.get(id)(...value); } catch (e) { consoleError(e); } } } }); return worker; }; const createWorkerProxy = (worker, workerMsgId, exportedMethod) => ( (...args) => new Promise((resolve, reject) => { let pendingId = pendingIds++; let i = 0; let argLen = args.length; let mainData = [resolve, reject]; pending.set(pendingId, mainData); for (; i < argLen; i++) { if (typeof args[i] === 'function') { const callbackId = callbackIds++; callbacks.set(callbackId, args[i]); args[i] = [workerMsgId + '.cb', callbackId]; (mainData[2] = mainData[2] || []).push(callbackId); } } const postMessage = (w) => ( w.postMessage( [workerMsgId, pendingId, exportedMethod, args], getTransferables(args) ) ); if (worker.then) { worker.then(postMessage); } else { postMessage(worker); } }) ); const workerPromise = import('./evaluate.worker-cf53b6cf.js').then(m => m.worker); const evalExpression = /*@__PURE__*/createWorkerProxy(workerPromise, 'stencil.evaluate.worker', 'evalExpression'); const operatorRegex = /(in |for |[><+\-=])/gi; const jsonRegEx = /(\{.*?\})/g; const alphabet = 'abcdefghijklmnopqrstuvwxyz'; /** * It returns true if the given string contains an operator * @param {string} value - The value of the attribute. * @returns A boolean value. */ function hasExpression(value) { return value.match(operatorRegex); } /** * It takes a string, finds all the JSON in it, replaces the JSON with a variable, and returns the * string with the JSON replaced and an object with the JSON and the variable * @param {string} expression - The expression to convert * @returns An object with two properties: data and expression. */ function convertFromJson(expression) { const data = {}; let newExpression = removeLineFeeds(expression).split(`'`).join(`"`); let index = 0; let match; let resultingExpression = newExpression.slice(); while ((match = jsonRegEx.exec(newExpression))) { const json = match[1]; const value = JSON.parse(json); let variable = alphabet[index]; data[variable] = value; index++; resultingExpression = resultingExpression .split(json) .join(variable); } return { data, expression: resultingExpression, }; } /** * It takes an expression and a context, and returns the result of evaluating the expression * @param {string} expression - The expression to evaluate. * @param {ExpressionContext} context - ExpressionContext = {} * @returns A promise that resolves to a number, boolean, or string. */ async function evaluate(expression, context = {}) { requireValue(expression, 'expression'); if (!hasExpression(expression)) return expression; try { context.null = null; const resolved = convertFromJson(expression); Object.assign(context, resolved.data); return await evalExpression(resolved.expression, context); } catch (error) { warnIf(state.debug, `An exception was raised evaluating expression '${expression}': ${error}`); return false; } } /** * This function first resolves any data-tokens, then passes the response to the * {evaluate} function. * * @export evaluateExpression * @param {string} expression * @param {*} [context={}] * @return {*} {Promise<any>} */ async function evaluateExpression(expression, context = {}) { requireValue(expression, 'expression'); const detokenizedExpression = await resolveTokens(expression, true); return evaluate(detokenizedExpression, context); } /** * This function first resolves any data-tokens, then passes the response to the * {evaluate} function, but uses the value to determine a true/false. * * @export * @param {string} expression * @param {ExpressionContext} [context={}] * @return {*} {Promise<boolean>} */ async function evaluatePredicate(expression, context = {}) { requireValue(expression, 'expression'); let workingExpression = expression.slice(); if (hasToken(workingExpression)) workingExpression = await resolveTokens(workingExpression, true); if (!workingExpression) return false; const negation = workingExpression.startsWith('!'); if (negation) { workingExpression = workingExpression.slice(1, workingExpression.length); } let result = toBoolean(workingExpression); if (hasExpression(workingExpression)) { result = await evaluate(workingExpression, context); } return negation ? !result : result; } const expressions = /*#__PURE__*/Object.freeze({ __proto__: null, hasExpression: hasExpression, convertFromJson: convertFromJson, evaluateExpression: evaluateExpression, evaluatePredicate: evaluatePredicate }); export { evaluatePredicate as a, createWorkerProxy as b, convertFromJson as c, createWorker as d, evaluateExpression as e, expressions as f, hasExpression as h };