UNPKG

ember-source

Version:

A JavaScript framework for creating ambitious web applications

178 lines (173 loc) 5.16 kB
import './debug-to-string-BsFOvUtQ.js'; import { i as isDict, e as expect } from './collections-B8me-ZlQ.js'; import { isDevelopingApp } from '@embroider/macros'; import { setProp, getProp } from '../@glimmer/global-context/index.js'; import { CONSTANT_TAG, INITIAL, validateTag, track, valueForTag, consumeTag } from '../@glimmer/validator/index.js'; const REFERENCE = Symbol('REFERENCE'); const CONSTANT = 0; const COMPUTE = 1; const UNBOUND = 2; const INVOKABLE = 3; ////////// class ReferenceImpl { [REFERENCE]; tag = null; lastRevision = INITIAL; lastValue; children = null; compute = null; update = null; debugLabel; constructor(type) { this[REFERENCE] = type; } } function createPrimitiveRef(value) { const ref = new ReferenceImpl(UNBOUND); ref.tag = CONSTANT_TAG; ref.lastValue = value; if (isDevelopingApp()) { ref.debugLabel = String(value); } return ref; } const UNDEFINED_REFERENCE = createPrimitiveRef(undefined); const NULL_REFERENCE = createPrimitiveRef(null); const TRUE_REFERENCE = createPrimitiveRef(true); const FALSE_REFERENCE = createPrimitiveRef(false); function createConstRef(value, debugLabel) { const ref = new ReferenceImpl(CONSTANT); ref.lastValue = value; ref.tag = CONSTANT_TAG; if (isDevelopingApp()) { ref.debugLabel = debugLabel; } return ref; } function createUnboundRef(value, debugLabel) { const ref = new ReferenceImpl(UNBOUND); ref.lastValue = value; ref.tag = CONSTANT_TAG; if (isDevelopingApp()) { ref.debugLabel = debugLabel; } return ref; } function createComputeRef(compute, update = null, debugLabel = 'unknown') { const ref = new ReferenceImpl(COMPUTE); ref.compute = compute; ref.update = update; if (isDevelopingApp()) { ref.debugLabel = `(result of a \`${debugLabel}\` helper)`; } return ref; } function createReadOnlyRef(ref) { if (!isUpdatableRef(ref)) return ref; return createComputeRef(() => valueForRef(ref), null, ref.debugLabel); } function isInvokableRef(ref) { return ref[REFERENCE] === INVOKABLE; } function createInvokableRef(inner) { const ref = createComputeRef(() => valueForRef(inner), value => updateRef(inner, value)); ref.debugLabel = inner.debugLabel; ref[REFERENCE] = INVOKABLE; return ref; } function isConstRef(_ref) { const ref = _ref; return ref.tag === CONSTANT_TAG; } function isUpdatableRef(_ref) { const ref = _ref; return ref.update !== null; } function valueForRef(_ref) { const ref = _ref; let { tag } = ref; if (tag === CONSTANT_TAG) { return ref.lastValue; } const { lastRevision } = ref; let lastValue; if (tag === null || !validateTag(tag, lastRevision)) { const { compute } = ref; const newTag = track(() => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme lastValue = ref.lastValue = compute(); }, isDevelopingApp() && ref.debugLabel); tag = ref.tag = newTag; ref.lastRevision = valueForTag(newTag); } else { lastValue = ref.lastValue; } consumeTag(tag); return lastValue; } function updateRef(_ref, value) { const ref = _ref; const update = expect(ref.update); update(value); } function childRefFor(_parentRef, path) { const parentRef = _parentRef; const type = parentRef[REFERENCE]; let children = parentRef.children; let child; if (children === null) { children = parentRef.children = new Map(); } else { const next = children.get(path); if (next) return next; } if (type === UNBOUND) { const parent = valueForRef(parentRef); if (isDict(parent)) { child = createUnboundRef(parent[path], isDevelopingApp() && `${parentRef.debugLabel}.${path}`); } else { child = UNDEFINED_REFERENCE; } } else { child = createComputeRef(() => { const parent = valueForRef(parentRef); if (isDict(parent)) { return getProp(parent, path); } }, val => { const parent = valueForRef(parentRef); if (isDict(parent)) { return setProp(parent, path, val); } }); if (isDevelopingApp()) { child.debugLabel = `${parentRef.debugLabel}.${path}`; } } children.set(path, child); return child; } function childRefFromParts(root, parts) { let reference = root; for (const part of parts) { reference = childRefFor(reference, part); } return reference; } let createDebugAliasRef; if (isDevelopingApp()) { createDebugAliasRef = (debugLabel, inner) => { const update = isUpdatableRef(inner) ? value => updateRef(inner, value) : null; const ref = createComputeRef(() => valueForRef(inner), update); ref[REFERENCE] = inner[REFERENCE]; ref.debugLabel = debugLabel; return ref; }; } export { FALSE_REFERENCE as F, NULL_REFERENCE as N, REFERENCE as R, TRUE_REFERENCE as T, UNDEFINED_REFERENCE as U, childRefFromParts as a, createComputeRef as b, childRefFor as c, createConstRef as d, createDebugAliasRef as e, createInvokableRef as f, createPrimitiveRef as g, createReadOnlyRef as h, createUnboundRef as i, isConstRef as j, isInvokableRef as k, isUpdatableRef as l, updateRef as u, valueForRef as v };