@endorphinjs/template-runtime
Advanced tools
Comparing version 0.1.9 to 0.1.10
@@ -28,6 +28,6 @@ 'use strict'; | ||
* @param {*} [ctx] | ||
* @returns {boolean} Returns `true` if data was updated | ||
* @returns {number} Returns `1` if data was updated, `0` otherwise | ||
*/ | ||
function finalizeItems(items, change, ctx) { | ||
let updated = false; | ||
let updated = 0; | ||
const { cur, prev } = items; | ||
@@ -38,3 +38,3 @@ | ||
if (curValue !== prevValue) { | ||
updated = true; | ||
updated = 1; | ||
change(name, prevValue, prev[name] = curValue, ctx); | ||
@@ -238,3 +238,5 @@ } | ||
function text(value) { | ||
return document.createTextNode(textValue(value)); | ||
const node = document.createTextNode(textValue(value)); | ||
node['$value'] = value; | ||
return node; | ||
} | ||
@@ -246,12 +248,12 @@ | ||
* @param {*} value | ||
* @param {*} prevValue | ||
* @return {*} New value used in text node | ||
* @returns {number} Returns `1` if text was updated, `0` otherwise | ||
*/ | ||
function updateText(node, value, prevValue) { | ||
if (value !== prevValue) { | ||
function updateText(node, value) { | ||
if (value !== node['$value']) { | ||
node.nodeValue = textValue(value); | ||
return value; | ||
node['$value'] = value; | ||
return 1; | ||
} | ||
return prevValue; | ||
return 0; | ||
} | ||
@@ -291,3 +293,3 @@ | ||
* @param {Injector} injector | ||
* @returns {boolean} Update status | ||
* @returns {number} Update status | ||
*/ | ||
@@ -341,5 +343,8 @@ function finalizeEvents(injector) { | ||
* @param {*} value | ||
* @return {number} Update status. Always returns `0` since actual attribute value | ||
* is defined in `finalizeAttributes()` | ||
*/ | ||
function setAttribute(injector, name, value) { | ||
injector.attributes.cur[name] = value; | ||
return 0; | ||
} | ||
@@ -406,35 +411,11 @@ | ||
* @param {Injector} injector | ||
* @return {number} Update status | ||
* @return {number} | ||
*/ | ||
function finalizeAttributes(injector) { | ||
return finalizeItems(normalize(injector).attributes, changeAttribute, injector.parentNode); | ||
} | ||
/** | ||
* Applies pending attributes changes to injector’s host element as props | ||
* @param {Injector} injector | ||
* @param {Object} [data] Additional props (most likely static ones) | ||
* @return {Changes} Updated props, if any | ||
*/ | ||
function finalizeProps(injector, data) { | ||
const changes = data || obj(); | ||
const updated = finalizeItems(normalize(injector).attributes, changeProp, changes); | ||
if (data || updated) { | ||
return /** @type {Component} */ (injector.parentNode).setProps(changes); | ||
} | ||
} | ||
/** | ||
* Normalizes attributes in given injector | ||
* @param {Injector} injector | ||
*/ | ||
function normalize(injector) { | ||
const { attributes } = injector; | ||
const className = attributes.cur['class']; | ||
if (isDefined(className)) { | ||
attributes.cur['class'] = normalizeClassName(className); | ||
if (isDefined(attributes.cur['class'])) { | ||
attributes.cur['class'] = normalizeClassName(attributes.cur['class']); | ||
} | ||
return injector; | ||
return finalizeItems(attributes, changeAttribute, injector.parentNode); | ||
} | ||
@@ -478,13 +459,2 @@ | ||
/** | ||
* Callback for changing attribute value | ||
* @param {string} name | ||
* @param {*} prevValue | ||
* @param {*} newValue | ||
* @param {object} changes | ||
*/ | ||
function changeProp(name, prevValue, newValue, changes) { | ||
changes[name] = newValue; | ||
} | ||
/** | ||
* Enters new variable scope context | ||
@@ -589,3 +559,5 @@ * @param {Component} host | ||
}; | ||
host.componentModel.slots[name] = mountBlock(host, createInjector(elem), blockEntry); | ||
const { slots } = host.componentModel; | ||
slots[name] = mountBlock(host, createInjector(elem), blockEntry); | ||
} | ||
@@ -598,6 +570,13 @@ | ||
function updateSlots(host) { | ||
const { slots } = host.componentModel; | ||
const { slots, slotStatus, input } = host.componentModel; | ||
for (const name in slots) { | ||
updateBlock(slots[name]); | ||
} | ||
for (const name in slotStatus) { | ||
if (slotStatus[name]) { | ||
runHook(host, 'didSlotUpdate', [name, input.slots[name]]); | ||
slotStatus[name] = 0; | ||
} | ||
} | ||
} | ||
@@ -640,2 +619,17 @@ | ||
/** | ||
* Marks slot update status | ||
* @param {Component} component | ||
* @param {string} slotName | ||
* @param {number} status | ||
*/ | ||
function markSlotUpdate(component, slotName, status) { | ||
const { slotStatus } = component.componentModel; | ||
if (slotName in slotStatus) { | ||
slotStatus[slotName] |= status; | ||
} else { | ||
slotStatus[slotName] = status; | ||
} | ||
} | ||
/** | ||
* Creates internal lightweight Endorphin component with given definition | ||
@@ -666,5 +660,5 @@ * @param {string} name | ||
element.refs = {}; | ||
element.props = assign(obj(), defaultProps); | ||
element.props = obj(defaultProps); | ||
element.state = collectData(definition, 'state'); | ||
element.setProps = function setProps(value, silent) { | ||
element.setProps = function setProps(value) { | ||
const { componentModel } = element; | ||
@@ -674,20 +668,9 @@ | ||
// check if `componentModel` is available | ||
if (!componentModel || value == null) { | ||
return; | ||
if (value != null && componentModel && componentModel.mounted) { | ||
const changes = setPropsInternal(element, element.props, obj(value)); | ||
changes && renderNext(element, changes); | ||
} | ||
value = fillDefaults(value, defaultProps); | ||
const changes = changed(value, element.props); | ||
if (changes) { | ||
assign(element.props, value); | ||
representProps(element, value); | ||
if (!silent && componentModel.mounted) { | ||
renderNext(element, changes); | ||
} | ||
} | ||
return changes; | ||
}; | ||
element.setState = function setState(value, silent) { | ||
element.setState = function setState(value) { | ||
const { componentModel } = element; | ||
@@ -697,3 +680,3 @@ | ||
// check if `componentModel` is available | ||
if (componentModel && value != null && changed(value, element.state)) { | ||
if (value != null && componentModel && hasChanges(element.state, value)) { | ||
assign(element.state, value); | ||
@@ -706,3 +689,3 @@ | ||
// on next tick | ||
if (!silent && componentModel.mounted && !componentModel.rendering) { | ||
if (componentModel.mounted && !componentModel.rendering) { | ||
scheduleRender(element); | ||
@@ -717,3 +700,3 @@ } | ||
if (!element.componentView) { | ||
element.componentView = definition.componentView ? definition.componentView(element, host) : element; | ||
element.componentView = element; | ||
} | ||
@@ -737,2 +720,3 @@ | ||
slots: obj(), | ||
slotStatus: obj(), | ||
mounted: false, | ||
@@ -742,3 +726,4 @@ rendering: false, | ||
queued: null, | ||
events: attachStaticEvents(element, definition) | ||
events: attachStaticEvents(element, definition), | ||
defaultProps | ||
}; | ||
@@ -756,12 +741,25 @@ | ||
*/ | ||
function mountComponent(elem$$1, initialProps = obj()) { | ||
function mountComponent(elem$$1, initialProps) { | ||
const { componentModel } = elem$$1; | ||
const { input, definition } = componentModel; | ||
const { input, definition, defaultProps } = componentModel; | ||
let changes = setPropsInternal(elem$$1, obj(), assign(obj(defaultProps), initialProps)); | ||
const runtimeChanges = setPropsInternal(elem$$1, input.attributes.prev, input.attributes.cur); | ||
if (changes && runtimeChanges) { | ||
assign(changes, runtimeChanges); | ||
} else if (runtimeChanges) { | ||
changes = runtimeChanges; | ||
} | ||
const args = [changes || {}]; | ||
finalizeEvents(input); | ||
finalizeProps(input, initialProps); | ||
const changes = changed(elem$$1.props, obj()); | ||
const args = [changes || {}]; | ||
componentModel.rendering = true; | ||
// Notify slot status | ||
for (const p in input.slots) { | ||
runHook(elem$$1, 'didSlotUpdate', [p, input.slots[p]]); | ||
} | ||
if (changes) { | ||
@@ -787,8 +785,9 @@ runHook(elem$$1, 'didChange', args); | ||
function updateComponent(elem$$1) { | ||
const { componentModel } = elem$$1; | ||
const { input } = elem$$1.componentModel; | ||
const changes = setPropsInternal(elem$$1, input.attributes.prev, input.attributes.cur); | ||
finalizeEvents(input); | ||
updateSlots(elem$$1); | ||
finalizeEvents(componentModel.input); | ||
const changes = finalizeProps(componentModel.input); | ||
if (changes) { | ||
renderComponent(elem$$1, changes); | ||
renderNext(elem$$1, changes); | ||
} | ||
@@ -908,16 +907,2 @@ } | ||
/** | ||
* Represents given props as attribute values in `elem` | ||
* @param {Element} elem | ||
* @param {object} props | ||
*/ | ||
function representProps(elem$$1, props) { | ||
for (const p in props) { | ||
// Do not represent passed partials: these are internals | ||
if (!/^partial:/.test(p)) { | ||
representAttributeValue(elem$$1, p.replace(/[A-Z]/g, kebabCase), props[p]); | ||
} | ||
} | ||
} | ||
/** | ||
* Collects and attaches static event listeners to `component` from given `definition` | ||
@@ -986,23 +971,56 @@ * @param {Component} component | ||
/** | ||
* Fills any `null` or `undefined` item in `data` with value from `defaults` | ||
* @param {Object} data | ||
* @param {Object} defaults | ||
* @returns {Object} | ||
* @param {Component} component | ||
* @param {Object} prevProps | ||
* @param {Object} nextProps | ||
* @returns {Changes} | ||
*/ | ||
function fillDefaults(data, defaults) { | ||
if (data) { | ||
const result = obj(); | ||
for (const p in data) { | ||
if (data[p] == null && p in defaults) { | ||
result[p] = defaults[p]; | ||
} else if (data[p] !== result[p]) { | ||
// Skip data from prototype | ||
result[p] = data[p]; | ||
function setPropsInternal(component, prevProps, nextProps) { | ||
/** @type {Changes} */ | ||
const changes = {}; | ||
let hasChanges = false; | ||
const { props } = component; | ||
const { defaultProps } = component.componentModel; | ||
for (const p in nextProps) { | ||
const prev = prevProps[p]; | ||
let current = nextProps[p]; | ||
if (current == null) { | ||
current = defaultProps[p]; | ||
} | ||
if (p === 'class' && current != null) { | ||
current = normalizeClassName(current); | ||
} | ||
if (current !== prev) { | ||
hasChanges = true; | ||
props[p] = prevProps[p] = current; | ||
changes[p] = { current, prev }; | ||
if (!/^partial:/.test(p)) { | ||
representAttributeValue(component, p.replace(/[A-Z]/g, kebabCase), current); | ||
} | ||
} | ||
return result; | ||
nextProps[p] = null; | ||
} | ||
return hasChanges ? changes : null; | ||
} | ||
/** | ||
* Check if `next` contains value that differs from one in `prev` | ||
* @param {Object} prev | ||
* @param {Object} next | ||
* @returns {boolean} | ||
*/ | ||
function hasChanges(prev, next) { | ||
for (const p in next) { | ||
if (next[p] !== prev[p]) { | ||
return true; | ||
} | ||
} | ||
} | ||
const blockKey = '&block'; | ||
@@ -1024,3 +1042,3 @@ | ||
// Do not use any additional function argument for adding value to `slots` | ||
// to reduce runtime checks and keep function in monomorphic state | ||
// to reduce runtime checks and keep functions in monomorphic state | ||
slots: null, | ||
@@ -1291,3 +1309,4 @@ attributes: changeSet(), | ||
function mountBlock(component, injector, get) { | ||
return updateBlock({ | ||
/** @type {BlockContext} */ | ||
const ctx = { | ||
component, | ||
@@ -1298,4 +1317,6 @@ injector, | ||
fn: null, | ||
update: null, | ||
}); | ||
update: null | ||
}; | ||
updateBlock(ctx); | ||
return ctx; | ||
} | ||
@@ -1306,5 +1327,6 @@ | ||
* @param {BlockContext} ctx | ||
* @returns {BlockContext} | ||
* @returns {number} Returns `1` if block was updated, `0` otherwise | ||
*/ | ||
function updateBlock(ctx) { | ||
let updated = 0; | ||
const { component, injector, block: block$$1, update } = ctx; | ||
@@ -1315,2 +1337,3 @@ const scope = getScope(component); | ||
if (ctx.fn !== fn) { | ||
updated = 1; | ||
// Unmount previously rendered content | ||
@@ -1324,6 +1347,6 @@ ctx.fn && dispose(injector, block$$1, false); | ||
// Update rendered result | ||
run(injector, block$$1, update, component, scope); | ||
updated = run(injector, block$$1, update, component, scope) ? 1 : 0; | ||
} | ||
return ctx; | ||
return updated; | ||
} | ||
@@ -1333,9 +1356,11 @@ | ||
* Mounts iterator block | ||
* @param {Comment} host | ||
* @param {Component} host | ||
* @param {Injector} injector | ||
* @param {function} get A function that returns collection to iterate | ||
* @param {function} body A function that renders item of iterated collection | ||
* @param {Function} get A function that returns collection to iterate | ||
* @param {Function} body A function that renders item of iterated collection | ||
* @returns {IteratorContext} | ||
*/ | ||
function mountIterator(host, injector, get, body) { | ||
return updateIterator({ | ||
/** @type {IteratorContext} */ | ||
const ctx = { | ||
host, | ||
@@ -1347,4 +1372,7 @@ injector, | ||
index: 0, | ||
rendered: [] | ||
}); | ||
rendered: [], | ||
updated: 0 | ||
}; | ||
updateIterator(ctx); | ||
return ctx; | ||
} | ||
@@ -1354,11 +1382,19 @@ | ||
* Updates iterator block defined in `ctx` | ||
* @param {object} ctx | ||
* @param {IteratorContext} ctx | ||
* @returns {number} Returns `1` if iterator was updated, `0` otherwise | ||
*/ | ||
function updateIterator(ctx) { | ||
run(ctx.injector, ctx.block, iteratorHost, ctx.host, ctx); | ||
return ctx; | ||
run(ctx.injector, ctx.block, iteratorHost, ctx.host, ctx) ? 1 : 0; | ||
return ctx.updated; | ||
} | ||
/** | ||
* | ||
* @param {Component} host | ||
* @param {Injector} injector | ||
* @param {IteratorContext} ctx | ||
*/ | ||
function iteratorHost(host, injector, ctx) { | ||
ctx.index = 0; | ||
ctx.updated = 0; | ||
const collection = ctx.get(host, getScope(host)); | ||
@@ -1371,2 +1407,3 @@ if (collection && typeof collection.forEach === 'function') { | ||
while (ctx.rendered.length > ctx.index) { | ||
ctx.updated = 1; | ||
dispose(injector, ctx.rendered.pop()[0], true); | ||
@@ -1376,2 +1413,7 @@ } | ||
/** | ||
* @this {IteratorContext} | ||
* @param {*} value | ||
* @param {*} key | ||
*/ | ||
function iterator(value, key) { | ||
@@ -1385,3 +1427,5 @@ const { host, injector, rendered, index } = this; | ||
setScope(host, assign(scope, localScope)); | ||
run(injector, b, update, host, scope); | ||
if (run(injector, b, update, host, scope)) { | ||
this.updated = 1; | ||
} | ||
exitScope(host); | ||
@@ -1395,2 +1439,3 @@ } else { | ||
rendered.push([b, update, scope]); | ||
this.updated = 1; | ||
} | ||
@@ -1408,5 +1453,7 @@ | ||
* @param {Function} body | ||
* @returns {KeyIteratorContext} | ||
*/ | ||
function mountKeyIterator(host, injector, get, keyExpr, body) { | ||
return updateKeyIterator({ | ||
/** @type {KeyIteratorContext} */ | ||
const ctx = { | ||
host, | ||
@@ -1420,4 +1467,7 @@ injector, | ||
index: 0, | ||
updated: 1, | ||
used: null | ||
}); | ||
}; | ||
updateKeyIterator(ctx); | ||
return ctx; | ||
} | ||
@@ -1427,7 +1477,8 @@ | ||
* Updates iterator block defined in `ctx` | ||
* @param {object} ctx | ||
* @param {KeyIteratorContext} ctx | ||
* @returns {number} Returns `1` if iterator was updated, `0` otherwise | ||
*/ | ||
function updateKeyIterator(ctx) { | ||
run(ctx.injector, ctx.block, keyIteratorHost, ctx.host, ctx); | ||
return ctx; | ||
return ctx.updated; | ||
} | ||
@@ -1439,3 +1490,3 @@ | ||
* @param {Injector} injector | ||
* @param {object} ctx | ||
* @param {KeyIteratorContext} ctx | ||
*/ | ||
@@ -1445,2 +1496,3 @@ function keyIteratorHost(host, injector, ctx) { | ||
ctx.index = 0; | ||
ctx.updated = 1; | ||
@@ -1455,2 +1507,3 @@ const collection = ctx.get(host, getScope(host)); | ||
for (let i = 0, items = ctx.rendered[k]; i < items.length; i++) { | ||
ctx.updated = 1; | ||
dispose(injector, items[i][0], true); | ||
@@ -1463,2 +1516,7 @@ } | ||
/** | ||
* @this {KeyIteratorContext} | ||
* @param {*} value | ||
* @param {*} key | ||
*/ | ||
function iterator$1(value, key) { | ||
@@ -1475,3 +1533,5 @@ const { host, injector, index, used, rendered, keyExpr, body } = this; | ||
move(injector, b, injector.ptr); | ||
run(injector, b, update, host, scope); | ||
if (run(injector, b, update, host, scope)) { | ||
this.updated = 1; | ||
} | ||
exitScope(host); | ||
@@ -1483,2 +1543,3 @@ } else { | ||
const update = run(injector, b, body, host, scope); | ||
this.updated = 1; | ||
exitScope(host); | ||
@@ -1504,5 +1565,8 @@ entry = [b, update, scope]; | ||
* @param {HTMLElement} elem | ||
* @returns {number} Update status. Refs must be explicitly finalized, thus | ||
* we always return `0` as nothing was changed | ||
*/ | ||
function setRef(host, name, elem) { | ||
host.componentModel.refs.cur[name] = elem; | ||
return 0; | ||
} | ||
@@ -1524,3 +1588,3 @@ | ||
* @param {Component} host | ||
* @returns {boolean} Update status | ||
* @returns {number} Update status | ||
*/ | ||
@@ -1555,10 +1619,12 @@ function finalizeRefs(host) { | ||
* Renders code, returned from `get` function, as HTML | ||
* @param {Component} component | ||
* @param {Component} host | ||
* @param {Injector} injector | ||
* @param {function} get | ||
* @returns {function} | ||
* @param {Function} get | ||
* @param {string} slotName | ||
* @returns {InnerHtmlContext} | ||
*/ | ||
function mountInnerHTML(component, injector, get, slotName) { | ||
return updateInnerHTML({ | ||
component, | ||
function mountInnerHTML(host, injector, get, slotName) { | ||
/** @type {InnerHtmlContext} */ | ||
const ctx = { | ||
host, | ||
injector, | ||
@@ -1569,3 +1635,5 @@ block: block(injector), | ||
slotName | ||
}); | ||
}; | ||
updateInnerHTML(ctx); | ||
return ctx; | ||
} | ||
@@ -1575,15 +1643,18 @@ | ||
* Updates inner HTML of block, defined in `ctx` | ||
* @param {object} ctx | ||
* @param {InnerHtmlContext} ctx | ||
* @returns {number} Returns `1` if inner HTML was updated, `0` otherwise | ||
*/ | ||
function updateInnerHTML(ctx) { | ||
const { component, injector, block: block$$1 } = ctx; | ||
const code = ctx.get(component, injector); | ||
const { host, injector, block: block$$1 } = ctx; | ||
const code = ctx.get(host, injector); | ||
let updated = 0; | ||
if (code !== ctx.code) { | ||
updated = 1; | ||
ctx.code = code; | ||
dispose(injector, block$$1, false); | ||
isDefined(code) && run(injector, block$$1, renderHTML, component, ctx); | ||
isDefined(code) && run(injector, block$$1, renderHTML, host, ctx); | ||
} | ||
return ctx; | ||
return updated; | ||
} | ||
@@ -1594,3 +1665,3 @@ | ||
* @param {Injector} injector | ||
* @param {Object} ctx | ||
* @param {InnerHtmlContext} ctx | ||
*/ | ||
@@ -1629,2 +1700,3 @@ function renderHTML(host, injector, ctx) { | ||
* @param {Object} args | ||
* @return {PartialContext} | ||
*/ | ||
@@ -1634,10 +1706,13 @@ function mountPartial(host, injector, partial, args) { | ||
// across renders | ||
return updatePartial({ | ||
/** @type {PartialContext} */ | ||
const ctx = { | ||
host, | ||
injector, | ||
block: block(injector), | ||
scope: createScope(host), | ||
scope: null, | ||
update: null, | ||
partial: null | ||
}, partial, args); | ||
}; | ||
updatePartial(ctx, partial, args); | ||
return ctx; | ||
} | ||
@@ -1647,9 +1722,10 @@ | ||
* Updates mounted partial | ||
* @param {Object} ctx | ||
* @param {PartialContext} ctx | ||
* @param {Object} partial | ||
* @param {Object} args | ||
* @return {Object} | ||
* @returns {number} Returns `1` if partial was updated, `0` otherwise | ||
*/ | ||
function updatePartial(ctx, partial, args) { | ||
const { host, injector, scope, block: block$$1 } = ctx; | ||
const { host, injector, block: block$$1 } = ctx; | ||
let updated = 0; | ||
@@ -1661,14 +1737,17 @@ if (ctx.partial !== partial) { | ||
// Mount new partial | ||
setScope(host, assign(scope, partial.defaults, args)); | ||
const scope = ctx.scope = enterScope(host, assign(obj(partial.defaults), args)); | ||
ctx.update = partial ? run(injector, block$$1, partial.body, host, scope) : null; | ||
ctx.partial = partial; | ||
exitScope(host); | ||
updated = 1; | ||
} else if (ctx.update) { | ||
// Update rendered partial | ||
setScope(host, assign(scope, partial.defaults, args)); | ||
run(injector, block$$1, ctx.update, host, scope); | ||
setScope(host, assign(ctx.scope, args)); | ||
if (run(injector, block$$1, ctx.update, host, ctx.scope)) { | ||
updated = 1; | ||
} | ||
exitScope(host); | ||
} | ||
return ctx; | ||
return updated; | ||
} | ||
@@ -1871,3 +1950,3 @@ | ||
exports.finalizeAttributes = finalizeAttributes; | ||
exports.finalizeProps = finalizeProps; | ||
exports.normalizeClassName = normalizeClassName; | ||
exports.addEvent = addEvent; | ||
@@ -1879,2 +1958,3 @@ exports.addStaticEvent = addStaticEvent; | ||
exports.updateSlots = updateSlots; | ||
exports.markSlotUpdate = markSlotUpdate; | ||
exports.setRef = setRef; | ||
@@ -1881,0 +1961,0 @@ exports.setStaticRef = setStaticRef; |
@@ -24,6 +24,6 @@ /** | ||
* @param {*} [ctx] | ||
* @returns {boolean} Returns `true` if data was updated | ||
* @returns {number} Returns `1` if data was updated, `0` otherwise | ||
*/ | ||
function finalizeItems(items, change, ctx) { | ||
let updated = false; | ||
let updated = 0; | ||
const { cur, prev } = items; | ||
@@ -34,3 +34,3 @@ | ||
if (curValue !== prevValue) { | ||
updated = true; | ||
updated = 1; | ||
change(name, prevValue, prev[name] = curValue, ctx); | ||
@@ -234,3 +234,5 @@ } | ||
function text(value) { | ||
return document.createTextNode(textValue(value)); | ||
const node = document.createTextNode(textValue(value)); | ||
node['$value'] = value; | ||
return node; | ||
} | ||
@@ -242,12 +244,12 @@ | ||
* @param {*} value | ||
* @param {*} prevValue | ||
* @return {*} New value used in text node | ||
* @returns {number} Returns `1` if text was updated, `0` otherwise | ||
*/ | ||
function updateText(node, value, prevValue) { | ||
if (value !== prevValue) { | ||
function updateText(node, value) { | ||
if (value !== node['$value']) { | ||
node.nodeValue = textValue(value); | ||
return value; | ||
node['$value'] = value; | ||
return 1; | ||
} | ||
return prevValue; | ||
return 0; | ||
} | ||
@@ -287,3 +289,3 @@ | ||
* @param {Injector} injector | ||
* @returns {boolean} Update status | ||
* @returns {number} Update status | ||
*/ | ||
@@ -337,5 +339,8 @@ function finalizeEvents(injector) { | ||
* @param {*} value | ||
* @return {number} Update status. Always returns `0` since actual attribute value | ||
* is defined in `finalizeAttributes()` | ||
*/ | ||
function setAttribute(injector, name, value) { | ||
injector.attributes.cur[name] = value; | ||
return 0; | ||
} | ||
@@ -402,35 +407,11 @@ | ||
* @param {Injector} injector | ||
* @return {number} Update status | ||
* @return {number} | ||
*/ | ||
function finalizeAttributes(injector) { | ||
return finalizeItems(normalize(injector).attributes, changeAttribute, injector.parentNode); | ||
} | ||
/** | ||
* Applies pending attributes changes to injector’s host element as props | ||
* @param {Injector} injector | ||
* @param {Object} [data] Additional props (most likely static ones) | ||
* @return {Changes} Updated props, if any | ||
*/ | ||
function finalizeProps(injector, data) { | ||
const changes = data || obj(); | ||
const updated = finalizeItems(normalize(injector).attributes, changeProp, changes); | ||
if (data || updated) { | ||
return /** @type {Component} */ (injector.parentNode).setProps(changes); | ||
} | ||
} | ||
/** | ||
* Normalizes attributes in given injector | ||
* @param {Injector} injector | ||
*/ | ||
function normalize(injector) { | ||
const { attributes } = injector; | ||
const className = attributes.cur['class']; | ||
if (isDefined(className)) { | ||
attributes.cur['class'] = normalizeClassName(className); | ||
if (isDefined(attributes.cur['class'])) { | ||
attributes.cur['class'] = normalizeClassName(attributes.cur['class']); | ||
} | ||
return injector; | ||
return finalizeItems(attributes, changeAttribute, injector.parentNode); | ||
} | ||
@@ -474,13 +455,2 @@ | ||
/** | ||
* Callback for changing attribute value | ||
* @param {string} name | ||
* @param {*} prevValue | ||
* @param {*} newValue | ||
* @param {object} changes | ||
*/ | ||
function changeProp(name, prevValue, newValue, changes) { | ||
changes[name] = newValue; | ||
} | ||
/** | ||
* Enters new variable scope context | ||
@@ -585,3 +555,5 @@ * @param {Component} host | ||
}; | ||
host.componentModel.slots[name] = mountBlock(host, createInjector(elem), blockEntry); | ||
const { slots } = host.componentModel; | ||
slots[name] = mountBlock(host, createInjector(elem), blockEntry); | ||
} | ||
@@ -594,6 +566,13 @@ | ||
function updateSlots(host) { | ||
const { slots } = host.componentModel; | ||
const { slots, slotStatus, input } = host.componentModel; | ||
for (const name in slots) { | ||
updateBlock(slots[name]); | ||
} | ||
for (const name in slotStatus) { | ||
if (slotStatus[name]) { | ||
runHook(host, 'didSlotUpdate', [name, input.slots[name]]); | ||
slotStatus[name] = 0; | ||
} | ||
} | ||
} | ||
@@ -636,2 +615,17 @@ | ||
/** | ||
* Marks slot update status | ||
* @param {Component} component | ||
* @param {string} slotName | ||
* @param {number} status | ||
*/ | ||
function markSlotUpdate(component, slotName, status) { | ||
const { slotStatus } = component.componentModel; | ||
if (slotName in slotStatus) { | ||
slotStatus[slotName] |= status; | ||
} else { | ||
slotStatus[slotName] = status; | ||
} | ||
} | ||
/** | ||
* Creates internal lightweight Endorphin component with given definition | ||
@@ -662,5 +656,5 @@ * @param {string} name | ||
element.refs = {}; | ||
element.props = assign(obj(), defaultProps); | ||
element.props = obj(defaultProps); | ||
element.state = collectData(definition, 'state'); | ||
element.setProps = function setProps(value, silent) { | ||
element.setProps = function setProps(value) { | ||
const { componentModel } = element; | ||
@@ -670,20 +664,9 @@ | ||
// check if `componentModel` is available | ||
if (!componentModel || value == null) { | ||
return; | ||
if (value != null && componentModel && componentModel.mounted) { | ||
const changes = setPropsInternal(element, element.props, obj(value)); | ||
changes && renderNext(element, changes); | ||
} | ||
value = fillDefaults(value, defaultProps); | ||
const changes = changed(value, element.props); | ||
if (changes) { | ||
assign(element.props, value); | ||
representProps(element, value); | ||
if (!silent && componentModel.mounted) { | ||
renderNext(element, changes); | ||
} | ||
} | ||
return changes; | ||
}; | ||
element.setState = function setState(value, silent) { | ||
element.setState = function setState(value) { | ||
const { componentModel } = element; | ||
@@ -693,3 +676,3 @@ | ||
// check if `componentModel` is available | ||
if (componentModel && value != null && changed(value, element.state)) { | ||
if (value != null && componentModel && hasChanges(element.state, value)) { | ||
assign(element.state, value); | ||
@@ -702,3 +685,3 @@ | ||
// on next tick | ||
if (!silent && componentModel.mounted && !componentModel.rendering) { | ||
if (componentModel.mounted && !componentModel.rendering) { | ||
scheduleRender(element); | ||
@@ -713,3 +696,3 @@ } | ||
if (!element.componentView) { | ||
element.componentView = definition.componentView ? definition.componentView(element, host) : element; | ||
element.componentView = element; | ||
} | ||
@@ -733,2 +716,3 @@ | ||
slots: obj(), | ||
slotStatus: obj(), | ||
mounted: false, | ||
@@ -738,3 +722,4 @@ rendering: false, | ||
queued: null, | ||
events: attachStaticEvents(element, definition) | ||
events: attachStaticEvents(element, definition), | ||
defaultProps | ||
}; | ||
@@ -752,12 +737,25 @@ | ||
*/ | ||
function mountComponent(elem$$1, initialProps = obj()) { | ||
function mountComponent(elem$$1, initialProps) { | ||
const { componentModel } = elem$$1; | ||
const { input, definition } = componentModel; | ||
const { input, definition, defaultProps } = componentModel; | ||
let changes = setPropsInternal(elem$$1, obj(), assign(obj(defaultProps), initialProps)); | ||
const runtimeChanges = setPropsInternal(elem$$1, input.attributes.prev, input.attributes.cur); | ||
if (changes && runtimeChanges) { | ||
assign(changes, runtimeChanges); | ||
} else if (runtimeChanges) { | ||
changes = runtimeChanges; | ||
} | ||
const args = [changes || {}]; | ||
finalizeEvents(input); | ||
finalizeProps(input, initialProps); | ||
const changes = changed(elem$$1.props, obj()); | ||
const args = [changes || {}]; | ||
componentModel.rendering = true; | ||
// Notify slot status | ||
for (const p in input.slots) { | ||
runHook(elem$$1, 'didSlotUpdate', [p, input.slots[p]]); | ||
} | ||
if (changes) { | ||
@@ -783,8 +781,9 @@ runHook(elem$$1, 'didChange', args); | ||
function updateComponent(elem$$1) { | ||
const { componentModel } = elem$$1; | ||
const { input } = elem$$1.componentModel; | ||
const changes = setPropsInternal(elem$$1, input.attributes.prev, input.attributes.cur); | ||
finalizeEvents(input); | ||
updateSlots(elem$$1); | ||
finalizeEvents(componentModel.input); | ||
const changes = finalizeProps(componentModel.input); | ||
if (changes) { | ||
renderComponent(elem$$1, changes); | ||
renderNext(elem$$1, changes); | ||
} | ||
@@ -904,16 +903,2 @@ } | ||
/** | ||
* Represents given props as attribute values in `elem` | ||
* @param {Element} elem | ||
* @param {object} props | ||
*/ | ||
function representProps(elem$$1, props) { | ||
for (const p in props) { | ||
// Do not represent passed partials: these are internals | ||
if (!/^partial:/.test(p)) { | ||
representAttributeValue(elem$$1, p.replace(/[A-Z]/g, kebabCase), props[p]); | ||
} | ||
} | ||
} | ||
/** | ||
* Collects and attaches static event listeners to `component` from given `definition` | ||
@@ -982,23 +967,56 @@ * @param {Component} component | ||
/** | ||
* Fills any `null` or `undefined` item in `data` with value from `defaults` | ||
* @param {Object} data | ||
* @param {Object} defaults | ||
* @returns {Object} | ||
* @param {Component} component | ||
* @param {Object} prevProps | ||
* @param {Object} nextProps | ||
* @returns {Changes} | ||
*/ | ||
function fillDefaults(data, defaults) { | ||
if (data) { | ||
const result = obj(); | ||
for (const p in data) { | ||
if (data[p] == null && p in defaults) { | ||
result[p] = defaults[p]; | ||
} else if (data[p] !== result[p]) { | ||
// Skip data from prototype | ||
result[p] = data[p]; | ||
function setPropsInternal(component, prevProps, nextProps) { | ||
/** @type {Changes} */ | ||
const changes = {}; | ||
let hasChanges = false; | ||
const { props } = component; | ||
const { defaultProps } = component.componentModel; | ||
for (const p in nextProps) { | ||
const prev = prevProps[p]; | ||
let current = nextProps[p]; | ||
if (current == null) { | ||
current = defaultProps[p]; | ||
} | ||
if (p === 'class' && current != null) { | ||
current = normalizeClassName(current); | ||
} | ||
if (current !== prev) { | ||
hasChanges = true; | ||
props[p] = prevProps[p] = current; | ||
changes[p] = { current, prev }; | ||
if (!/^partial:/.test(p)) { | ||
representAttributeValue(component, p.replace(/[A-Z]/g, kebabCase), current); | ||
} | ||
} | ||
return result; | ||
nextProps[p] = null; | ||
} | ||
return hasChanges ? changes : null; | ||
} | ||
/** | ||
* Check if `next` contains value that differs from one in `prev` | ||
* @param {Object} prev | ||
* @param {Object} next | ||
* @returns {boolean} | ||
*/ | ||
function hasChanges(prev, next) { | ||
for (const p in next) { | ||
if (next[p] !== prev[p]) { | ||
return true; | ||
} | ||
} | ||
} | ||
const blockKey = '&block'; | ||
@@ -1020,3 +1038,3 @@ | ||
// Do not use any additional function argument for adding value to `slots` | ||
// to reduce runtime checks and keep function in monomorphic state | ||
// to reduce runtime checks and keep functions in monomorphic state | ||
slots: null, | ||
@@ -1287,3 +1305,4 @@ attributes: changeSet(), | ||
function mountBlock(component, injector, get) { | ||
return updateBlock({ | ||
/** @type {BlockContext} */ | ||
const ctx = { | ||
component, | ||
@@ -1294,4 +1313,6 @@ injector, | ||
fn: null, | ||
update: null, | ||
}); | ||
update: null | ||
}; | ||
updateBlock(ctx); | ||
return ctx; | ||
} | ||
@@ -1302,5 +1323,6 @@ | ||
* @param {BlockContext} ctx | ||
* @returns {BlockContext} | ||
* @returns {number} Returns `1` if block was updated, `0` otherwise | ||
*/ | ||
function updateBlock(ctx) { | ||
let updated = 0; | ||
const { component, injector, block: block$$1, update } = ctx; | ||
@@ -1311,2 +1333,3 @@ const scope = getScope(component); | ||
if (ctx.fn !== fn) { | ||
updated = 1; | ||
// Unmount previously rendered content | ||
@@ -1320,6 +1343,6 @@ ctx.fn && dispose(injector, block$$1, false); | ||
// Update rendered result | ||
run(injector, block$$1, update, component, scope); | ||
updated = run(injector, block$$1, update, component, scope) ? 1 : 0; | ||
} | ||
return ctx; | ||
return updated; | ||
} | ||
@@ -1329,9 +1352,11 @@ | ||
* Mounts iterator block | ||
* @param {Comment} host | ||
* @param {Component} host | ||
* @param {Injector} injector | ||
* @param {function} get A function that returns collection to iterate | ||
* @param {function} body A function that renders item of iterated collection | ||
* @param {Function} get A function that returns collection to iterate | ||
* @param {Function} body A function that renders item of iterated collection | ||
* @returns {IteratorContext} | ||
*/ | ||
function mountIterator(host, injector, get, body) { | ||
return updateIterator({ | ||
/** @type {IteratorContext} */ | ||
const ctx = { | ||
host, | ||
@@ -1343,4 +1368,7 @@ injector, | ||
index: 0, | ||
rendered: [] | ||
}); | ||
rendered: [], | ||
updated: 0 | ||
}; | ||
updateIterator(ctx); | ||
return ctx; | ||
} | ||
@@ -1350,11 +1378,19 @@ | ||
* Updates iterator block defined in `ctx` | ||
* @param {object} ctx | ||
* @param {IteratorContext} ctx | ||
* @returns {number} Returns `1` if iterator was updated, `0` otherwise | ||
*/ | ||
function updateIterator(ctx) { | ||
run(ctx.injector, ctx.block, iteratorHost, ctx.host, ctx); | ||
return ctx; | ||
run(ctx.injector, ctx.block, iteratorHost, ctx.host, ctx) ? 1 : 0; | ||
return ctx.updated; | ||
} | ||
/** | ||
* | ||
* @param {Component} host | ||
* @param {Injector} injector | ||
* @param {IteratorContext} ctx | ||
*/ | ||
function iteratorHost(host, injector, ctx) { | ||
ctx.index = 0; | ||
ctx.updated = 0; | ||
const collection = ctx.get(host, getScope(host)); | ||
@@ -1367,2 +1403,3 @@ if (collection && typeof collection.forEach === 'function') { | ||
while (ctx.rendered.length > ctx.index) { | ||
ctx.updated = 1; | ||
dispose(injector, ctx.rendered.pop()[0], true); | ||
@@ -1372,2 +1409,7 @@ } | ||
/** | ||
* @this {IteratorContext} | ||
* @param {*} value | ||
* @param {*} key | ||
*/ | ||
function iterator(value, key) { | ||
@@ -1381,3 +1423,5 @@ const { host, injector, rendered, index } = this; | ||
setScope(host, assign(scope, localScope)); | ||
run(injector, b, update, host, scope); | ||
if (run(injector, b, update, host, scope)) { | ||
this.updated = 1; | ||
} | ||
exitScope(host); | ||
@@ -1391,2 +1435,3 @@ } else { | ||
rendered.push([b, update, scope]); | ||
this.updated = 1; | ||
} | ||
@@ -1404,5 +1449,7 @@ | ||
* @param {Function} body | ||
* @returns {KeyIteratorContext} | ||
*/ | ||
function mountKeyIterator(host, injector, get, keyExpr, body) { | ||
return updateKeyIterator({ | ||
/** @type {KeyIteratorContext} */ | ||
const ctx = { | ||
host, | ||
@@ -1416,4 +1463,7 @@ injector, | ||
index: 0, | ||
updated: 1, | ||
used: null | ||
}); | ||
}; | ||
updateKeyIterator(ctx); | ||
return ctx; | ||
} | ||
@@ -1423,7 +1473,8 @@ | ||
* Updates iterator block defined in `ctx` | ||
* @param {object} ctx | ||
* @param {KeyIteratorContext} ctx | ||
* @returns {number} Returns `1` if iterator was updated, `0` otherwise | ||
*/ | ||
function updateKeyIterator(ctx) { | ||
run(ctx.injector, ctx.block, keyIteratorHost, ctx.host, ctx); | ||
return ctx; | ||
return ctx.updated; | ||
} | ||
@@ -1435,3 +1486,3 @@ | ||
* @param {Injector} injector | ||
* @param {object} ctx | ||
* @param {KeyIteratorContext} ctx | ||
*/ | ||
@@ -1441,2 +1492,3 @@ function keyIteratorHost(host, injector, ctx) { | ||
ctx.index = 0; | ||
ctx.updated = 1; | ||
@@ -1451,2 +1503,3 @@ const collection = ctx.get(host, getScope(host)); | ||
for (let i = 0, items = ctx.rendered[k]; i < items.length; i++) { | ||
ctx.updated = 1; | ||
dispose(injector, items[i][0], true); | ||
@@ -1459,2 +1512,7 @@ } | ||
/** | ||
* @this {KeyIteratorContext} | ||
* @param {*} value | ||
* @param {*} key | ||
*/ | ||
function iterator$1(value, key) { | ||
@@ -1471,3 +1529,5 @@ const { host, injector, index, used, rendered, keyExpr, body } = this; | ||
move(injector, b, injector.ptr); | ||
run(injector, b, update, host, scope); | ||
if (run(injector, b, update, host, scope)) { | ||
this.updated = 1; | ||
} | ||
exitScope(host); | ||
@@ -1479,2 +1539,3 @@ } else { | ||
const update = run(injector, b, body, host, scope); | ||
this.updated = 1; | ||
exitScope(host); | ||
@@ -1500,5 +1561,8 @@ entry = [b, update, scope]; | ||
* @param {HTMLElement} elem | ||
* @returns {number} Update status. Refs must be explicitly finalized, thus | ||
* we always return `0` as nothing was changed | ||
*/ | ||
function setRef(host, name, elem) { | ||
host.componentModel.refs.cur[name] = elem; | ||
return 0; | ||
} | ||
@@ -1520,3 +1584,3 @@ | ||
* @param {Component} host | ||
* @returns {boolean} Update status | ||
* @returns {number} Update status | ||
*/ | ||
@@ -1551,10 +1615,12 @@ function finalizeRefs(host) { | ||
* Renders code, returned from `get` function, as HTML | ||
* @param {Component} component | ||
* @param {Component} host | ||
* @param {Injector} injector | ||
* @param {function} get | ||
* @returns {function} | ||
* @param {Function} get | ||
* @param {string} slotName | ||
* @returns {InnerHtmlContext} | ||
*/ | ||
function mountInnerHTML(component, injector, get, slotName) { | ||
return updateInnerHTML({ | ||
component, | ||
function mountInnerHTML(host, injector, get, slotName) { | ||
/** @type {InnerHtmlContext} */ | ||
const ctx = { | ||
host, | ||
injector, | ||
@@ -1565,3 +1631,5 @@ block: block(injector), | ||
slotName | ||
}); | ||
}; | ||
updateInnerHTML(ctx); | ||
return ctx; | ||
} | ||
@@ -1571,15 +1639,18 @@ | ||
* Updates inner HTML of block, defined in `ctx` | ||
* @param {object} ctx | ||
* @param {InnerHtmlContext} ctx | ||
* @returns {number} Returns `1` if inner HTML was updated, `0` otherwise | ||
*/ | ||
function updateInnerHTML(ctx) { | ||
const { component, injector, block: block$$1 } = ctx; | ||
const code = ctx.get(component, injector); | ||
const { host, injector, block: block$$1 } = ctx; | ||
const code = ctx.get(host, injector); | ||
let updated = 0; | ||
if (code !== ctx.code) { | ||
updated = 1; | ||
ctx.code = code; | ||
dispose(injector, block$$1, false); | ||
isDefined(code) && run(injector, block$$1, renderHTML, component, ctx); | ||
isDefined(code) && run(injector, block$$1, renderHTML, host, ctx); | ||
} | ||
return ctx; | ||
return updated; | ||
} | ||
@@ -1590,3 +1661,3 @@ | ||
* @param {Injector} injector | ||
* @param {Object} ctx | ||
* @param {InnerHtmlContext} ctx | ||
*/ | ||
@@ -1625,2 +1696,3 @@ function renderHTML(host, injector, ctx) { | ||
* @param {Object} args | ||
* @return {PartialContext} | ||
*/ | ||
@@ -1630,10 +1702,13 @@ function mountPartial(host, injector, partial, args) { | ||
// across renders | ||
return updatePartial({ | ||
/** @type {PartialContext} */ | ||
const ctx = { | ||
host, | ||
injector, | ||
block: block(injector), | ||
scope: createScope(host), | ||
scope: null, | ||
update: null, | ||
partial: null | ||
}, partial, args); | ||
}; | ||
updatePartial(ctx, partial, args); | ||
return ctx; | ||
} | ||
@@ -1643,9 +1718,10 @@ | ||
* Updates mounted partial | ||
* @param {Object} ctx | ||
* @param {PartialContext} ctx | ||
* @param {Object} partial | ||
* @param {Object} args | ||
* @return {Object} | ||
* @returns {number} Returns `1` if partial was updated, `0` otherwise | ||
*/ | ||
function updatePartial(ctx, partial, args) { | ||
const { host, injector, scope, block: block$$1 } = ctx; | ||
const { host, injector, block: block$$1 } = ctx; | ||
let updated = 0; | ||
@@ -1657,14 +1733,17 @@ if (ctx.partial !== partial) { | ||
// Mount new partial | ||
setScope(host, assign(scope, partial.defaults, args)); | ||
const scope = ctx.scope = enterScope(host, assign(obj(partial.defaults), args)); | ||
ctx.update = partial ? run(injector, block$$1, partial.body, host, scope) : null; | ||
ctx.partial = partial; | ||
exitScope(host); | ||
updated = 1; | ||
} else if (ctx.update) { | ||
// Update rendered partial | ||
setScope(host, assign(scope, partial.defaults, args)); | ||
run(injector, block$$1, ctx.update, host, scope); | ||
setScope(host, assign(ctx.scope, args)); | ||
if (run(injector, block$$1, ctx.update, host, ctx.scope)) { | ||
updated = 1; | ||
} | ||
exitScope(host); | ||
} | ||
return ctx; | ||
return updated; | ||
} | ||
@@ -1839,3 +1918,3 @@ | ||
export { get, filter, mountBlock, updateBlock, mountIterator, updateIterator, mountKeyIterator, updateKeyIterator, createInjector, block, run, insert, move, dispose, enterScope, exitScope, createScope, setScope, getScope, getProp, getState, getVar, setVar, setAttribute, updateAttribute, updateProps, addClass, finalizeAttributes, finalizeProps, addEvent, addStaticEvent, finalizeEvents, getEventHandler, mountSlot, updateSlots, setRef, setStaticRef, finalizeRefs, createComponent, mountComponent, updateComponent, unmountComponent, subscribeStore, scheduleRender, renderComponent, mountInnerHTML, updateInnerHTML, elem, elemNS, elemWithText, elemNSWithText, text, updateText, mountPartial, updatePartial, Store }; | ||
export { get, filter, mountBlock, updateBlock, mountIterator, updateIterator, mountKeyIterator, updateKeyIterator, createInjector, block, run, insert, move, dispose, enterScope, exitScope, createScope, setScope, getScope, getProp, getState, getVar, setVar, setAttribute, updateAttribute, updateProps, addClass, finalizeAttributes, normalizeClassName, addEvent, addStaticEvent, finalizeEvents, getEventHandler, mountSlot, updateSlots, markSlotUpdate, setRef, setStaticRef, finalizeRefs, createComponent, mountComponent, updateComponent, unmountComponent, subscribeStore, scheduleRender, renderComponent, mountInnerHTML, updateInnerHTML, elem, elemNS, elemWithText, elemNSWithText, text, updateText, mountPartial, updatePartial, Store }; | ||
//# sourceMappingURL=runtime.es.js.map |
{ | ||
"name": "@endorphinjs/template-runtime", | ||
"version": "0.1.9", | ||
"version": "0.1.10", | ||
"description": "EndorphinJS template runtime, embedded with template bundles", | ||
@@ -23,2 +23,3 @@ "main": "./dist/runtime.cjs.js", | ||
"devDependencies": { | ||
"@endorphinjs/template-compiler": "^0.1.10", | ||
"mocha": "^5.2.0", | ||
@@ -25,0 +26,0 @@ "reify": "^0.18.1", |
@@ -54,3 +54,3 @@ import { Store } from './lib/store'; | ||
*/ | ||
setProps(value: object, silent?: boolean): void; | ||
setProps(value: object): void; | ||
@@ -62,3 +62,3 @@ /** | ||
*/ | ||
setState(value: object, silent: boolean): void; | ||
setState(value: object): void; | ||
} | ||
@@ -109,2 +109,9 @@ | ||
/** | ||
* Slots update status | ||
*/ | ||
slotStatus?: { | ||
[name: string]: number | ||
}; | ||
/** | ||
* Indicates that component was mounted | ||
@@ -126,2 +133,7 @@ * @private | ||
rendering: boolean; | ||
/** | ||
* Default props values | ||
*/ | ||
defaultProps: object; | ||
} | ||
@@ -275,3 +287,5 @@ | ||
*/ | ||
slots: object; | ||
slots?: { | ||
[name: string]: DocumentFragment | Element | ||
}; | ||
@@ -349,2 +363,41 @@ /** | ||
interface IteratorContext { | ||
host: Component; | ||
injector: Injector; | ||
get: Function; | ||
body: Function; | ||
block: Block; | ||
index: number; | ||
updated: number; | ||
rendered: Array<[Block, Function, Object]>; | ||
} | ||
interface KeyIteratorContext extends IteratorContext { | ||
keyExpr: Function; | ||
used: { | ||
[key: string]: Array<[Block, Function, Object]> | ||
} | ||
rendered: { | ||
[key: string]: Array<[Block, Function, Object]> | ||
} | ||
} | ||
interface InnerHtmlContext { | ||
host: Component; | ||
injector: Injector; | ||
block: Block; | ||
get: Function; | ||
code?: string; | ||
slotName: string; | ||
} | ||
interface PartialContext { | ||
host: Component; | ||
injector: Injector; | ||
block: Block, | ||
update?: Function, | ||
scope?: object, | ||
partial?: object | ||
} | ||
interface StoreUpdateHandler { | ||
@@ -351,0 +404,0 @@ (state: object, changes: object): void |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
283050
9
3693
4