'use strict';
if (typeof globalThis == 'undefined') {
const e =
'undefined' != typeof global
? global
: 'undefined' != typeof window
? window
: 'undefined' != typeof self
? self
: {};
e.globalThis = e;
}
Object.defineProperty(exports, '__esModule', { value: true });
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
// minification can replace the `globalThis.qDev` with `false`
// which will remove all dev code within from the build
const qDev = true;
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
const EMPTY_ARRAY = [];
const EMPTY_OBJ = {};
if (qDev) {
Object.freeze(EMPTY_ARRAY);
Object.freeze(EMPTY_OBJ);
}
function isQrl(value) {
return value instanceof QRLInternal;
}
class QRL {
constructor(chunk, symbol, symbolRef, symbolFn, capture, captureRef, guard) {
this.chunk = chunk;
this.symbol = symbol;
this.symbolRef = symbolRef;
this.symbolFn = symbolFn;
this.capture = capture;
this.captureRef = captureRef;
this.guard = guard;
this.canonicalChunk = chunk.replace(FIND_EXT, '');
}
}
const QRLInternal = QRL;
// https://regexr.com/6enjv
const FIND_EXT = /\.[\w?=&]+$/;
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
function assertDefined(value, text) {
if (qDev) {
if (value != null)
return;
throw newError(text || 'Expected defined value.');
}
}
function assertNotEqual(value1, value2, text) {
if (qDev) {
if (value1 !== value2)
return;
throw newError(text || `Expected '${value1}' !== '${value2}'.`);
}
}
function assertEqual(value1, value2, text) {
if (qDev) {
if (value1 === value2)
return;
throw newError(text || `Expected '${value1}' === '${value2}'.`);
}
}
function assertGreaterOrEqual(value1, value2, text) {
if (qDev) {
if (value1 >= value2)
return;
throw newError(text || `Expected '${value1}' >= '${value2}'.`);
}
}
function assertGreater(value1, value2, text) {
if (qDev) {
if (value1 > value2)
return;
throw newError(text || `Expected '${value1}' > '${value2}'.`);
}
}
function newError(text) {
debugger; // eslint-disable-line no-debugger
const error = new Error(text);
console.error(error); // eslint-disable-line no-console
return error;
}
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
let runtimeSymbolId = 0;
const RUNTIME_QRL = '/runtimeQRL';
// https://regexr.com/68v72
const EXTRACT_IMPORT_PATH = /\(\s*(['"])([^\1]+)\1\s*\)/;
// https://regexr.com/690ds
const EXTRACT_SELF_IMPORT = /Promise\s*\.\s*resolve/;
// https://regexr.com/6a83h
const EXTRACT_FILE_NAME = /[\\/(]([\w\d.\-_]+\.(js|ts)x?):/;
function toInternalQRL(qrl) {
assertEqual(isQrl(qrl), true);
return qrl;
}
function staticQrl(chunkOrFn, symbol, lexicalScopeCapture = EMPTY_ARRAY) {
let chunk;
let symbolFn = null;
if (typeof chunkOrFn === 'string') {
chunk = chunkOrFn;
}
else if (typeof chunkOrFn === 'function') {
symbolFn = chunkOrFn;
let match;
const srcCode = String(chunkOrFn);
if ((match = srcCode.match(EXTRACT_IMPORT_PATH)) && match[2]) {
chunk = match[2];
}
else if ((match = srcCode.match(EXTRACT_SELF_IMPORT))) {
const ref = 'QWIK-SELF';
const frames = new Error(ref).stack.split('\n');
const start = frames.findIndex((f) => f.includes(ref));
const frame = frames[start + 2];
match = frame.match(EXTRACT_FILE_NAME);
if (!match) {
chunk = 'main';
}
else {
chunk = match[1];
}
}
else {
throw new Error('Q-ERROR: Dynamic import not found: ' + srcCode);
}
}
else {
throw new Error('Q-ERROR: Unknown type argument: ' + chunkOrFn);
}
return new QRLInternal(chunk, symbol, null, symbolFn, null, lexicalScopeCapture, null);
}
function runtimeQrl(symbol, lexicalScopeCapture = EMPTY_ARRAY) {
return new QRLInternal(RUNTIME_QRL, 's' + runtimeSymbolId++, symbol, null, null, lexicalScopeCapture, null);
}
function stringifyQRL(qrl, element) {
const qrl_ = toInternalQRL(qrl);
const parts = [qrl_.chunk];
const symbol = qrl_.symbol;
if (symbol && symbol !== 'default') {
parts.push('#', symbol);
}
const guard = qrl_.guard;
guard === null || guard === void 0 ? void 0 : guard.forEach((value, key) => parts.push('|', key, value && value.length ? '.' + value.join('.') : ''));
const capture = qrl_.capture;
if (capture && capture.length > 0) {
parts.push(JSON.stringify(capture));
}
const qrlString = parts.join('');
if (qrl_.chunk === RUNTIME_QRL && element) {
const qrls = element.__qrls__ || (element.__qrls__ = new Set());
qrls.add(qrl);
}
return qrlString;
}
/**
* `./chunk#symbol|symbol.propA.propB|[captures]
*/
function parseQRL(qrl, element) {
if (element) {
const qrls = element.__qrls__;
if (qrls) {
for (const runtimeQrl of qrls) {
if (stringifyQRL(runtimeQrl) == qrl) {
return runtimeQrl;
}
}
}
}
const endIdx = qrl.length;
const hashIdx = indexOf(qrl, 0, '#');
const guardIdx = indexOf(qrl, hashIdx, '|');
const captureIdx = indexOf(qrl, guardIdx, '[');
const chunkEndIdx = Math.min(hashIdx, guardIdx, captureIdx);
const chunk = qrl.substring(0, chunkEndIdx);
const symbolStartIdx = hashIdx == endIdx ? hashIdx : hashIdx + 1;
const symbolEndIdx = Math.min(guardIdx, captureIdx);
const symbol = symbolStartIdx == symbolEndIdx ? 'default' : qrl.substring(symbolStartIdx, symbolEndIdx);
const guardStartIdx = guardIdx;
const guardEndIdx = captureIdx;
const guard = guardStartIdx < guardEndIdx ? parseGuard(qrl.substring(guardStartIdx, guardEndIdx)) : null;
const captureStartIdx = captureIdx;
const captureEndIdx = endIdx;
const capture = captureStartIdx === captureEndIdx
? EMPTY_ARRAY
: JSONparse(qrl.substring(captureStartIdx, captureEndIdx));
if (chunk === RUNTIME_QRL) {
console.error(`Q-ERROR: '${qrl}' is runtime but no instance found on element.`);
}
return new QRLInternal(chunk, symbol, null, null, capture, null, guard);
}
function JSONparse(json) {
try {
return JSON.parse(json);
}
catch (e) {
console.error('JSON:', json);
throw e;
}
}
function parseGuard(text) {
let map = null;
if (text) {
text.split('|').forEach((obj) => {
if (obj) {
const parts = obj.split('.');
const id = parts.shift();
if (!map)
map = new Map();
map.set(id, parts);
}
});
}
return map;
}
function indexOf(text, startIdx, char) {
const endIdx = text.length;
const charIdx = text.indexOf(char, startIdx == endIdx ? 0 : startIdx);
return charIdx == -1 ? endIdx : charIdx;
}
function toQrlOrError(symbolOrQrl) {
if (!isQrl(symbolOrQrl)) {
if (typeof symbolOrQrl == 'function' || typeof symbolOrQrl == 'string') {
symbolOrQrl = runtimeQrl(symbolOrQrl);
}
else {
// TODO(misko): centralize
throw new Error(`Q-ERROR Only 'function's and 'string's are supported.`);
}
}
return symbolOrQrl;
}
/**
* Returns true if the `node` is `Element` and of the right `tagName`.
*
* @param node
* @private
*/
function isDomElementWithTagName(node, tagName) {
return isHtmlElement(node) && node.tagName.toUpperCase() == tagName.toUpperCase();
}
/**
* @private
*/
function isTemplateElement(node) {
return isDomElementWithTagName(node, 'template');
}
/**
* @private
*/
function isQSLotTemplateElement(node) {
return isTemplateElement(node) && node.hasAttribute("q:slot" /* QSlotAttr */);
}
/**
* @private
*/
function isComponentElement(node) {
return isHtmlElement(node) && node.hasAttribute("on:q-render" /* OnRenderAttr */);
}
/**
* @private
*/
function isHtmlElement(node) {
return node ? node.nodeType === 1 /* ELEMENT_NODE */ : false;
}
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
function isNode(value) {
return value && typeof value.nodeType == 'number';
}
function isDocument(value) {
return value && value.nodeType == 9 /* DOCUMENT_NODE */;
}
function isElement(value) {
return isNode(value) && value.nodeType == 1 /* ELEMENT_NODE */;
}
function isComment(value) {
return isNode(value) && value.nodeType == 8 /* COMMENT_NODE */;
}
const createPlatform = (doc) => {
let queuePromise;
let storePromise;
const moduleCache = new Map();
return {
importSymbol(element, url, symbolName) {
const urlDoc = toUrl(element.ownerDocument, element, url).toString();
const urlCopy = new URL(urlDoc);
urlCopy.hash = '';
urlCopy.search = '';
const importURL = urlCopy.href;
const mod = moduleCache.get(importURL);
if (mod) {
return mod[symbolName];
}
return (function (t) { return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require(t)); }); })(/* @vite-ignore */ importURL).then((mod) => {
moduleCache.set(importURL, mod);
return mod[symbolName];
});
},
queueRender: (renderMarked) => {
if (!queuePromise) {
queuePromise = new Promise((resolve, reject) => doc.defaultView.requestAnimationFrame(() => {
queuePromise = null;
renderMarked(doc).then(resolve, reject);
}));
}
return queuePromise;
},
queueStoreFlush: (flushStore) => {
if (!storePromise) {
storePromise = new Promise((resolve, reject) => doc.defaultView.requestAnimationFrame(() => {
storePromise = null;
flushStore(doc).then(resolve, reject);
}));
}
return storePromise;
},
};
};
/**
* Convert relative base URI and relative URL into a fully qualified URL.
*
* @param base -`QRL`s are relative, and therefore they need a base for resolution.
* - `Element` use `base.ownerDocument.baseURI`
* - `Document` use `base.baseURI`
* - `string` use `base` as is
* - `QConfig` use `base.baseURI`
* @param url - relative URL
* @returns fully qualified URL.
*/
function toUrl(doc, element, url) {
let _url;
let _base = undefined;
if (url === undefined) {
// recursive call
if (element) {
_url = element.getAttribute('q:base');
_base = toUrl(doc, element.parentNode && element.parentNode.closest('[q\\:base]'));
}
else {
_url = doc.baseURI;
}
}
else if (url) {
(_url = url), (_base = toUrl(doc, element.closest('[q\\:base]')));
}
else {
throw new Error('INTERNAL ERROR');
}
return new URL(String(_url), _base);
}
/**
* @public
*/
const setPlatform = (doc, plt) => (doc[DocumentPlatform] = plt);
/**
* @public
*/
const getPlatform = (docOrNode) => {
const doc = (isDocument(docOrNode) ? docOrNode : docOrNode.ownerDocument);
return doc[DocumentPlatform] || (doc[DocumentPlatform] = createPlatform(doc));
};
const DocumentPlatform = /*@__PURE__*/ Symbol();
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/m5DzCi5MTa26LuUj5t3HpQ#qrlImport instead)
/**
* Lazy-load a `QRL` symbol and return the lazy-loaded value.
*
* See: `QRL`
*
* @param element - Location of the URL to resolve against. This is needed to take `q:base` into
* account.
* @param qrl - QRL to load.
* @returns A resolved QRL value as a Promise.
* @public
*/
//
async function qrlImport(element, qrl) {
const qrl_ = toInternalQRL(qrl);
if (qrl_.symbolRef)
return qrl_.symbolRef;
const doc = element.ownerDocument;
if (qrl_.symbolFn) {
return (qrl_.symbolRef = qrl_.symbolFn().then((module) => module[qrl_.symbol]));
}
else {
return (qrl_.symbolRef = await getPlatform(doc).importSymbol(element, qrl_.chunk, qrl_.symbol));
}
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/m5DzCi5MTa26LuUj5t3HpQ#$ instead)
/**
* Qwik Optimizer marker function.
*
* Use `$(...)` to tell Qwik Optimizer to extract the expression in `$(...)` into a lazy-loadable
* resource referenced by `QRL`.
*
* See: `implicit$FirstArg` for additional `____$(...)` rules.
*
* In this example `$(...)` is used to capture the callback function of `onmousemove` into
* lazy-loadable reference. This allows the code to refer to the function without actually
* loading the function. In this example, the callback function does not get loaded until
* `mousemove` event fires.
*
* ```typescript
* onDocument(
* 'mousemove',
* $(() => console.log('mousemove'))
* );
* ```
*
* In this code the Qwik Optimizer detects `$(...)` and transforms the code into:
*
* ```typescript
* // FILE:
* onDocument('mousemove', qrl('./chunk-abc.js', 'onMousemove'));
*
* // FILE: chunk-abc.js
* export const onMousemove = () => console.log('mousemove');
* ```
*
* ## Special Rules
*
* The Qwik Optimizer places special rules on functions that can be lazy-loaded.
*
* 1. The expression of the `$(expression)` function must be importable by the system.
* (expression shows up in `import` or has `export`)
* 2. If inlined function then all lexically captured values must be:
* - importable (vars shows up in `import` or has `export`)
* - const (The capturing process differs from JS capturing in that writing to captured
* variables does not update them, and therefore writes are forbidden. The best practice is that
* all captured variables are constants.)
* - Must be runtime serializable.
*
* ```typescript
* import { importedFn } from './example';
*
* export const greet = () => console.log('greet');
* function topLevelFn() {}
*
* function myCode() {
* const store = createStore({});
* function localFn() {}
* // Valid Examples
* $(greet); // greet is importable
* $(importedFn); // importedFn is importable
* $(() => greet()); // greet is importable;
* $(() => importedFn()); // importedFn is importable
* $(() => console.log(store)); // store is serializable.
*
* // Compile time errors
* $(topLevelFn); // ERROR: `topLevelFn` not importable
* $(() => topLevelFn()); // ERROR: `topLevelFn` not importable
*
* // Runtime errors
* $(localFn); // ERROR: `localFn` fails serialization
* $(() => localFn()); // ERROR: `localFn` fails serialization
* }
*
* ```
*
* @param expression - Expression which should be lazy loaded
* @public
*/
//
function $(expression) {
return runtimeQrl(expression);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/m5DzCi5MTa26LuUj5t3HpQ#implicit$FirstArg instead)
/**
* Create a `____$(...)` convenience method from `___(...)`.
*
* It is very common for functions to take a lazy-loadable resource as a first argument. For this
* reason, the Qwik Optimizer automatically extracts the first argument from any function which
* ends in `$`.
*
* This means that `foo$(arg0)` and `foo($(arg0))` are equivalent with respect to Qwik Optimizer.
* The former is just a shorthand for the latter.
*
* For example all of these function call are equivalent:
*
* - `component$(() => {...})` is same as `onRender($(() => {...}))`
* - `$(() => <>...>)` is same as `onRender($(() => <>...>))`
*
* ```typescript
* export function myApi(callback: QRL<() => void>): void {
* // ...
* }
*
* export const myApi$ = implicit$FirstArg(myApi);
* // type of myApi$: (callback: () => void): void
*
* // can be used as:
* myApi$(() => console.log('callback'));
*
* // will be transpiled to:
* // FILE:
* myApi(qrl('./chunk-abc.js', 'callback'));
*
* // FILE: chunk-abc.js
* export const callback = () => console.log('callback');
* ```
*
* @param fn - function that should have its first argument automatically `$`.
* @public
*/
//
function implicit$FirstArg(fn) {
return function (first, ...rest) {
return fn.call(null, $(first), ...rest);
};
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/m5DzCi5MTa26LuUj5t3HpQ#qrl instead)
/**
* Used by Qwik Optimizer to point to lazy-loaded resources.
*
* This function should be used by the Qwik Optimizer only. The function should not be directly
* referred to in the source code of the application.
*
* See: `QRL`, `$(...)`
*
* @param chunkOrFn - Chunk name (or function which is stringified to extract chunk name)
* @param symbol - Symbol to lazy load
* @param lexicalScopeCapture - a set of lexically scoped variables to capture.
* @public
*/
//
const qrl = staticQrl;
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
function stringifyDebug(value) {
if (value == null)
return String(value);
if (typeof value === 'function')
return value.name;
if (isHtmlElement(value))
return stringifyElement(value);
if (value instanceof URL)
return String(value);
if (typeof value === 'object')
return JSON.stringify(value, function (key, value) {
if (isHtmlElement(value))
return stringifyElement(value);
return value;
});
return String(value);
}
function stringifyElement(element) {
let html = '<' + element.tagName.toLowerCase();
const attributes = element.attributes;
const names = [];
for (let i = 0; i < attributes.length; i++) {
names.push(attributes[i].name);
}
names.sort();
for (let i = 0; i < names.length; i++) {
const name = names[i];
let value = element.getAttribute(name);
if (value === null || value === void 0 ? void 0 : value.startsWith('file:/')) {
value = value.replace(/(file:\/\/).*(\/.*)$/, (all, protocol, file) => protocol + '...' + file);
}
html +=
' ' + name + (value == null || value == '' ? '' : "='" + value.replace("'", ''') + "'");
}
return html + '>';
}
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
function qError(code, ...args) {
if (qDev) {
const text = codeToText(code);
const parts = text.split('{}');
const error = parts
.map((value, index) => {
return value + (index === parts.length - 1 ? '' : stringifyDebug(args[index]));
})
.join('');
debugger; // eslint-disable-line no-debugger
return new Error(error);
}
else {
return new Error(`QError ` + code);
}
}
function codeToText(code) {
const area = {
0: 'ERROR',
1: 'QRL-ERROR',
2: 'INJECTOR-ERROR',
3: 'SERVICE-ERROR',
4: 'COMPONENT-ERROR',
5: 'PROVIDER-ERROR',
6: 'RENDER-ERROR',
7: 'EVENT-ERROR',
}[Math.floor(code / 100)];
const text = {
[1 /* Core_qConfigNotFound_path */]: "QConfig not found in path '{}'.",
[2 /* Core_unrecognizedStack_frame */]: "Unrecognized stack format '{}'",
[3 /* Core_noAttribute_atr1_element */]: "Could not find entity state '{}' at '{}' or any of it's parents.",
[4 /* Core_noAttribute_atr1_attr2_element */]: "Could not find entity state '{}' ( or entity provider '{}') at '{}' or any of it's parents.",
[5 /* Core_missingProperty_name_props */]: "Missing property '{}' in props '{}'.",
[6 /* Core_missingExport_name_url_props */]: "Missing export '{}' from '{}'. Exported symbols are: {}",
//////////////
[100 /* QRL_expectFunction_url_actual */]: "QRL '${}' should point to function, was '{}'.",
//////////////
[200 /* Injector_noHost_element */]: "Can't find host element above '{}'.",
[201 /* Injector_expectedSpecificInjector_expected_actual */]: "Provider is expecting '{}' but got '{}'.",
[202 /* Injector_notElement_arg */]: "Expected 'Element' was '{}'.",
[203 /* Injector_wrongMethodThis_expected_actual */]: "Expected injection 'this' to be of type '{}', but was of type '{}'.",
[204 /* Injector_missingSerializedState_entityKey_element */]: "Entity key '{}' is found on '{}' but does not contain state. Was 'serializeState()' not run during dehydration?",
[206 /* Injector_notFound_element */]: "No injector can be found starting at '{}'.",
[207 /* Injector_eventInjectorNotSerializable */]: 'EventInjector does not support serialization.',
//////////////
[300 /* Entity_notValidKey_key */]: "Data key '{}' is not a valid key.\n" +
' - Data key can only contain characters (preferably lowercase) or number\n' +
' - Data key is prefixed with entity name\n' +
" - Data key is made up from parts that are separated with ':'.",
[301 /* Entity_keyAlreadyExists_key */]: "A entity with key '{}' already exists.",
[303 /* Entity_invalidAttribute_name */]: "'{}' is not a valid attribute. " +
"Attributes can only contain 'a-z' (lowercase), '0-9', '-' and '_'.",
[304 /* Entity_missingExpandoOrState_attrName */]: "Found '{}' but expando did not have entity and attribute did not have state.",
[305 /* Entity_elementMissingEntityAttr_element_attr */]: "Element '{}' is missing entity attribute definition '{}'.",
[306 /* Entity_noState_entity_props */]: "Unable to create state for entity '{}' with props '{}' because no state found and '$newState()' method was not defined on entity.",
[307 /* Entity_expected_obj */]: "'{}' is not an instance of 'Entity'.",
[308 /* Entity_overridesConstructor_entity */]: "'{}' overrides 'constructor' property preventing 'EntityType' retrieval.",
[311 /* Entity_no$keyProps_entity */]: "Entity '{}' does not define '$keyProps'.",
[310 /* Entity_no$type_entity */]: "Entity '{}' must have static '$type' property defining the name of the entity.",
[312 /* Entity_no$qrl_entity */]: "Entity '{}' must have static '$qrl' property defining the import location of the entity.",
[313 /* Entity_nameCollision_name_currentQrl_expectedQrl */]: "Name collision. Already have entity named '{}' with QRL '{}' but expected QRL '{}'.",
[309 /* Entity_keyMissingParts_key_key */]: "Entity key '{}' is missing values. Expecting '{}:someValue'.",
[314 /* Entity_keyTooManyParts_entity_parts_key */]: "Entity '{}' defines '$keyProps' as '{}'. Actual key '{}' has more parts than entity defines.",
[315 /* Entity_keyNameMismatch_key_name_entity_name */]: "Key '{}' belongs to entity named '{}', but expected entity '{}' with name '{}'.",
[316 /* Entity_stateMissingKey_state */]: "Entity state is missing '$key'. Are you sure you passed in state? Got '{}'.",
//////////////
[400 /* Component_bindNeedsKey */]: "'bind:' must have an key. (Example: 'bind:key=\"propertyName\"').",
[401 /* Component_bindNeedsValue */]: "'bind:id' must have a property name. (Example: 'bind:key=\"propertyName\"').",
[402 /* Component_needsState */]: "Can't find state on host element.",
[403 /* Component_needsInjectionContext_constructor */]: "Components must be instantiated inside an injection context. Use '{}.new(...)' for creation.",
[404 /* Component_noProperty_propName_props_host */]: "Property '{}' not found in '{}' on component '{}'.",
[405 /* Component_notFound_component */]: "Unable to find '{}' component.",
[406 /* Component_doesNotMatch_component_actual */]: "Requesting component type '{}' does not match existing component instance '{}'.",
[408 /* Component_noState_component_props */]: "Unable to create state for component '{}' with props '{}' because no state found and '$newState()' method was not defined on component.",
//////////////
[500 /* Provider_unrecognizedFormat_value */]: "Unrecognized expression format '{}'.",
//////////////
[600 /* Render_unexpectedJSXNodeType_type */]: 'Unexpected JSXNode<{}> type.',
[601 /* Render_unsupportedFormat_obj_attr */]: "Value '{}' can't be written into '{}' attribute.",
[602 /* Render_expectingEntity_entity */]: "Expecting entity object, got '{}'.",
[603 /* Render_expectingEntityArray_obj */]: "Expecting array of entities, got '{}'.",
[604 /* Render_expectingEntityOrComponent_obj */]: "Expecting Entity or Component got '{}'.",
[699 /* Render_stateMachineStuck */]: 'Render state machine did not advance.',
//////////////
[700 /* Event_emitEventRequiresName_url */]: "Missing '$type' attribute in the '{}' url.",
[701 /* Event_emitEventCouldNotFindListener_event_element */]: "Re-emitting event '{}' but no listener found at '{}' or any of its parents.",
}[code];
let textCode = '000' + code;
textCode = textCode.substr(textCode.length - 3);
return `${area}(Q-${textCode}): ${text}`;
}
/**
* Remove item from array (Same as `Array.splice()` but faster.)
*
* `Array.splice()` is not as fast because it has to allocate an array for the elements which were
* removed. This causes memory pressure and slows down code when most of the time we don't
* care about the deleted items array.
*
* https://jsperf.com/fast-array-splice (About 20x faster)
*
* @param array Array to splice
* @param index Index of element in array to remove.
* @param count Number of items to remove.
*/
/**
* Same as `Array.splice2(index, 0, value1, value2)` but faster.
*
* `Array.splice()` is not fast because it has to allocate an array for the elements which were
* removed. This causes memory pressure and slows down code when most of the time we don't
* care about the deleted items array.
*
* @param array Array to splice.
* @param index Index in array where the `value` should be added.
* @param value1 Value to add to array.
* @param value2 Value to add to array.
*/
function arrayInsert2(array, index, value1, value2) {
let end = array.length;
if (end == index) {
// inserting at the end.
array.push(value1, value2);
}
else if (end === 1) {
// corner case when we have less items in array than we have items to insert.
array.push(value2, array[0]);
array[0] = value1;
}
else {
end--;
array.push(array[end - 1], array[end]);
while (end > index) {
const previousEnd = end - 2;
array[end] = array[previousEnd];
end--;
}
array[index] = value1;
array[index + 1] = value2;
}
}
function keyValueArrayGet(keyValueArray, key, notFoundFactory) {
const index = keyValueArrayIndexOf(keyValueArray, key);
if (index >= 0) {
// if we found it retrieve it.
return keyValueArray[index | 1];
}
if (notFoundFactory) {
const value = notFoundFactory();
arrayInsert2(keyValueArray, ~index, key, value);
return value;
}
return undefined;
}
/**
* Retrieve a `key` index value in the array or `-1` if not found.
*
* @param keyValueArray to search.
* @param key The key to locate.
* @returns index of where the key is (or should have been.)
* - positive (even) index if key found.
* - negative index if key not found. (`~index` (even) to get the index where it should have
* been inserted.)
*/
function keyValueArrayIndexOf(keyValueArray, key) {
return _arrayIndexOfSorted(keyValueArray, key, 1);
}
/**
* INTERNAL: Get an index of an `value` in a sorted `array` by grouping search by `shift`.
*
* NOTE:
* - This uses binary search algorithm for fast removals.
*
* @param array A sorted array to binary search.
* @param value The value to look for.
* @param shift grouping shift.
* - `0` means look at every location
* - `1` means only look at every other (even) location (the odd locations are to be ignored as
* they are values.)
* @returns index of the value.
* - positive index if value found.
* - negative index if value not found. (`~index` to get the value where it should have been
* inserted)
*/
function _arrayIndexOfSorted(array, value, shift) {
let start = 0;
let end = array.length >> shift;
while (end !== start) {
const middle = start + ((end - start) >> 1); // find the middle.
const current = array[middle << shift];
if (value === current) {
return middle << shift;
}
else if (current > value) {
end = middle;
}
else {
start = middle + 1; // We already searched middle so make it non-inclusive by adding 1
}
}
return ~(end << shift);
}
function isSlotMap(value) {
return Array.isArray(value);
}
/**
* Retrieves the current `SlotMap` from `QComponent`
*
*
* This method collects the content `Node`s for a given component.
*
* @param component
* @returns
*/
function getSlotMap(component) {
const slots = [];
const host = component.hostElement;
const firstChild = host.firstElementChild;
if (isQSlotTemplate(firstChild)) {
slotMapAddChildren(slots, firstChild.content, null);
}
const previousSlots = [];
host.querySelectorAll("Q\\:SLOT" /* QSlotSelector */).forEach((qSlot) => {
for (const parent of previousSlots) {
if (parent.contains(qSlot)) {
// When we do `querySelectorAll` it is possible that we get ``
// which are children of existing ``. This check is here
// to make sure that we don't get `` recursively.
//
//
//
//
//
return;
}
}
previousSlots.push(qSlot);
const name = qSlot.getAttribute('name') || '';
slotMapAddChildren(slots, qSlot, name);
});
return slots;
}
/**
* Determines if the `node` is `` used for storing un-projected items.
*/
function isQSlotTemplate(node) {
return isDomElementWithTagName(node, 'template') && node.hasAttribute("q:slot" /* QSlotAttr */);
}
/**
* Add projected nodes into `SlotMap`.
*
* See `SlotMap` for the layout.
*
* @param slots
* @param parent Parent whoes children should be added to the `slots`.
*/
function slotMapAddChildren(slots, parent, name) {
_slotParent = parent;
let child = parent.firstChild;
if (name !== null) {
keyValueArrayGet(slots, name, emptyArrayFactory);
}
while (child) {
const slotName = name !== null
? name
: (isHtmlElement(child) && child.getAttribute("q:slot" /* QSlotAttr */)) || '';
keyValueArrayGet(slots, slotName, emptyArrayFactory).push(child);
child = child.nextSibling;
}
_slotParent = undefined;
}
let _slotParent;
function emptyArrayFactory() {
return [-1, _slotParent];
}
/**
* Create a cursor which reconciles logical children.
*
* Here logical means children as defined by JSX. (This will be same as DOM except
* in the case of projection.) In case of projection the cursor will correctly
* deal with the logical children of the View (rather then rendered children.)
*
* See: `cursorForComponent`
*
* @param parent Parent `Element` whose children should be reconciled.
*/
function cursorForParent(parent) {
let firstChild = parent.firstChild;
if (firstChild && firstChild.nodeType === 10 /* DOCUMENT_TYPE_NODE */) {
firstChild = firstChild.nextSibling;
}
return newCursor(parent, firstChild, null);
}
function newCursor(parent, node, end) {
return { parent, node, end };
}
function getNode(cursor) {
const node = cursor.node;
return cursor.end == node ? null : node;
}
function setNode(cursor, node) {
cursor.node = cursor.end == node ? null : node;
}
function cursorClone(cursor) {
return newCursor(cursor.parent, cursor.node, cursor.end);
}
/**
* Reconcile view children of a component.
*
* Use this method to create a cursor when reconciling a component's view.
*
* The main point of this method is to skip the `` Node.
*
* @param componentHost Component host element for which view children should be
* reconciled.
* @returns
*/
function cursorForComponent(componentHost) {
assertEqual(isComponentElement(componentHost), true);
let firstNonTemplate = componentHost.firstChild;
if (isQSLotTemplateElement(firstNonTemplate)) {
firstNonTemplate = firstNonTemplate.nextSibling;
}
return newCursor(componentHost, firstNonTemplate, null);
}
/**
* Ensure that node at cursor is an `Element` with given attributes.
*
* Reconciles the current cursor location with `expectTag`/`expectProps`.
* This method will either leave the element alone if it matches, updates the
* props, or completely removes and replaces the node with correct element.
*
* After invocation of this method, the cursor is advanced to the next sibling.
*
* @param cursor
* @param component `ComponentRenderContext` of the component to whom the view childer
* logically belong.
* @param expectTag
* @param expectProps
* @param componentRenderQueue Set if the current element is a component.
* This means that the reconciliation should detect input changes and if
* present add the component to the `componentRenderQueue` for further processing.
* @returns Child `Cursor` to reconcile the children of this `Element`.
*/
function cursorReconcileElement(cursor, component, expectTag, expectProps, componentRenderQueue) {
let node = getNode(cursor);
assertNotEqual(node, undefined, 'Cursor already closed');
if (isSlotMap(node)) {
assertDefined(cursor.parent);
return slotMapReconcileSlots(cursor.parent, node, cursor.end, component, expectTag, expectProps, componentRenderQueue);
}
else {
assertNotEqual(node, undefined, 'Cursor already closed');
node = _reconcileElement(cursor.parent, node, cursor.end, component, expectTag, expectProps, componentRenderQueue);
assertDefined(node);
setNode(cursor, node.nextSibling);
return _reconcileElementChildCursor(node, !!componentRenderQueue);
}
}
function slotMapReconcileSlots(parent, slots, end, component, expectTag, expectProps, componentRenderQueue) {
const slotName = expectProps["q:slot" /* QSlotAttr */] || '';
const namedSlot = keyValueArrayGet(slots, slotName);
let childNode;
if (namedSlot) {
assertGreaterOrEqual(namedSlot.length, 2);
const parent = namedSlot[1 /* parent */];
let index = namedSlot[0 /* index */];
if (index == -1) {
index = 2;
}
childNode = (namedSlot.length > index ? namedSlot[index] : null);
const node = _reconcileElement(parent, childNode, end, component, expectTag, expectProps, componentRenderQueue);
if (childNode !== node) {
namedSlot[index] = node;
childNode = node;
}
namedSlot[0 /* index */] = index + 1;
}
else {
const template = getUnSlottedStorage(parent);
childNode = _reconcileElement(template.content, null, end, component, expectTag, expectProps, true);
assertDefined(childNode);
}
return _reconcileElementChildCursor(childNode, !!componentRenderQueue);
}
function _reconcileElement(parent, existing, end, component, expectTag, expectProps, componentRenderQueue) {
let shouldDescendIntoComponent;
let reconciledElement;
if (isDomElementWithTagName(existing, expectTag)) {
const props = getProps(existing);
Object.assign(props, expectProps);
shouldDescendIntoComponent = didQPropsChange(props) && !!componentRenderQueue;
reconciledElement = existing;
}
else {
// Expected node and actual node did not match. Need to switch.
reconciledElement = replaceNode(parent, existing, (isDocument(parent) ? parent : parent.ownerDocument).createElement(expectTag), end);
shouldDescendIntoComponent = !!componentRenderQueue;
Object.assign(getProps(reconciledElement), expectProps);
}
component && component.styleClass && reconciledElement.classList.add(component.styleClass);
if (shouldDescendIntoComponent) {
const hostComponent = getQComponent(reconciledElement);
hostComponent.styleHostClass && reconciledElement.classList.add(hostComponent.styleHostClass);
if (Array.isArray(componentRenderQueue)) {
componentRenderQueue.push(hostComponent.render());
}
else if (reconciledElement.getAttribute("on:q-render" /* OnRenderAttr */)) {
reconciledElement.setAttribute("on:q-render-notify" /* RenderNotify */, '');
}
}
return reconciledElement;
}
function _reconcileElementChildCursor(node, isComponent) {
assertDefined(node);
if (isComponent) {
// We are a component. We need to return Slots
return newCursor(node, getSlotMap(getQComponent(node)), null);
}
else {
// Not a component, normal return.
return cursorForParent(node);
}
}
/**
* Ensure that node at cursor is a `Text`.
*
* Reconciles the current cursor location with expected text.
* This method will either leave the text alone if it matches, updates the
* text, or completely removes and replaces the node with correct text.
*
* After invocation of this method, the cursor is advanced to the next sibling.
*
* @param cursor
* @param expectText
*/
function cursorReconcileText(cursor, expectText) {
let node = getNode(cursor);
assertNotEqual(node, undefined, 'Cursor already closed');
assertDefined(cursor.parent);
if (isSlotMap(node)) {
let parent;
let childNode;
const namedSlot = keyValueArrayGet(node, '');
if (namedSlot) {
assertGreaterOrEqual(namedSlot.length, 2);
parent = namedSlot[1 /* parent */];
let index = namedSlot[0 /* index */];
if (index == -1) {
index = 2;
}
childNode = (namedSlot.length > index ? namedSlot[index] : null);
node = _reconcileText(parent, childNode, cursor.end, expectText);
if (childNode !== node) {
namedSlot[index] = node;
}
namedSlot[0 /* index */] = index + 1;
}
else {
const template = getUnSlottedStorage(cursor.parent);
_reconcileText(template.content, null, cursor.end, expectText);
}
}
else {
node = _reconcileText(cursor.parent, node, cursor.end, expectText);
setNode(cursor, node.nextSibling);
}
}
function _reconcileText(parent, node, beforeNode, expectText) {
// Reconcile as Text Node
if (node && node.nodeType == 3 /* TEXT_NODE */) {
if (node.textContent !== expectText) {
node.textContent = expectText;
}
}
else {
// Expected node and actual node did not match. Need to switch.
node = replaceNode(parent, node, parent.ownerDocument.createTextNode(expectText), beforeNode);
}
return node;
}
/**
* Close out the cursor and clear any extra elements.
*
* Invocation of this method indicates that no mare Nodes after the cursor are expected.
* This is a signal to remove any excess `Node`s if present.
*
* @param cursor
*/
function cursorReconcileEnd(cursor) {
let node = getNode(cursor);
if (isSlotMap(node)) {
for (let i = 0; i < node.length; i = i + 2) {
const namedSlot = node[i + 1];
if (namedSlot[0 /* index */] !== -1) {
assertGreater(namedSlot[0 /* index */], 1 /* parent */);
for (let k = namedSlot[0 /* index */]; k < namedSlot.length; k++) {
namedSlot[1 /* parent */].removeChild(namedSlot[k]);
}
}
}
}
else {
while (node) {
const next = node.nextSibling;
cursor.parent.removeChild(node);
node = next;
}
}
setNode(cursor, undefined);
}
function getUnSlottedStorage(componentElement) {
assertEqual(isComponentElement(componentElement), true, 'Must be component element');
let template = componentElement === null || componentElement === void 0 ? void 0 : componentElement.firstElementChild;
if (!isDomElementWithTagName(template, 'template') ||
!template.hasAttribute("q:slot" /* QSlotAttr */)) {
template = componentElement.insertBefore(componentElement.ownerDocument.createElement('template'), template);
template.setAttribute("q:slot" /* QSlotAttr */, '');
}
return template;
}
const V_NODE_START = '');
const endVNode = doc.createComment(V_NODE_END + id + '>');
node = replaceNode(cursor.parent, node, endVNode, null);
cursor.parent.insertBefore(startVNode, endVNode);
setNode(cursor, endVNode.nextSibling);
return newCursor(parent, startVNode, endVNode);
}
}
}
function cursorReconcileStartVirtualNode(cursor) {
const node = getNode(cursor);
assertEqual(isComment(node) && node.textContent.startsWith(V_NODE_START), true);
setNode(cursor, node && node.nextSibling);
}
function replaceNode(parentNode, existingNode, newNode, insertBefore) {
parentNode.insertBefore(newNode, existingNode || insertBefore);
if (existingNode) {
parentNode.removeChild(existingNode);
}
return newNode;
}
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
function flattenArray(array, dst) {
// Yes this function is just Array.flat, but we need to run on old versions of Node.
if (!dst)
dst = [];
for (const item of array) {
if (Array.isArray(item)) {
flattenArray(item, dst);
}
else {
dst.push(item);
}
}
return dst;
}
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
/**
* Converts a tree of Promises into a flat array of resolved promise values.
*
* @param tree - array of arrays of values or promises of values.
* @returns a `Promise` of array of values.
*/
function flattenPromiseTree(tree) {
return Promise.all(tree).then((values) => {
const flatArray = flattenArray(values);
for (let i = 0; i < flatArray.length; i++) {
if (isPromise(flatArray[i])) {
return flattenPromiseTree(flatArray);
}
}
return flatArray;
});
}
function isPromise(value) {
return value instanceof Promise;
}
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
/**
* Place at the root of the component View to allow binding of attributes on the Host element.
*
* ```
*
* View content implementation.
*
* ```
*
* Qwik requires that components have [docs/HOST_ELEMENTS.ts] so that it is possible to have
* asynchronous loading point. Host element is not owned by the component. At times it is
* desirable for the component to render additional attributes on the host element. ``
* servers that purpose.
* @public
*/
const Host = { __brand__: 'host' };
/**
* @public
*/
function jsx(type, props, key) {
return new JSXNodeImpl(type, props, key);
}
class JSXNodeImpl {
constructor(type, props, key) {
this.type = type;
this.props = props;
this.key = key;
if (props && props.children !== undefined) {
if (Array.isArray(props.children)) {
this.children = props.children;
}
else {
this.children = [props.children];
}
}
else {
this.children = EMPTY_ARRAY;
}
}
}
const isJSXNode = (n) => {
if (qDev) {
if (n instanceof JSXNodeImpl) {
return true;
}
if (n && typeof n === 'object' && n.constructor.name === JSXNodeImpl.name) {
throw new Error(`Duplicate implementations of "JSXNodeImpl" found`);
}
return false;
}
else {
return n instanceof JSXNodeImpl;
}
};
/**
* @public
*/
const Fragment = {};
/**
* @public
*/
const Slot = {
__brand__: 'slot',
};
function visitJsxNode(component, renderQueue, cursor, jsxNode) {
if (isJSXNode(jsxNode)) {
const nodeType = jsxNode.type;
if (nodeType == null)
return;
if (typeof nodeType === 'string') {
visitJsxLiteralNode(component, renderQueue, cursor, jsxNode);
}
else if (nodeType === Fragment || nodeType == null) {
const jsxChildren = jsxNode.children || EMPTY_ARRAY;
for (const jsxChild of jsxChildren) {
visitJsxNode(component, renderQueue, cursor, jsxChild);
}
}
else if (jsxNode.type === Host) {
const props = getProps(cursor.parent);
Object.assign(props, jsxNode.props);
const jsxChildren = jsxNode.children || EMPTY_ARRAY;
for (const jsxChild of jsxChildren) {
visitJsxNode(component, renderQueue, cursor, jsxChild);
}
didQPropsChange(props);
}
else if (jsxNode.type === Slot) {
component && visitQSlotJsxNode(component, renderQueue, cursor, jsxNode);
}
else if (typeof jsxNode.type === 'function') {
visitJsxNode(component, renderQueue, cursor, jsxNode.type(jsxNode.props));
}
else {
throw qError(600 /* Render_unexpectedJSXNodeType_type */, nodeType);
}
}
else if (isPromise(jsxNode)) {
const vNodeCursor = cursorReconcileVirtualNode(cursor);
const render = (jsxNode) => {
cursorReconcileStartVirtualNode(vNodeCursor);
visitJsxNode(component, renderQueue, vNodeCursor, jsxNode);
cursorReconcileEnd(vNodeCursor);
};
jsxNode.then(render, render);
if (jsxNode.whilePending) {
const vNodePending = cursorClone(vNodeCursor);
cursorReconcileStartVirtualNode(vNodePending);
visitJsxNode(component, renderQueue, vNodePending, jsxNode.whilePending);
cursorReconcileEnd(vNodePending);
}
}
else if (Array.isArray(jsxNode)) {
const jsxChildren = jsxNode;
for (const jsxChild of jsxChildren) {
visitJsxNode(component, renderQueue, cursor, jsxChild);
}
}
else if (typeof jsxNode === 'string' || typeof jsxNode === 'number') {
// stringify
cursorReconcileText(cursor, String(jsxNode));
}
}
function visitJsxLiteralNode(component, renderQueue, cursor, jsxNode) {
const jsxTag = jsxNode.type;
const isQComponent = "on:qRender" /* OnRenderProp */ in jsxNode.props;
const elementCursor = cursorReconcileElement(cursor, component, jsxTag, jsxNode.props, isQComponent ? renderQueue : null);
if (!hasInnerHtmlOrTextBinding(jsxNode)) {
// we don't process children if we have inner-html bound to something.
const jsxChildren = jsxNode.children || EMPTY_ARRAY;
for (const jsxChild of jsxChildren) {
visitJsxNode(component, renderQueue, elementCursor, jsxChild);
}
cursorReconcileEnd(elementCursor);
}
else if (isQComponent) {
//TODO(misko): needs tests and QError.
throw new Error('innerHTML/innerText bindings not supported on component content');
}
}
function hasInnerHtmlOrTextBinding(jsxNode) {
return 'innerHTML' in jsxNode.props || 'innerText' in jsxNode.props;
}
function visitQSlotJsxNode(component, renderQueue, cursor, jsxNode) {
const slotName = jsxNode.props.name || '';
const slotCursor = cursorReconcileElement(cursor, component, "Q:SLOT" /* QSlot */, Object.assign({ ["name" /* QSlotName */]: slotName }, jsxNode.props), null);
const slotMap = getSlotMap(component);
const namedSlot = keyValueArrayGet(slotMap, slotName);
if (namedSlot && namedSlot.length > 2 /* firstNode */) {
// project existing nodes.
const cursorParent = slotCursor.parent;
if (namedSlot[1 /* parent */] !== cursorParent) {
// The only time we need to do anything if the existing elements are not already
// in the right spot. Move them.
cursorReconcileEnd(slotCursor); // clear anything which is already in.
for (let i = 2 /* firstNode */; i < namedSlot.length; i++) {
const node = namedSlot[i];
cursorParent.appendChild(node);
}
cursorReconcileEnd(slotCursor);
}
cursorParent.querySelectorAll("[on\\:q-render-notify]" /* RenderNotifySelector */).forEach((compElem) => {
renderQueue.push(getQComponent(compElem).render());
});
}
else {
// fallback to default value projection.
const jsxChildren = jsxNode.children;
for (const jsxChild of jsxChildren) {
visitJsxNode(component, renderQueue, slotCursor, jsxChild);
}
cursorReconcileEnd(slotCursor);
}
}
function hashCode(text, hash = 0) {
if (text.length === 0)
return hash;
for (let i = 0; i < text.length; i++) {
const chr = text.charCodeAt(i);
hash = (hash << 5) - hash + chr;
hash |= 0; // Convert to 32bit integer
}
return Number(Math.abs(hash)).toString(36);
}
function styleKey(qStyles) {
return qStyles && String(hashCode(qStyles.symbol));
}
function styleHost(styleId) {
return styleId && "\uD83D\uDCE6" /* ComponentStylesPrefixHost */ + styleId;
}
function styleContent(styleId) {
return styleId && "\uD83C\uDFF7\uFE0F" /* ComponentStylesPrefixContent */ + styleId;
}
function safeQSubscribe(qObject) {
assertNotEqual(unwrapProxy(qObject), qObject, 'Expecting Proxy');
_context && _context.subscriptions && qObject && _context.subscriptions.add(qObject);
}
let _context;
function getInvokeContext() {
if (!_context) {
const context = typeof document !== 'undefined' && document && document.__q_context__;
if (!context) {
// TODO(misko): centralize
throw new Error("Q-ERROR: invoking 'use*()' method outside of invocation context.");
}
if (Array.isArray(context)) {
const element = context[0].closest("[on\\:q\\-render]" /* OnRenderSelector */);
assertDefined(element);
return (document.__q_context__ = newInvokeContext(element, context[1], context[2]));
}
return context;
}
return _context;
}
function useInvoke(context, fn, ...args) {
const previousContext = _context;
let returnValue;
try {
_context = context;
returnValue = fn.apply(null, args);
}
finally {
const currentCtx = _context;
const subscriptions = currentCtx.subscriptions;
if (subscriptions) {
const element = currentCtx.hostElement;
element && (getProps(element)[':subscriptions'] = subscriptions);
}
_context = previousContext;
if (currentCtx.waitOn && currentCtx.waitOn.length > 0) {
// eslint-disable-next-line no-unsafe-finally
return Promise.all(currentCtx.waitOn).then(() => returnValue);
}
}
return returnValue;
}
function newInvokeContext(hostElement, event, url) {
return {
hostElement: hostElement,
event: event,
url: url || null,
qrl: undefined,
subscriptions: event === 'qRender' ? new Set() : undefined,
};
}
/**
* @private
*/
function useWaitOn(promise) {
const ctx = getInvokeContext();
(ctx.waitOn || (ctx.waitOn = [])).push(promise);
}
// TODO(misko): Can we get rid of this whole file, and instead teach getProps to know how to render
// the advantage will be that the render capability would then be exposed to the outside world as well.
class QComponentCtx {
constructor(hostElement) {
this.styleId = undefined;
this.styleClass = null;
this.styleHostClass = null;
this.hostElement = hostElement;
}
async render() {
const hostElement = this.hostElement;
const props = getProps(hostElement);
const onRender = props['on:qRender']; // TODO(misko): extract constant
assertDefined(onRender);
hostElement.removeAttribute("on:q-render-notify" /* RenderNotify */);
const renderQueue = [];
try {
const event = 'qRender';
const jsxNode = await useInvoke(newInvokeContext(hostElement, event), onRender);
if (this.styleId === undefined) {
const scopedStyleId = (this.styleId = hostElement.getAttribute("q:sstyle" /* ComponentScopedStyles */));
if (scopedStyleId) {
this.styleHostClass = styleHost(scopedStyleId);
this.styleClass = styleContent(scopedStyleId);
}
}
const cursor = cursorForComponent(this.hostElement);
visitJsxNode(this, renderQueue, cursor, jsxNode);
cursorReconcileEnd(cursor);
}
catch (e) {
// TODO(misko): Proper error handling
// eslint-disable-next-line no-console
console.log(e);
}
return [this.hostElement, ...(await flattenPromiseTree(renderQueue))];
}
}
const COMPONENT_PROP = '__qComponent__';
function getQComponent(hostElement) {
const element = hostElement;
let component = element[COMPONENT_PROP];
if (!component)
component = element[COMPONENT_PROP] = new QComponentCtx(hostElement);
return component;
}
/**
* Mark component for rendering.
*
* Use `notifyRender` method to mark a component for rendering at some later point in time.
* This method uses `getPlatform(doc).queueRender` for scheduling of the rendering. The
* default implementation of the method is to use `requestAnimationFrame` to do actual rendering.
*
* The method is intended to coalesce multiple calls into `notifyRender` into a single call for
* rendering.
*
* @param hostElement - Host-element of the component to re-render.
* @returns A promise which is resolved when the component has been rendered.
* @public
*/
// TODO(misko): tests
// TODO(misko): this should take QComponent as well.
function notifyRender(hostElement) {
assertDefined(hostElement.getAttribute("on:q-render" /* OnRenderAttr */));
hostElement.setAttribute("on:q-render-notify" /* RenderNotify */, '');
return scheduleRender(hostElement.ownerDocument);
}
/**
* Schedule rendering for the future.
*
* Multiple calls to this function result in a single `rAF` scheduling creating coalescence.
*
* Rendering is achieved by `querySelectorAll` looking for all `on:q-render` attributes.
*
* @returns a `Promise` of all of the `HostElements` which were re-rendered.
* @internal
*/
function scheduleRender(doc) {
return getPlatform(doc).queueRender(renderMarked);
}
async function renderMarked(doc) {
const hosts = Array.from(doc.querySelectorAll("[on\\:q-render-notify]" /* RenderNotifySelector */));
return Promise.all(hosts.map((hostElement) => {
hostElement.removeAttribute("on:q-render-notify" /* RenderNotify */);
const cmp = getQComponent(hostElement);
return cmp && cmp.render();
}));
}
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
function debugStringify(value) {
if (value != null && typeof value == 'object') {
return String(value.constructor.name) + '\n' + safeJSONStringify(value);
}
return String(value);
}
function safeJSONStringify(value) {
try {
return JSON.stringify(value, null, ' ');
}
catch (e) {
return String(e);
}
}
function createWatchFnObserver(doc) {
const subscriptions = new Map();
function wrap(obj) {
const id = getQObjectId(obj);
if (!id) {
throw new Error('Q-ERROR: only object stores can be observed.');
}
const obs = subscriptions.get(obj);
if (obs) {
return obs.value;
}
QObject_addDoc(obj, doc);
const proxy = new SubscribeProxy(obj, subscriptions, wrap);
const value = new Proxy(obj, proxy);
subscriptions.set(obj, { value, proxy });
return value;
}
wrap.getGuard = function () {
const map = new Map();
subscriptions.forEach((value, key) => {
const props = value.proxy.properties;
return props && map.set(getQObjectId(key), Array.from(props));
});
return map;
};
return wrap;
}
class SubscribeProxy {
constructor(obj, subscriptions, wrap) {
this.obj = obj;
this.subscriptions = subscriptions;
this.wrap = wrap;
this.properties = null;
}
get(target, prop) {
let value = target[prop];
const props = this.properties || (this.properties = new Set());
props.add(prop);
if (typeof value == 'object' && value != null) {
value = this.wrap(value);
}
return value;
}
set(target, prop, newValue) {
throw new Error('Writing to observables is not allowed! Property: ' + prop + ' ' + newValue);
// return true;
}
has(target, property) {
return Object.prototype.hasOwnProperty.call(target, property);
}
ownKeys(target) {
return Object.getOwnPropertyNames(target);
}
}
const ON_WATCH = 'on:qWatch';
function registerOnWatch(element, props, watchFnQrl) {
props[ON_WATCH] = watchFnQrl;
invokeWatchFn(element, watchFnQrl);
}
const cleanupFnMap = new Map();
async function invokeWatchFn(element, watchFnQrl) {
const watchFn = await qrlImport(element, watchFnQrl);
const previousCleanupFn = cleanupFnMap.get(watchFn);
cleanupFnMap.delete(watchFn);
if (isCleanupFn(previousCleanupFn)) {
try {
previousCleanupFn();
}
catch (e) {
// TODO(misko): Centralize error handling
console.error(e);
}
}
const obs = createWatchFnObserver(element.ownerDocument);
try {
const nextCleanupFn = watchFn(obs);
if (isCleanupFn(nextCleanupFn)) {
cleanupFnMap.set(watchFn, nextCleanupFn);
}
}
catch (e) {
// TODO(misko): Centralize error handling
console.error(e);
}
finally {
// const guardRef = (watchFnQrl.guardRef = new Map());
watchFnQrl.guard = obs.getGuard();
getProps(element)[ON_WATCH] = watchFnQrl; // force a re-render of QRL.
}
}
function isCleanupFn(value) {
return typeof value === 'function';
}
async function notifyWatchers(element, qObjectId, propName) {
const qProps = getProps(element);
const onWatch = qProps['on:qWatch'];
if (onWatch) {
try {
const context = newInvokeContext(element);
context.qrlGuard = (qrl) => {
var _a;
const props = (_a = qrl.guard) === null || _a === void 0 ? void 0 : _a.get(qObjectId);
return props ? props.indexOf(propName) !== -1 : false;
};
await useInvoke(context, onWatch, qObjectId, propName);
}
catch (e) {
console.error(e);
}
}
}
function qObject(obj) {
assertEqual(unwrapProxy(obj), obj, 'Unexpected proxy at this location');
if (obj == null || typeof obj !== 'object') {
// TODO(misko): centralize
throw new Error(`Q-ERROR: Only objects can be wrapped in 'QObject', got ` + debugStringify(obj));
}
if (obj.constructor !== Object) {
throw new Error(`Q-ERROR: Only objects literals can be wrapped in 'QObject', got ` + debugStringify(obj));
}
const proxy = readWriteProxy(obj, generateId());
Object.assign(proxy, obj);
return proxy;
}
function _restoreQObject(obj, id) {
return readWriteProxy(obj, id);
}
function QObject_notifyWrite(id, doc, propName) {
if (doc) {
const effectedElements = doc.querySelectorAll(idToComponentSelector(id));
effectedElements.forEach(notifyRender);
effectedElements.forEach((element) => notifyWatchers(element, id, propName));
}
}
function QObject_notifyRead(target) {
const proxy = proxyMap.get(target);
assertDefined(proxy);
safeQSubscribe(proxy);
}
function QObject_addDoc(qObj, doc) {
assertNotEqual(unwrapProxy(qObj), qObj, 'Expected Proxy');
qObj[QObjectDocumentSymbol] = doc;
}
function getQObjectId(obj) {
let id;
if (obj && typeof obj === 'object') {
id = obj[QObjectIdSymbol];
if (!id && isElement(obj)) {
id = obj.getAttribute("q:id" /* ELEMENT_ID */);
if (id == null) {
obj.setAttribute("q:id" /* ELEMENT_ID */, (id = generateId()));
}
id = "#" /* ELEMENT_ID_PREFIX */ + id;
}
}
return id || null;
}
function getTransient(obj, key) {
assertDefined(getQObjectId(obj));
return obj[QOjectTransientsSymbol].get(key);
}
function setTransient(obj, key, value) {
assertDefined(getQObjectId(obj));
obj[QOjectTransientsSymbol].set(key, value);
return value;
}
function idToComponentSelector(id) {
id = id.replace(/([^\w\d])/g, (_, v) => '\\' + v);
return '[q\\:obj*=\\!' + id + ']';
}
/**
* Creates a proxy which notifies of any writes.
*/
function readWriteProxy(target, id) {
if (!target || typeof target !== 'object')
return target;
let proxy = proxyMap.get(target);
if (proxy)
return proxy;
proxy = new Proxy(target, new ReadWriteProxyHandler(id));
proxyMap.set(target, proxy);
return proxy;
}
const QOjectTargetSymbol = ':target:';
const QOjectTransientsSymbol = ':transients:';
const QObjectIdSymbol = ':id:';
const QObjectDocumentSymbol = ':doc:';
function unwrapProxy(proxy) {
if (proxy && typeof proxy == 'object') {
const value = proxy[QOjectTargetSymbol];
if (value)
return value;
}
return proxy;
}
function wrap(value) {
if (value && typeof value === 'object') {
const nakedValue = unwrapProxy(value);
if (nakedValue !== value) {
// already a proxy return;
return value;
}
const proxy = proxyMap.get(value);
return proxy ? proxy : readWriteProxy(value, generateId());
}
else {
return value;
}
}
class ReadWriteProxyHandler {
constructor(id) {
this.doc = null;
this.transients = null;
this.id = id;
}
get(target, prop) {
if (prop === QOjectTargetSymbol)
return target;
if (prop === QObjectIdSymbol)
return this.id;
if (prop === QOjectTransientsSymbol) {
return this.transients || (this.transients = new WeakMap());
}
const value = target[prop];
QObject_notifyRead(target);
return wrap(value);
}
set(target, prop, newValue) {
if (prop === QObjectDocumentSymbol) {
this.doc = newValue;
}
else if (prop == QObjectIdSymbol) {
this.id = newValue;
}
else {
const unwrappedNewValue = unwrapProxy(newValue);
const oldValue = target[prop];
if (oldValue !== unwrappedNewValue) {
target[prop] = unwrappedNewValue;
QObject_notifyWrite(this.id, this.doc, prop);
}
}
return true;
}
has(target, property) {
if (property === QOjectTargetSymbol)
return true;
return Object.prototype.hasOwnProperty.call(target, property);
}
ownKeys(target) {
return Object.getOwnPropertyNames(target);
}
}
const proxyMap = new WeakMap();
function generateId() {
return (
// TODO(misko): For now I have removed the data as I think it is overkill
// and makes the output unnecessarily big.
// new Date().getTime().toString(36) +
Math.round(Math.random() * Number.MAX_SAFE_INTEGER).toString(36));
}
// TODO(misko): need full object parsing /serializing
const JSON_OBJ_PREFIX = '\u0010';
const ATTR_OBJ_PREFIX = '*';
function qJsonStringify(obj, map) {
if (obj == undefined)
return String(obj);
if (typeof obj == 'number')
return String(obj);
if (typeof obj == 'boolean')
return String(obj);
const id = getQObjectId(obj);
if (id) {
map && map.set(id, obj);
return ATTR_OBJ_PREFIX + id;
}
if (typeof obj == 'string') {
const ch = obj.charCodeAt(0);
if (isDash(ch) || isDigit(ch) || isObj(ch) || isReserved(obj) || containsEscape(obj)) {
return "'" + obj.replace(/'/g, "\\'").replace(/\//g, '\\') + "'";
}
return obj;
}
return JSON.stringify(obj, function (key, value) {
const id = getQObjectId(value);
if (id) {
assertDefined(map);
map && map.set(id, value);
return JSON_OBJ_PREFIX + id;
}
return value;
});
}
function qJsonParse(txt, map) {
if (txt == '')
return '';
if (txt == 'null')
return null;
if (txt == 'undefined')
return undefined;
if (txt == 'false')
return false;
if (txt == 'true')
return true;
const ch = txt.charCodeAt(0);
if (isDigit(ch) || isDash(ch)) {
return Number(txt);
}
if (isAttrObj(ch)) {
const id = txt.substr(1); // QObject ID;
if (!map) {
// TODO(misko): better error / test
throw new Error('Map needs to be present when parsing QObjects');
}
const obj = map.get(id);
assertDefined(obj);
return obj;
}
if (isQuote(ch)) {
return txt.substring(1, txt.length - 1).replace(/\\(.)/, (v) => v);
}
if (isObj(ch)) {
return JSON.parse(txt, function (key, value) {
if (typeof value == 'string' && isJsonObj(value.charCodeAt(0))) {
if (!map) {
// TODO(misko): better error / test
throw new Error('Map needs to be present when parsing QObjects');
}
value = map.get(value.substr(1));
assertDefined(value);
}
return value;
});
}
return txt;
}
function qDeflate(obj, map) {
if (obj && typeof obj === 'object') {
let id = getQObjectId(obj);
if (!id) {
obj = qObject(obj);
id = getQObjectId(obj);
}
map.set(id, obj);
return JSON_OBJ_PREFIX + id;
}
return obj;
}
function qInflate(obj, map) {
if (typeof obj === 'string' && obj.charAt(0) === JSON_OBJ_PREFIX) {
const prefix = obj.charAt(1);
if (prefix == "#" /* ELEMENT_ID_PREFIX */ ||
prefix == "&" /* ELEMENT_ID_Q_PROPS_PREFIX */) {
const id = obj.substring(2);
const selector = "[q\\:id=\"{}\"]" /* ELEMENT_ID_SELECTOR */.replace('{}', id);
const element = map.element;
const ourElement = element.closest(selector) ||
element.querySelector(selector) ||
element.ownerDocument.querySelector(selector);
if (!ourElement) {
// TODO(misko): centralize
throw new Error(`Q-ERROR: Element with '${selector}' can not be located.`);
}
return prefix == "&" /* ELEMENT_ID_Q_PROPS_PREFIX */
? getProps(ourElement)
: ourElement;
}
else {
const id = obj.substring(1);
const ref = map.get(id);
if (!ref) {
// TODO(misko): centralize
throw new Error(`Q-ERROR: Unable to located object with id '${id}'.`);
}
return ref;
}
}
return obj;
}
function isDash(ch) {
return ch == '-'.charCodeAt(0);
}
function isObj(ch) {
return ch == '['.charCodeAt(0) || ch == '{'.charCodeAt(0);
}
function isQuote(ch) {
return ch == "'".charCodeAt(0);
}
function isDigit(ch) {
return '0'.charCodeAt(0) <= ch && ch <= '9'.charCodeAt(0);
}
function isAttrObj(ch) {
return ch == ATTR_OBJ_PREFIX.charCodeAt(0);
}
function isJsonObj(ch) {
return ch == JSON_OBJ_PREFIX.charCodeAt(0);
}
function isReserved(obj) {
return obj === 'null' || obj === 'undefined' || obj == 'true' || obj == 'false';
}
function containsEscape(obj) {
return obj.indexOf("'") != -1 || obj.indexOf('\\') != -1;
}
function QStore_hydrate(doc) {
const script = doc.querySelector('script[type="qwik/json"]');
let map = null;
doc.qDehydrate = () => QStore_dehydrate(doc);
if (script) {
script.parentElement.removeChild(script);
map = JSON.parse(script.textContent || '{}');
reviveQObjects(map);
reviveNestedQObjects(map, map);
}
return map;
}
/**
* Serialize the current state of the application into DOM
*
* @param doc
*/
function QStore_dehydrate(doc) {
const map = {};
// Find all Elements which have qObjects attached to them
doc.querySelectorAll('[q\\:obj]').forEach((node) => {
const props = getProps(node);
const qMap = props.__qRefs__;
clearQProps(node);
assertDefined(qMap);
qMap.forEach((v, k) => {
map[k] = v.obj;
collectQObjects(v, new Set(), (k, v) => (map[k] = v));
});
});
// Serialize
const script = doc.createElement('script');
script.setAttribute('type', 'qwik/json');
script.textContent = JSON.stringify(map, function (key, value) {
if (this === map)
return value;
if (key.startsWith('__'))
return undefined;
const id = getQObjectId(value);
if (id)
return JSON_OBJ_PREFIX + id;
return value;
}, qDev ? ' ' : undefined);
doc.body.appendChild(script);
clearQPropsMap(doc);
}
function reviveQObjects(map) {
for (const key in map) {
if (Object.prototype.hasOwnProperty.call(map, key)) {
const value = map[key];
map[key] = _restoreQObject(value, key);
}
}
}
function reviveNestedQObjects(obj, map) {
if (obj && typeof obj == 'object') {
if (Array.isArray(obj)) {
for (let i = 0; i < obj.length; i++) {
const value = obj[i];
if (typeof value == 'string' && value.startsWith(JSON_OBJ_PREFIX)) {
obj[i] = map[value.substring(JSON_OBJ_PREFIX.length)];
}
else {
reviveNestedQObjects(value, map);
}
}
}
else {
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
const value = obj[key];
if (typeof value == 'string' && value.startsWith(JSON_OBJ_PREFIX)) {
obj[key] = map[value.substring(JSON_OBJ_PREFIX.length)];
}
else {
reviveNestedQObjects(value, map);
}
}
}
}
}
}
function collectQObjects(obj, seen, foundFn) {
if (obj && typeof obj == 'object') {
if (seen.has(obj))
return;
seen.add(obj);
if (Array.isArray(obj)) {
for (let i = 0; i < obj.length; i++) {
collectQObjects(obj[i], seen, foundFn);
}
}
else {
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
const value = obj[key];
const id = getQObjectId(value);
if (id)
foundFn(id, value);
collectQObjects(value, seen, foundFn);
}
}
}
}
}
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
const camelToKebabCase = new Map();
function fromCamelToKebabCase(text, includeFirst = false) {
if (typeof text != 'string')
return text;
const value = camelToKebabCase.get(text);
if (value != null)
return value;
let converted = '';
for (let x = 0; x < text.length; x++) {
const ch = text.charAt(x);
if (isUpperCase(ch)) {
converted += (x != 0 || includeFirst ? '-' : '') + ch.toLowerCase();
}
else {
converted += ch;
}
}
camelToKebabCase.set(text, converted);
return converted;
}
function isUpperCase(ch) {
return 'A' <= ch && ch <= 'Z';
}
const Q_OBJECT_ATTR = 'q:obj';
function updateSubscriptions(element, map, idSubscriptionSet) {
map.forEach((value, key) => {
const qObj = value.obj;
if (idSubscriptionSet.has(value.obj)) {
// do nothing; already subscribed
if (!value.isSub) {
setMapFacade(map, getQObjectId(qObj), qObj, element, true, 1);
}
}
else if (value.isSub) {
// Unsubscribe
value.isSub = false;
releaseRef(value, map, key);
}
idSubscriptionSet.delete(qObj);
});
idSubscriptionSet.forEach((qObj) => setMapFacade(map, getQObjectId(qObj), qObj, element, true, 1));
writeQObjAttr(element, map);
}
function writeQObjAttr(element, map) {
const list = [];
map.forEach((v, k) => {
if (v.isSub)
k = '!' + k;
v.count == 1 ? list.push(k) : list.push('#' + v.count, k);
});
if (list.length) {
element.setAttribute(Q_OBJECT_ATTR, list.join(' '));
}
else {
element.removeAttribute(Q_OBJECT_ATTR);
}
}
function newQObjectMap(element, map) {
return {
element: element,
forEach(fn) {
return map.forEach((v, k) => {
fn(v.obj, k);
});
},
get(key) {
const value = map.get(key);
return value === null || value === void 0 ? void 0 : value.obj;
},
set(key, qObj) {
if (!isDomId(key)) {
setMapFacade(map, key, qObj, element, false, 1);
writeQObjAttr(element, map);
}
},
};
}
function isDomId(key) {
const prefix = key.charAt(0);
return (prefix === "#" /* ELEMENT_ID_PREFIX */ ||
prefix === "&" /* ELEMENT_ID_Q_PROPS_PREFIX */);
}
function setMapFacade(map, key, qObj, element, subscribed, count) {
assertDefined(key);
let value = map.get(key);
if (qObj) {
QObject_addDoc(qObj, element.ownerDocument);
if (value) {
value.count += count;
value.isSub = value.isSub || subscribed;
}
else {
map.set(key, (value = { obj: qObj, count, isSub: subscribed }));
}
}
else {
if (value) {
value = releaseRef(value, map, key);
}
}
return value;
}
function releaseRef(value, map, key) {
value.count--;
if (value.count == 0) {
map.delete(key);
return undefined;
}
return value;
}
function loadObjectsFromState(element, storeMap) {
const getProps = newQProps(element);
const objs = element.getAttribute(Q_OBJECT_ATTR);
if (objs) {
const parts = objs.split(' ');
const qMap = getProps.__qRefs__;
let lastCount = 1;
parts.forEach((key) => {
if (key.startsWith('#')) {
lastCount = Number(key.substr(1));
}
else {
let isSubscribed = false;
if (key.startsWith('!')) {
key = key.substr(1);
isSubscribed = true;
}
const qObj = storeMap[key];
setMapFacade(qMap, key, qObj, element, isSubscribed, lastCount);
}
});
}
}
const ON_PREFIX = 'on:';
const ON_PREFIX_$ = 'on$:';
const ON_DOCUMENT_PREFIX = 'onDocument:';
const ON_DOCUMENT_PREFIX_$ = 'onDocument$:';
const ON_WINDOW_PREFIX = 'onWindow:';
const ON_WINDOW_PREFIX_$ = 'onWindow$:';
function isOnProp(prop) {
return (prop.startsWith(ON_PREFIX) ||
prop.startsWith(ON_DOCUMENT_PREFIX) ||
prop.startsWith(ON_WINDOW_PREFIX));
}
function isOn$Prop(prop) {
return (prop.startsWith(ON_PREFIX_$) ||
prop.startsWith(ON_DOCUMENT_PREFIX_$) ||
prop.startsWith(ON_WINDOW_PREFIX_$));
}
function isQrlFactory(value) {
return typeof value === 'function' && value.__brand__ === 'QRLFactory';
}
function qPropReadQRL(cache, map, prop) {
const existingQRLs = getExistingQRLs(cache, prop);
if (existingQRLs.length === 0)
return null;
return () => {
const context = getInvokeContext();
const qrls = getExistingQRLs(cache, prop);
return Promise.all(qrls.map(async (qrlOrPromise) => {
const qrl = await qrlOrPromise;
const qrlGuard = context.qrlGuard;
if (qrlGuard && !qrlGuard(qrl))
return;
if (!qrl.symbolRef) {
qrl.symbolRef = await qrlImport(cache.__element__, qrl);
}
context.qrl = qrl;
if (qrlGuard) {
return invokeWatchFn(cache.__element__, qrl);
}
else {
return useInvoke(context, qrl.symbolRef);
}
}));
};
}
function qPropWriteQRL(cache, map, prop, value) {
if (!value)
return;
prop = prop.replace('$:', ':');
if (typeof value == 'string') {
value = parseQRL(value);
}
const existingQRLs = getExistingQRLs(cache, prop);
if (Array.isArray(value)) {
value.forEach((value) => qPropWriteQRL(cache, map, prop, value));
}
else if (isQrl(value)) {
const capture = value.capture;
if (capture == null) {
// we need to serialize the lexical scope references
const captureRef = value.captureRef;
value.capture =
captureRef && captureRef.length ? captureRef.map((ref) => qDeflate(ref, map)) : EMPTY_ARRAY;
}
// Important we modify the array as it is cached.
for (let i = 0; i < existingQRLs.length; i++) {
const qrl = existingQRLs[i];
if (!isPromise(qrl) &&
qrl.canonicalChunk === value.canonicalChunk &&
qrl.symbol === value.symbol) {
existingQRLs.splice(i, 1);
i--;
}
}
existingQRLs.push(value);
}
else if (isQrlFactory(value)) {
if (existingQRLs.length === 0) {
// if we don't have any than we use the `qrlFactory` to create a QRLInternal
// (otherwise ignore the factory)
qPropWriteQRL(cache, map, prop, value(cache.__element__));
}
}
else if (isPromise(value)) {
const writePromise = value.then((qrl) => {
existingQRLs.splice(existingQRLs.indexOf(writePromise), 1);
qPropWriteQRL(cache, map, prop, qrl);
return qrl;
});
existingQRLs.push(writePromise);
}
else {
// TODO(misko): Test/better text
throw new Error(`Not QRLInternal: prop: ${prop}; value: ` + value);
}
const kebabProp = fromCamelToKebabCase(prop);
cache.__element__.setAttribute(kebabProp, serializeQRLs(existingQRLs, map));
}
function getExistingQRLs(cache, prop) {
if (prop in cache)
return cache[prop];
const kebabProp = fromCamelToKebabCase(prop);
const parts = [];
const element = cache.__element__;
(element.getAttribute(kebabProp) || '').split('\n').forEach((qrl) => {
if (qrl) {
parts.push(parseQRL(qrl, element));
}
});
return (cache[prop] = parts);
}
function serializeQRLs(existingQRLs, map) {
const element = map.element;
return existingQRLs
.map((qrl) => (isPromise(qrl) ? '' : stringifyQRL(qrl, element)))
.filter((v) => !!v)
.join('\n');
}
Error.stackTraceLimit = 9999;
// TODO(misko): For better debugger experience the getProps should never store Proxy, always naked objects to make it easier to traverse in the debugger.
const Q_IS_HYDRATED = '__isHydrated__';
const Q_PROP = 'qProps';
function hydrateIfNeeded(element) {
const doc = element.ownerDocument;
const isHydrated = doc[Q_IS_HYDRATED];
if (!isHydrated) {
doc[Q_IS_HYDRATED] = true;
const map = QStore_hydrate(element.ownerDocument);
if (map) {
doc.querySelectorAll(Q_OBJECT_ATTR_SELECTOR).forEach((element) => {
loadObjectsFromState(element, map);
});
}
}
}
function clearQPropsMap(doc) {
doc[Q_IS_HYDRATED] = undefined;
}
function clearQProps(element) {
element[Q_PROP] = undefined;
}
const Q_MAP = '__qMap__';
const Q_OBJECT_ATTR_SELECTOR = '[q\\:obj]';
const QProps_ = class QProps {
constructor(__element__, __qRefs__, __qMap__) {
this.__element__ = __element__;
this.__qRefs__ = __qRefs__;
this.__qMap__ = __qMap__;
this.__mutation__ = false;
this.__self__ = null;
}
};
function newQProps(element) {
const qObjRefMap = new Map();
const qObjMap = newQObjectMap(element, qObjRefMap);
const cache = new QProps_(element, qObjRefMap, qObjMap);
return (element[Q_PROP] = cache.__self__ =
new Proxy(cache, {
get: (target, prop) => {
if (typeof prop == 'string') {
if (prop === '__mutation__') {
const mutation = target.__mutation__;
target.__mutation__ = false;
return mutation;
}
else if (prop === '__qMap__') {
return target.__qMap__;
}
else if (prop == '__parent__') {
const parent = element.parentElement;
return parent && getProps(parent);
}
else if (isOnProp(prop)) {
return qPropReadQRL(cache, qObjMap, prop);
}
else if (prop === QObjectIdSymbol) {
const id = getQObjectId(element);
assertEqual(id.charAt(0), "#" /* ELEMENT_ID_PREFIX */);
return "&" /* ELEMENT_ID_Q_PROPS_PREFIX */ + id.substring(1);
}
if (prop in cache) {
return target[prop];
}
return (cache[prop] = readAttribute(element, qObjMap, prop));
}
},
set: (target, prop, value) => {
if (typeof prop == 'string') {
if (prop === 'children')
return true;
if (isOnProp(prop)) {
qPropWriteQRL(cache, qObjMap, prop, value);
}
else if (isOn$Prop(prop)) {
qPropWriteQRL(cache, qObjMap, prop.replace('$', ''), $(value));
}
else if (prop === ':subscriptions') {
updateSubscriptions(element, qObjRefMap, value);
}
else {
value = wrap(value);
const existingValue = prop in target
? target[prop]
: (target[prop] = readAttribute(element, qObjMap, prop));
/**
const qObjs = diff(existingValue, value);
if (qObjs) {
qObjs.forEach((id) => qObjMap.set(id, null!));
writeAttribute(element, qObjMap, prop, (target[prop] = value));
target.__mutation__ = true;
}
*/
if (value !== existingValue) {
const existingId = getQObjectId(existingValue);
existingId && qObjMap.set(existingId, null);
writeAttribute(element, qObjMap, prop, (target[prop] = value));
target.__mutation__ = true;
}
}
return true;
}
else {
// TODO(misko): Better error/test
throw new Error('Only string keys are supported');
}
},
}));
}
function readAttribute(element, map, propName) {
if (isOnProp(propName)) {
const attrName = fromCamelToKebabCase(propName.split(':')[1]);
const attrValue = element.getAttribute(attrName);
const listeners = [];
attrValue === null || attrValue === void 0 ? void 0 : attrValue.split('\n').forEach((qrl) => {
listeners.push(parseQRL(qrl));
});
return listeners;
}
else {
const attrName = fromCamelToKebabCase(propName);
const attrValue = element.getAttribute(attrName);
if (attrValue === null) {
return undefined;
}
else {
return qJsonParse(attrValue, map);
}
}
}
function writeAttribute(element, map, propName, value) {
let attrName = fromCamelToKebabCase(propName);
if (propName === 'class') {
element.setAttribute(propName, stringifyClassOrStyle(value, true));
}
else if (propName === 'style') {
element.setAttribute(propName, stringifyClassOrStyle(value, false));
}
else if (propName === 'innerHTML' || propName === 'innerText') {
element.setAttribute(attrName, '');
element[propName] = value;
}
else {
if (propName in element) {
// INPUT properties like `value` and `checked` are special because they can go out of sync
// between the attribute and what the user entered, so they have special treatment.
element[propName] = value;
if (value === true) {
value = '';
}
}
else if (LOWERCASE_PROP_TO_ATTR[propName] || propName.toLowerCase() in element) {
// JSX Prop "charSet" === HTML Attribute "charset"
// JSX Prop "autoComplete" === HTML Attribute "autocomplete"
attrName = propName.toLowerCase();
element[attrName] = value;
}
if (value === undefined || value === false) {
element.removeAttribute(attrName);
}
else {
element.setAttribute(attrName, qJsonStringify(value, map));
}
}
}
/**
* Special cases where a camelCase JSX prop should not be hyphenated html attribute
*/
const LOWERCASE_PROP_TO_ATTR = {
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta#attr-charset
charSet: 1,
};
function didQPropsChange(getProps) {
return getProps.__mutation__;
}
/**
* Turn an `Array` or object literal into a `class` or `style`
*
* @param obj `string`, `Array` or object literal
* @param isClass `true` if expecting `class` output
* @returns `string`
*/
function stringifyClassOrStyle(obj, isClass) {
if (obj == null)
return '';
if (typeof obj == 'object') {
let text = '';
let sep = '';
if (Array.isArray(obj)) {
if (!isClass) {
throw qError(601 /* Render_unsupportedFormat_obj_attr */, obj, 'style');
}
for (let i = 0; i < obj.length; i++) {
text += sep + obj[i];
sep = ' ';
}
}
else {
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
const value = obj[key];
text += isClass ? (value ? sep + key : '') : sep + key + ':' + value;
sep = isClass ? ' ' : ';';
}
}
}
return text;
}
return String(obj);
}
/**
* @public
*/
function getProps(element) {
hydrateIfNeeded(element);
let getProps = element[Q_PROP];
if (!getProps) {
getProps = newQProps(element);
}
return getProps;
}
/* eslint-disable */
/**
* @public
*/
function h(type, props, ...children) {
// Using legacy h() jsx transform and morphing it
// so it can use the modern vdom structure
// https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html
// https://www.typescriptlang.org/tsconfig#jsxImportSource
const normalizedProps = {
children: arguments.length > 2 ? flattenArray(children) : EMPTY_ARRAY,
};
let key;
let i;
for (i in props) {
if (i == 'key')
key = props[i];
else
normalizedProps[i] = props[i];
}
return new JSXNodeImpl(type, normalizedProps, key);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/lQ8v7fyhR-WD3b-2aRUpyw#useHostElement instead)
/**
* Retrieves the Host Element of the current component.
*
* NOTE: `useHostElement` method can only be used in the synchronous portion of the callback
* (before any `await` statements.)
*
* @public
*/
//
function useHostElement() {
const element = getInvokeContext().hostElement;
assertDefined(element);
return element;
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#onUnmount instead)
/**
* A lazy-loadable reference to a component's destroy hook.
*
* Invoked when the component is destroyed (removed from render tree).
*
* @public
*/
//
function onUnmount(unmountFn) {
throw new Error('IMPLEMENT: onUnmount' + unmountFn);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#onUnmount instead)
/**
* A lazy-loadable reference to a component's destroy hook.
*
* Invoked when the component is destroyed (removed from render tree).
*
* @public
*/
//
const onUnmount$ = implicit$FirstArg(onUnmount);
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#onResume instead)
/**
* A lazy-loadable reference to a component's on resume hook.
*
* The hook is eagerly invoked when the application resumes on the client. Because it is called
* eagerly, this allows the component to hydrate even if no user interaction has taken place.
*
* @public
*/
//
function onResume(resumeFn) {
throw new Error('IMPLEMENT: onRender' + resumeFn);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#onResume instead)
/**
* A lazy-loadable reference to a component's on resume hook.
*
* The hook is eagerly invoked when the application resumes on the client. Because it is called
* eagerly, this allows the component to hydrate even if no user interaction has taken place.
*
* @public
*/
//
const onResume$ = implicit$FirstArg(onResume);
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#onHydrate instead)
/**
* A lazy-loadable reference to a component's on hydrate hook.
*
* Invoked when the component's state is re-hydrated from serialization. This allows the
* component to do any work to re-activate itself.
*
* @public
*/
//
function onHydrate(hydrateFn) {
throw new Error('IMPLEMENT: onHydrate' + hydrateFn);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#onHydrate instead)
/**
* A lazy-loadable reference to a component's on hydrate hook.
*
* Invoked when the component's state is re-hydrated from serialization. This allows the
* component to do any work to re-activate itself.
*
* @public
*/
//
const onHydrate$ = implicit$FirstArg(onHydrate);
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#onDehydrate instead)
/**
* A lazy-loadable reference to a component's on dehydrate hook.
*
* Invoked when the component's state is being serialized (dehydrated) into the DOM. This allows
* the component to do last-minute clean-up before its state is serialized.
*
* Typically used with transient state.
*
* @public
*/
//
function onDehydrate(dehydrateFn) {
throw new Error('IMPLEMENT: onDehydrate' + dehydrateFn);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#onDehydrate instead)
/**
* A lazy-loadable reference to a component's on dehydrate hook.
*
* Invoked when the component's state is being serialized (dehydrated) into the DOM. This allows
* the component to do last-minute clean-up before its state is serialized.
*
* Typically used with transient state.
*
* @public
*/
//
const onDehydrate$ = implicit$FirstArg(onDehydrate);
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#on instead)
/**
* Register a listener on the current component's host element.
*
* Used to programmatically add event listeners. Useful from custom `use*` methods, which do not
* have access to the JSX.
*
* See: `on`, `onWindow`, `onDocument`.
*
* @public
*/
//
function on(event, eventFn) {
throw new Error('IMPLEMENT: on' + eventFn);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#onDocument instead)
/**
* Register a listener on `document`.
*
* Used to programmatically add event listeners. Useful from custom `use*` methods, which do not
* have access to the JSX.
*
* See: `on`, `onWindow`, `onDocument`.
*
* @public
*/
//
function onDocument(event, eventFn) {
throw new Error('IMPLEMENT: onDocument' + eventFn);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#onWindow instead)
/**
* Register a listener on `window`.
*
* Used to programmatically add event listeners. Useful from custom `use*` methods, which do not
* have access to the JSX.
*
* See: `on`, `onWindow`, `onDocument`.
*
* @public
*/
//
function onWindow(event, eventFn) {
throw new Error('IMPLEMENT: onWindow' + eventFn);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#useStyles instead)
/**
* @alpha
*/
//
function useStyles(styles) {
_useStyles(styles, false);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#useStyles instead)
/**
* @alpha
*/
//
const useStyles$ = implicit$FirstArg(useStyles);
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#withScopedStyles instead)
/**
* @alpha
*/
//
function withScopedStyles(styles) {
_useStyles(styles, true);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#withScopedStyles instead)
/**
* @alpha
*/
//
const withScopedStyles$ = implicit$FirstArg(withScopedStyles);
/**
* @public
*/
function component(onMount, options = {}) {
var _a;
const tagName = (_a = options.tagName) !== null && _a !== void 0 ? _a : 'div';
// Return a QComponent Factory function.
return function QComponent(props) {
const onRenderFactory = async (hostElement) => {
// Turn function into QRL
const onMountQrl = toQrlOrError(onMount);
const onMountFn = await resolveQrl(hostElement, onMountQrl);
const componentProps = Object.assign(getProps(hostElement), props);
const invokeCtx = newInvokeContext(hostElement);
return useInvoke(invokeCtx, onMountFn, componentProps);
};
onRenderFactory.__brand__ = 'QRLFactory';
return h(tagName, Object.assign({ 'on:qRender': onRenderFactory }, props));
};
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/c_nNpiLZSYugTU0c5JATJA#component instead)
/**
* Declare a Qwik component that can be used to create UI.
*
* Use `component` (and `component$`) to declare a Qwik component. A Qwik component is a special
* kind of component that allows the Qwik framework to lazy load and execute the component
* independently of other Qwik components as well as lazy load the component's life-cycle hooks
* and event handlers.
*
* Side note: You can also declare regular (standard JSX) components that will have standard
* synchronous behavior.
*
* Qwik component is a facade that describes how the component should be used without forcing the
* implementation of the component to be eagerly loaded. A minimum Qwik definition consists of:
*
* - Component `onMount` method, which needs to return an
* - `onRender` closure which constructs the component's JSX.
*
* ### Example:
*
* An example showing how to create a counter component:
*
* ```typescript
* export const Counter = component$((props: { value?: number; step?: number }) => {
* const state = createStore({ count: props.value || 0 });
* return $(() => (
*
* {state.count}
*
*
* ));
* });
* ```
*
* - `component$` is how a component gets declared.
* - `{ value?: number; step?: number }` declares the public (props) interface of the component.
* - `{ count: number }` declares the private (state) interface of the component.
* - `onMount` closure: is used to create the data store (see: `createStore`);
* - `onRender$`: is the required hook for rendering the component.
* - `$`: mark which parts of the component will be lazy-loaded. (see `$` for details.)
*
* The above can then be used like so:
*
* ```typescript
* export const OtherComponent = component$(() => {
* return $(() => );
* });
* ```
*
* See also: `component`, `onRender`, `onUnmount`, `onHydrate`, `onDehydrate`, `onHalt`,
* `onResume`, `on`, `onDocument`, `onWindow`, `useStyles`, `withScopedStyles`
*
* @param onMount - Initialization closure used when the component is first created.
* @param tagName - Optional components options. It can be used to set a custom tag-name to be
* used for the component's host element.
*
* @public
*/
//
function component$(onMount, options) {
return component($(onMount), options);
}
function resolveQrl(hostElement, onMountQrl) {
return onMountQrl.symbolRef
? Promise.resolve(onMountQrl.symbolRef)
: Promise.resolve(null).then(() => {
return qrlImport(hostElement, onMountQrl);
});
}
function _useStyles(styles, scoped) {
const styleQrl = toQrlOrError(styles);
const styleId = styleKey(styleQrl);
const hostElement = useHostElement();
if (scoped) {
hostElement.setAttribute("q:sstyle" /* ComponentScopedStyles */, styleId);
}
useWaitOn(qrlImport(hostElement, styleQrl).then((styleText) => {
const document = hostElement.ownerDocument;
const head = document.querySelector('head');
if (head && !head.querySelector(`style[q\\:style="${styleId}"]`)) {
const style = document.createElement('style');
style.setAttribute('q:style', styleId);
style.textContent = scoped ? styleText.replace(/�/g, styleId) : styleText;
head.appendChild(style);
}
}));
}
function _bubble(eventType, payload) {
let props = getProps(useHostElement());
payload = Object.assign({ type: eventType }, payload);
const eventName = 'on:' + eventType;
while (props) {
const listener = props[eventName];
listener && useInvoke(newInvokeContext(props.__element__, payload), listener);
props = props.__parent__;
}
}
/**
* @public
*/
function bubble(eventType, payload) {
return _bubble(eventType, payload || {});
}
//TODO(misko): Add public DOCS.
//TODO(misko): Rename to dehydrate
/**
* @public
*/
function dehydrate(document) {
QStore_dehydrate(document);
}
function useProps() {
const ctx = getInvokeContext();
let props = ctx.props;
if (!props) {
props = ctx.props = getProps(useHostElement());
}
return props;
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/_Kl9br9tT8OB-1Dv8uR4Kg#onWatch instead)
/**
* Reruns the `watchFn` when the observed inputs change.
*
* Use `onWatch` to observe changes on a set of inputs, and then re-execute the `watchFn` when
* those inputs change.
*
* The `watchFn` only executes if the observed inputs change. To observe the inputs use the `obs`
* function to wrap property reads. This creates subscriptions which will trigger the `watchFn`
* to re-run.
*
* See: `Observer`
*
* @public
*
* ## Example
*
* The `onWatch` function is used to observe the `state.count` property. Any changes to the
* `state.count` cause the `watchFn` to execute which in turn updates the `state.doubleCount` to
* the double of `state.count`.
*
* ```typescript
* export const MyComp = component$(() => {
* const store = createStore({ count: 0, doubleCount: 0 });
* onWatch$((obs) => {
* store.doubleCount = 2 * obs(store).count;
* });
* return $(() => (
*
*
* {store.count} / {store.doubleCount}
*
*
*
* ));
* });
* ```
*
*
* @param watch - Function which should be re-executed when changes to the inputs are detected
* @public
*/
//
function onWatch(watchFn) {
registerOnWatch(useHostElement(), useProps(), watchFn);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/_Kl9br9tT8OB-1Dv8uR4Kg#onWatch instead)
/**
* Reruns the `watchFn` when the observed inputs change.
*
* Use `onWatch` to observe changes on a set of inputs, and then re-execute the `watchFn` when
* those inputs change.
*
* The `watchFn` only executes if the observed inputs change. To observe the inputs use the `obs`
* function to wrap property reads. This creates subscriptions which will trigger the `watchFn`
* to re-run.
*
* See: `Observer`
*
* @public
*
* ## Example
*
* The `onWatch` function is used to observe the `state.count` property. Any changes to the
* `state.count` cause the `watchFn` to execute which in turn updates the `state.doubleCount` to
* the double of `state.count`.
*
* ```typescript
* export const MyComp = component$(() => {
* const store = createStore({ count: 0, doubleCount: 0 });
* onWatch$((obs) => {
* store.doubleCount = 2 * obs(store).count;
* });
* return $(() => (
*
*
* {store.count} / {store.doubleCount}
*
*
*
* ));
* });
* ```
*
*
* @param watch - Function which should be re-executed when changes to the inputs are detected
* @public
*/
//
const onWatch$ = implicit$FirstArg(onWatch);
/**
* Use to render asynchronous (`Promise`) values.
*
* A `Promise` does not allow a synchronous examination of its state. For this reason
* `` provides a mechanism to render pending, resolved and error state of a `Promise`.
* `` provides that mechanism by registering a `then` method with the `Promise` and
* providing callbacks hooks for `pending`, `resolved` and `rejected` state of the promise.
*
* Additionally, `` automatically re-renders the portion of the view when the status
* of the `Promise` changes.
*
* `` provides three callbacks:
* - `onPending`: invoked initially to provide a way for the template to provide output while
* waiting for the `promise` to resolve.
* - `onResolved`: invoked when the `promise` is `resolved` allowing the template to generate
* output using the `resolved` value.
* - `onError`: invoked when the `promise` is `rejected` allowing the template to generate
* error output describing the problem.
*
* The `` can be used in two ways, which are semantically equivalent and are provided
* based on the developer needs/preferences.
*
* ### Using multiple callbacks
*
* ```typescript
* loading...}
* onResolved={(value) => {value}}
* onError={(rejection) =>
{rejection}
}
* />
* ```
*
* ### Using single callbacks
*
* ```typescript
*
* {(response) => {
* if (response.isPending) return loading...;
* if (response.isResolved) return {response.value};
* if (response.isRejected) return
{response.rejection}
;
* }}
*
* ```
*
* @param onPending - invoked initially to provide a way for the template to provide output while
* waiting for the `promise` to resolve.
* @param onResolved - invoked when the `promise` is `resolved` allowing the template to generate
* output using the `resolved` value.
* @param onError - invoked when the `promise` is `rejected` allowing the template to generate
* error output describing the problem.
* @param children - a single callback function for `onPending`, `onResolved` and `onError`.
* (Use either `children` or `onPending`, `onResolved` and `onError`, but not both.)
* See "Using multiple callbacks" vs "Using single callbacks" above.
*
* @public
*/
function Async(props) {
// TODO(misko): implement onPending/onResolved/onError
if (!('children' in props)) {
throw new Error('IMPLEMENT');
}
const children = [props.children].flat()[0];
const renderFn = typeof children == 'function' ? children : null;
const promiseValue = {
isPending: true,
isResolved: false,
value: undefined,
isRejected: false,
rejection: undefined,
};
let pending;
const jsxPromise = new Promise((resolve, reject) => {
pending = renderFn && renderFn(promiseValue);
Promise.resolve(props.resolve).then((value) => {
promiseValue.isPending = false;
promiseValue.isResolved = true;
promiseValue.value = value;
return resolve(renderFn && renderFn(promiseValue));
}, (error) => {
promiseValue.isPending = false;
promiseValue.isRejected = true;
promiseValue.rejection = error;
return reject(renderFn && renderFn(promiseValue));
});
});
jsxPromise.whilePending = pending;
return jsxPromise;
}
/**
* Render JSX.
*
* Use this method to render JSX. This function does reconciling which means
* it always tries to reuse what is already in the DOM (rather then destroy and
* recrate content.)
*
* @param parent - Element which will act as a parent to `jsxNode`. When
* possible the rendering will try to reuse existing nodes.
* @param jsxNode - JSX to render
* @public
*/
async function render(parent, jsxNode) {
// If input is not JSX, convert it
if (!isJSXNode(jsxNode)) {
jsxNode = jsx(jsxNode, null);
}
const renderQueue = [];
let firstChild = parent.firstChild;
while (firstChild && firstChild.nodeType > 8 /* COMMENT_NODE */) {
firstChild = firstChild.nextSibling;
}
const cursor = cursorForParent(parent);
visitJsxNode(null, renderQueue, cursor, jsxNode);
return flattenPromiseTree(renderQueue);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/lQ8v7fyhR-WD3b-2aRUpyw#useEvent instead)
/**
* Retrieves the current event which triggered the action.
*
* NOTE: The `useEvent` method can only be used in the synchronous portion of the callback
* (before any `await` statements.)
*
* @public
*/
//
function useEvent(expectEventType) {
const event = getInvokeContext().event;
expectEventType && assertEqual(event.type, expectEventType);
return event;
}
function useQRL() {
return getInvokeContext().qrl || null;
}
function useURL() {
const url = getInvokeContext().url;
if (!url) {
// TODO(misko): centralize
throw new Error('Q-ERROR: no URL is associated with the execution context');
}
return url;
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/lQ8v7fyhR-WD3b-2aRUpyw#useLexicalScope instead)
/**
* Used by the Qwik Optimizer to restore the lexical scoped variables.
*
* This method should not be present in the application source code.
*
* NOTE: `useLexicalScope` method can only be used in the synchronous portion of the callback
* (before any `await` statements.)
*
* @public
*/
//
function useLexicalScope() {
const qrl = useQRL() || parseQRL(decodeURIComponent(String(useURL())));
if (qrl.captureRef == null) {
const props = getProps(useHostElement());
const qMap = props[Q_MAP];
assertDefined(qrl.capture);
qrl.captureRef = qrl.capture.map((obj) => qInflate(obj, qMap));
}
return qrl.captureRef;
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/lQ8v7fyhR-WD3b-2aRUpyw#createStore instead)
/**
* Creates a object that Qwik can track across serializations.
*
* Use `createStore` to create state for your application. The return object is a proxy which has
* a unique ID. The ID of the object is used in the `QRL`s to refer to the store.
*
* ## Example
*
* Example showing how `createStore` is used in Counter example to keep track of count.
*
* ```typescript
* export const Counter = component$(() => {
* const store = createStore({ count: 0 });
* return $(() => );
* });
* ```
*
* @public
*/
//
function createStore(initialState) {
return qObject(initialState);
}
//
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!! (edit https://hackmd.io/lQ8v7fyhR-WD3b-2aRUpyw#useTransient instead)
/**
* @public
*/
//
function useTransient(obj, factory, ...args) {
const existing = getTransient(obj, factory);
return existing || setTransient(obj, factory, factory.apply(obj, args));
}
/**
* @license
* Copyright Builder.io, Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/BuilderIO/qwik/blob/main/LICENSE
*/
/**
* @alpha
*/
const version = "0.0.16-dev20220215101413";
exports.$ = $;
exports.Async = Async;
exports.Fragment = Fragment;
exports.Host = Host;
exports.Slot = Slot;
exports.bubble = bubble;
exports.component = component;
exports.component$ = component$;
exports.createStore = createStore;
exports.dehydrate = dehydrate;
exports.getPlatform = getPlatform;
exports.getProps = getProps;
exports.h = h;
exports.implicit$FirstArg = implicit$FirstArg;
exports.jsx = jsx;
exports.jsxDEV = jsx;
exports.jsxs = jsx;
exports.notifyRender = notifyRender;
exports.on = on;
exports.onDehydrate = onDehydrate;
exports.onDehydrate$ = onDehydrate$;
exports.onDocument = onDocument;
exports.onHydrate = onHydrate;
exports.onHydrate$ = onHydrate$;
exports.onResume = onResume;
exports.onResume$ = onResume$;
exports.onUnmount = onUnmount;
exports.onUnmount$ = onUnmount$;
exports.onWatch = onWatch;
exports.onWatch$ = onWatch$;
exports.onWindow = onWindow;
exports.qrl = qrl;
exports.qrlImport = qrlImport;
exports.render = render;
exports.setPlatform = setPlatform;
exports.useEvent = useEvent;
exports.useHostElement = useHostElement;
exports.useLexicalScope = useLexicalScope;
exports.useStyles = useStyles;
exports.useStyles$ = useStyles$;
exports.useTransient = useTransient;
exports.version = version;
exports.withScopedStyles = withScopedStyles;
exports.withScopedStyles$ = withScopedStyles$;
//# sourceMappingURL=core.cjs.map