mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Final fixes for #670 - Add support for serialized globals and retain globals on re-render
This commit is contained in:
parent
25c779024c
commit
3d1ceab41d
@ -3,6 +3,7 @@
|
||||
|
||||
var domInsert = require('../runtime/dom-insert');
|
||||
var marko = require('../');
|
||||
var getComponentsContext = require('./ComponentsContext').$__getComponentsContext;
|
||||
var componentsUtil = require('./util');
|
||||
var componentLookup = componentsUtil.$__componentLookup;
|
||||
var emitLifecycleEvent = componentsUtil.$__emitLifecycleEvent;
|
||||
@ -16,7 +17,6 @@ var inherit = require('raptor-util/inherit');
|
||||
var updateManager = require('./update-manager');
|
||||
var morphdom = require('../morphdom');
|
||||
var eventDelegation = require('./event-delegation');
|
||||
var ComponentsContext = require('./ComponentsContext');
|
||||
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
@ -520,10 +520,6 @@ Component.prototype = componentProto = {
|
||||
out.sync();
|
||||
out.$__document = self.$__document;
|
||||
|
||||
var componentsContext = ComponentsContext.$__getComponentsContext(out);
|
||||
componentsContext.$__rerenderComponent = self;
|
||||
componentsContext.$__isRerenderInBrowser = isRerenderInBrowser;
|
||||
|
||||
if (isRerenderInBrowser === true) {
|
||||
out.e =
|
||||
out.be =
|
||||
@ -536,6 +532,11 @@ Component.prototype = componentProto = {
|
||||
outNoop;
|
||||
}
|
||||
|
||||
var componentsContext = getComponentsContext(out);
|
||||
var globalComponentsContext = componentsContext.$__globalContext;
|
||||
globalComponentsContext.$__rerenderComponent = self;
|
||||
globalComponentsContext.$__isRerenderInBrowser = isRerenderInBrowser;
|
||||
|
||||
renderer(input, out);
|
||||
|
||||
var result = new RenderResult(out);
|
||||
@ -549,29 +550,28 @@ Component.prototype = componentProto = {
|
||||
while(targetEl) {
|
||||
var id = targetEl.id;
|
||||
|
||||
if (id) {
|
||||
fromEl = fromEls[id];
|
||||
if (fromEl) {
|
||||
morphdom(
|
||||
fromEl,
|
||||
targetEl,
|
||||
globalComponentsContext,
|
||||
onNodeAdded,
|
||||
onBeforeElUpdated,
|
||||
onBeforeNodeDiscarded,
|
||||
onNodeDiscarded,
|
||||
onBeforeElChildrenUpdated);
|
||||
}
|
||||
if (id) {
|
||||
fromEl = fromEls[id];
|
||||
if (fromEl) {
|
||||
morphdom(
|
||||
fromEl,
|
||||
targetEl,
|
||||
globalComponentsContext,
|
||||
onNodeAdded,
|
||||
onBeforeElUpdated,
|
||||
onBeforeNodeDiscarded,
|
||||
onNodeDiscarded,
|
||||
onBeforeElChildrenUpdated);
|
||||
}
|
||||
|
||||
targetEl = targetEl.nextSibling;
|
||||
targetEl = targetEl.nextSibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.afterInsert(doc);
|
||||
|
||||
out.emit('$__componentsInitialized');
|
||||
|
||||
out.data.components = null;
|
||||
});
|
||||
|
||||
this.$__reset();
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
'use strict';
|
||||
var nextRepeatedId = require('./nextRepeatedId');
|
||||
var repeatedRegExp = /\[\]$/;
|
||||
var componentUtil = require('./util');
|
||||
var nextComponentId = componentUtil.$__nextComponentId;
|
||||
var attachBubblingEvent = componentUtil.$__attachBubblingEvent;
|
||||
var extend = require('raptor-util/extend');
|
||||
|
||||
@ -11,8 +9,8 @@ var extend = require('raptor-util/extend');
|
||||
* a single component and this information is used to instantiate the component
|
||||
* later (after the rendered HTML has been added to the DOM)
|
||||
*/
|
||||
function ComponentDef(component, componentId, out, componentStack, componentStackLen) {
|
||||
this.$__out = out; // The AsyncWriter that this component is associated with
|
||||
function ComponentDef(component, componentId, globalComponentsContext, componentStack, componentStackLen) {
|
||||
this.$__globalComponentsContext = globalComponentsContext; // The AsyncWriter that this component is associated with
|
||||
this.$__componentStack = componentStack;
|
||||
this.$__componentStackLen = componentStackLen;
|
||||
this.$__component = component;
|
||||
@ -20,7 +18,7 @@ function ComponentDef(component, componentId, out, componentStack, componentStac
|
||||
|
||||
this.$__roots = null; // IDs of root elements if there are multiple root elements
|
||||
this.$__children = null; // An array of nested ComponentDef instances
|
||||
this.$__domEvents = null; // An array of DOM events that need to be added (in sets of three)
|
||||
this.$__domEvents = undefined; // An array of DOM events that need to be added (in sets of three)
|
||||
|
||||
this.$__isExisting = false;
|
||||
|
||||
@ -61,7 +59,7 @@ ComponentDef.prototype = {
|
||||
return id;
|
||||
} else {
|
||||
if (typeof nestedId == 'string' && repeatedRegExp.test(nestedId)) {
|
||||
return nextRepeatedId(this.$__out, id, nestedId);
|
||||
return this.$__globalComponentsContext.$__nextRepeatedId(id, nestedId);
|
||||
} else {
|
||||
return id + '-' + nestedId;
|
||||
}
|
||||
@ -89,12 +87,12 @@ ComponentDef.prototype = {
|
||||
/**
|
||||
* Returns the next auto generated unique ID for a nested DOM element or nested DOM component
|
||||
*/
|
||||
$__nextId: function() {
|
||||
$__nextComponentId: function() {
|
||||
var id = this.id;
|
||||
|
||||
return id ?
|
||||
id + '-c' + (this.$__nextIdIndex++) :
|
||||
nextComponentId(this.$__out);
|
||||
return id === null ?
|
||||
this.$__globalComponentsContext.$__nextComponentId(this.$__out) :
|
||||
id + '-c' + (this.$__nextIdIndex++);
|
||||
},
|
||||
|
||||
d: function(handlerMethodName, extraArgs) {
|
||||
@ -102,7 +100,7 @@ ComponentDef.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
ComponentDef.$__deserialize = function(o, types, registry) {
|
||||
ComponentDef.$__deserialize = function(o, types, globals, registry) {
|
||||
var id = o[0];
|
||||
var typeName = types[o[1]];
|
||||
var input = o[2];
|
||||
@ -145,6 +143,8 @@ ComponentDef.$__deserialize = function(o, types, registry) {
|
||||
component.$__setCustomEvents(customEvents, scope);
|
||||
}
|
||||
|
||||
component.$__global = globals;
|
||||
|
||||
return {
|
||||
$__component: component,
|
||||
$__roots: extra.r,
|
||||
|
||||
@ -2,7 +2,8 @@
|
||||
|
||||
var ComponentDef = require('./ComponentDef');
|
||||
var initComponents = require('./init-components');
|
||||
var isServer = require('./util').$__isServer === true;
|
||||
var componentsUtil = require('./util');
|
||||
var isServer = componentsUtil.$__isServer === true;
|
||||
|
||||
var EMPTY_OBJECT = {};
|
||||
|
||||
@ -12,6 +13,9 @@ function GlobalComponentsContext(out) {
|
||||
this.$__preservedBodies = EMPTY_OBJECT;
|
||||
this.$__componentsById = {};
|
||||
this.$__out = out;
|
||||
this.$__rerenderComponent = undefined;
|
||||
this.$__nextIdLookup = null;
|
||||
this.$__nextComponentId = componentsUtil.$__nextComponentIdProvider(out);
|
||||
}
|
||||
|
||||
GlobalComponentsContext.prototype = {
|
||||
@ -32,6 +36,10 @@ GlobalComponentsContext.prototype = {
|
||||
|
||||
this.$__roots = null;
|
||||
|
||||
// Reset things stored in global since global is retained for
|
||||
// future renders
|
||||
this.$__out.global.components = undefined;
|
||||
|
||||
return topLevelComponentDefs;
|
||||
},
|
||||
$__preserveDOMNode: function(elId, bodyOnly) {
|
||||
@ -44,6 +52,19 @@ GlobalComponentsContext.prototype = {
|
||||
}
|
||||
}
|
||||
preserved[elId] = true;
|
||||
},
|
||||
$__nextRepeatedId: function(parentId, id) {
|
||||
var nextIdLookup = this.$__nextIdLookup || (this.$__nextIdLookup = {});
|
||||
|
||||
var indexLookupKey = parentId + '-' + id;
|
||||
var currentIndex = nextIdLookup[indexLookupKey];
|
||||
if (currentIndex == null) {
|
||||
currentIndex = nextIdLookup[indexLookupKey] = 0;
|
||||
} else {
|
||||
currentIndex = ++nextIdLookup[indexLookupKey];
|
||||
}
|
||||
|
||||
return indexLookupKey.slice(0, -2) + '[' + currentIndex + ']';
|
||||
}
|
||||
};
|
||||
|
||||
@ -53,13 +74,13 @@ function ComponentsContext(out, parentComponentsContext, shouldAddGlobalRoot) {
|
||||
var globalComponentsContext;
|
||||
|
||||
if (parentComponentsContext === undefined) {
|
||||
root = new ComponentDef(null, null, out);
|
||||
|
||||
globalComponentsContext = out.global.components;
|
||||
if (globalComponentsContext === undefined) {
|
||||
out.global.components = globalComponentsContext = new GlobalComponentsContext(out);
|
||||
}
|
||||
|
||||
root = new ComponentDef(null, null, globalComponentsContext);
|
||||
|
||||
if (shouldAddGlobalRoot !== false) {
|
||||
globalComponentsContext.$__roots.push(root);
|
||||
}
|
||||
@ -72,7 +93,6 @@ function ComponentsContext(out, parentComponentsContext, shouldAddGlobalRoot) {
|
||||
this.$__globalContext = globalComponentsContext;
|
||||
this.$__out = out;
|
||||
this.$__componentStack = [root];
|
||||
this.$__rerenderComponent = undefined;
|
||||
}
|
||||
|
||||
ComponentsContext.prototype = {
|
||||
@ -82,29 +102,23 @@ ComponentsContext.prototype = {
|
||||
$__beginComponent: function(component, isSplitComponent) {
|
||||
var componentStack = this.$__componentStack;
|
||||
var origLength = componentStack.length;
|
||||
var parent = componentStack[origLength - 1];
|
||||
var parentComponentDef = componentStack[origLength - 1];
|
||||
|
||||
var componentId = component.id;
|
||||
|
||||
if (!componentId) {
|
||||
componentId = component.id = parent.$__nextId();
|
||||
}
|
||||
|
||||
var out = this.$__out;
|
||||
|
||||
var componentDef = new ComponentDef(component, componentId, out, componentStack, origLength);
|
||||
var componentDef = new ComponentDef(component, componentId, this.$__globalContext, componentStack, origLength);
|
||||
if (isServer) {
|
||||
// On the server
|
||||
if (parent.$__willRerenderInBrowser === true) {
|
||||
if (parentComponentDef.$__willRerenderInBrowser === true) {
|
||||
componentDef.$__willRerenderInBrowser = true;
|
||||
} else {
|
||||
parent.$__addChild(componentDef);
|
||||
if (isSplitComponent === false && out.global.noBrowserRerender !== true) {
|
||||
parentComponentDef.$__addChild(componentDef);
|
||||
if (isSplitComponent === false && this.$__out.global.noBrowserRerender !== true) {
|
||||
componentDef.$__willRerenderInBrowser = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parent.$__addChild(componentDef);
|
||||
parentComponentDef.$__addChild(componentDef);
|
||||
this.$__globalContext.$__componentsById[componentId] = componentDef;
|
||||
}
|
||||
|
||||
@ -115,8 +129,8 @@ ComponentsContext.prototype = {
|
||||
|
||||
$__nextComponentId: function() {
|
||||
var componentStack = this.$__componentStack;
|
||||
var parent = componentStack[componentStack.length - 1];
|
||||
return parent.$__nextId();
|
||||
var parentComponentDef = componentStack[componentStack.length - 1];
|
||||
return parentComponentDef.$__nextComponentId();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -101,9 +101,10 @@ function flattenHelper(components, flattened, typesArray, typesLookup) {
|
||||
function getRenderedComponents(out, shouldIncludeAll) {
|
||||
var componentDefs;
|
||||
var globalComponentsContext;
|
||||
var outGlobal = out.global;
|
||||
|
||||
if (shouldIncludeAll === true) {
|
||||
globalComponentsContext = out.global.components;
|
||||
globalComponentsContext = outGlobal.components;
|
||||
|
||||
if (globalComponentsContext === undefined) {
|
||||
return undefined;
|
||||
@ -126,6 +127,7 @@ function getRenderedComponents(out, shouldIncludeAll) {
|
||||
var flattened = [];
|
||||
var typesLookup = {};
|
||||
var typesArray = [];
|
||||
var serializedGlobals;
|
||||
|
||||
if (shouldIncludeAll === true) {
|
||||
let roots = globalComponentsContext.$__roots;
|
||||
@ -136,6 +138,18 @@ function getRenderedComponents(out, shouldIncludeAll) {
|
||||
flattenHelper(children, flattened, typesArray, typesLookup);
|
||||
}
|
||||
}
|
||||
|
||||
var serializedGlobalsLookup = outGlobal.serializedGlobals;
|
||||
if (serializedGlobalsLookup) {
|
||||
serializedGlobals = {};
|
||||
var keys = Object.keys(serializedGlobalsLookup);
|
||||
for (let i=0, len=keys.length; i<len; i++) {
|
||||
let key = keys[i];
|
||||
if (serializedGlobalsLookup[key] === true) {
|
||||
serializedGlobals[key] = outGlobal[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
flattenHelper(componentDefs, flattened, typesArray, typesLookup);
|
||||
}
|
||||
@ -144,7 +158,7 @@ function getRenderedComponents(out, shouldIncludeAll) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {w: flattened, t: typesArray};
|
||||
return {w: flattened, t: typesArray, g: serializedGlobals};
|
||||
}
|
||||
|
||||
function writeInitComponentsCode(out, shouldIncludeAll) {
|
||||
|
||||
@ -182,12 +182,13 @@ function initServerRendered(renderedComponents, doc) {
|
||||
|
||||
var componentDefs = renderedComponents.w;
|
||||
var typesArray = renderedComponents.t;
|
||||
var globals = renderedComponents.g || {};
|
||||
|
||||
componentDefs.forEach(function(componentDef) {
|
||||
componentDef = ComponentDef.$__deserialize(componentDef, typesArray, registry);
|
||||
componentDef = ComponentDef.$__deserialize(componentDef, typesArray, globals, registry);
|
||||
initComponent(componentDef, doc || defaultDocument);
|
||||
});
|
||||
}
|
||||
|
||||
exports.$__initClientRendered = initClientRendered;
|
||||
exports.$__initServerRendered = initServerRendered;
|
||||
exports.$__initServerRendered = initServerRendered;
|
||||
|
||||
@ -40,9 +40,10 @@ function createRendererFunc(templateRenderFunc, componentProps) {
|
||||
var componentBody;
|
||||
var componentState;
|
||||
|
||||
var componentsContext = ComponentsContext.$__getComponentsContext(out);
|
||||
var componentsContext = getComponentsContext(out);
|
||||
var globalComponentsContext = componentsContext.$__globalContext;
|
||||
|
||||
var component = componentsContext.$__rerenderComponent;
|
||||
var component = globalComponentsContext.$__rerenderComponent;
|
||||
var fakeComponent;
|
||||
var isRerender = component !== undefined;
|
||||
var id = assignedId;
|
||||
@ -53,7 +54,7 @@ function createRendererFunc(templateRenderFunc, componentProps) {
|
||||
if (component) {
|
||||
id = component.id;
|
||||
isExisting = true;
|
||||
componentsContext.$__rerenderComponent = null;
|
||||
globalComponentsContext.$__rerenderComponent = null;
|
||||
} else {
|
||||
var componentArgs = out.$__componentArgs;
|
||||
|
||||
@ -69,12 +70,11 @@ function createRendererFunc(templateRenderFunc, componentProps) {
|
||||
if (ref != null) {
|
||||
ref = ref.toString();
|
||||
}
|
||||
id = id || resolveComponentKey(out, ref, scope);
|
||||
id = id || resolveComponentKey(globalComponentsContext, ref, scope);
|
||||
customEvents = componentArgs[2];
|
||||
}
|
||||
}
|
||||
|
||||
var componentsContext = getComponentsContext(out);
|
||||
id = id || componentsContext.$__nextComponentId();
|
||||
|
||||
if (registry.$__isServer && typeName) {
|
||||
@ -145,19 +145,21 @@ function createRendererFunc(templateRenderFunc, componentProps) {
|
||||
}
|
||||
}
|
||||
|
||||
if (component && isExisting) {
|
||||
if (isExisting === true) {
|
||||
if (!component.$__isDirty || !component.shouldUpdate(input, component.$__state)) {
|
||||
if (customEvents) {
|
||||
component.$__setCustomEvents(customEvents, scope);
|
||||
}
|
||||
|
||||
preserveComponentEls(component, out, componentsContext);
|
||||
preserveComponentEls(component, out, globalComponentsContext);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!component) {
|
||||
fakeComponent = {};
|
||||
fakeComponent = {
|
||||
id: id
|
||||
};
|
||||
} else {
|
||||
componentState = component.$__rawState || componentState;
|
||||
}
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
var REPEATED_ID_KEY = '$rep';
|
||||
|
||||
module.exports = function nextRepeatedId(out, parentId, id) {
|
||||
var nextIdLookup = out.global[REPEATED_ID_KEY] || (out.global[REPEATED_ID_KEY] = {});
|
||||
|
||||
var indexLookupKey = parentId + '-' + id;
|
||||
var currentIndex = nextIdLookup[indexLookupKey];
|
||||
if (currentIndex == null) {
|
||||
currentIndex = nextIdLookup[indexLookupKey] = 0;
|
||||
} else {
|
||||
currentIndex = ++nextIdLookup[indexLookupKey];
|
||||
}
|
||||
|
||||
return indexLookupKey.slice(0, -2) + '[' + currentIndex + ']';
|
||||
};
|
||||
@ -4,8 +4,6 @@ var emitLifecycleEvent = componentsUtil.$__emitLifecycleEvent;
|
||||
|
||||
var ComponentsContext = require('./ComponentsContext');
|
||||
var getComponentsContext = ComponentsContext.$__getComponentsContext;
|
||||
|
||||
var nextRepeatedId = require('./nextRepeatedId');
|
||||
var repeatedRegExp = /\[\]$/;
|
||||
var registry = require('./registry');
|
||||
var copyProps = require('raptor-util/copyProps');
|
||||
@ -13,14 +11,14 @@ var isServer = componentsUtil.$__isServer === true;
|
||||
|
||||
var COMPONENT_BEGIN_ASYNC_ADDED_KEY = '$wa';
|
||||
|
||||
function resolveComponentKey(out, key, scope) {
|
||||
function resolveComponentKey(globalComponentsContext, key, scope) {
|
||||
if (key[0] == '#') {
|
||||
return key.substring(1);
|
||||
} else {
|
||||
var resolvedId;
|
||||
|
||||
if (repeatedRegExp.test(key)) {
|
||||
resolvedId = nextRepeatedId(out, scope, key);
|
||||
resolvedId = globalComponentsContext.$__nextRepeatedId(scope, key);
|
||||
} else {
|
||||
resolvedId = scope + '-' + key;
|
||||
}
|
||||
@ -29,7 +27,7 @@ function resolveComponentKey(out, key, scope) {
|
||||
}
|
||||
}
|
||||
|
||||
function preserveComponentEls(existingComponent, out, componentsContext) {
|
||||
function preserveComponentEls(existingComponent, out, globalComponentsContext) {
|
||||
var rootEls = existingComponent.$__getRootEls({});
|
||||
|
||||
for (var elId in rootEls) {
|
||||
@ -39,7 +37,7 @@ function preserveComponentEls(existingComponent, out, componentsContext) {
|
||||
// DOM node is matched up correctly when using morphdom.
|
||||
out.element(el.tagName, { id: elId });
|
||||
|
||||
componentsContext.$__globalContext.$__preserveDOMNode(elId); // Mark the element as being preserved (for morphdom)
|
||||
globalComponentsContext.$__preserveDOMNode(elId); // Mark the element as being preserved (for morphdom)
|
||||
}
|
||||
|
||||
existingComponent.$__reset(); // The component is no longer dirty so reset internal flags
|
||||
@ -86,9 +84,10 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic)
|
||||
}
|
||||
}
|
||||
|
||||
var componentsContext = ComponentsContext.$__getComponentsContext(out);
|
||||
var componentsContext = getComponentsContext(out);
|
||||
var globalComponentsContext = componentsContext.$__globalContext;
|
||||
|
||||
var component = componentsContext.$__rerenderComponent;
|
||||
var component = globalComponentsContext.$__rerenderComponent;
|
||||
var isRerender = component !== undefined;
|
||||
var id = assignedId;
|
||||
var isExisting;
|
||||
@ -98,7 +97,7 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic)
|
||||
if (component) {
|
||||
id = component.id;
|
||||
isExisting = true;
|
||||
componentsContext.$__rerenderComponent = null;
|
||||
globalComponentsContext.$__rerenderComponent = null;
|
||||
} else {
|
||||
var componentArgs = out.$__componentArgs;
|
||||
|
||||
@ -115,12 +114,11 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic)
|
||||
if (key != null) {
|
||||
key = key.toString();
|
||||
}
|
||||
id = id || resolveComponentKey(out, key, scope);
|
||||
id = id || resolveComponentKey(globalComponentsContext, key, scope);
|
||||
customEvents = componentArgs[2];
|
||||
}
|
||||
}
|
||||
|
||||
var componentsContext = getComponentsContext(out);
|
||||
id = id || componentsContext.$__nextComponentId();
|
||||
|
||||
if (isServer) {
|
||||
@ -180,7 +178,7 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic)
|
||||
|
||||
if (isExisting === true) {
|
||||
if (component.$__isDirty === false || component.shouldUpdate(input, component.$__state) === false) {
|
||||
preserveComponentEls(component, out, componentsContext);
|
||||
preserveComponentEls(component, out, globalComponentsContext);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
var ComponentsContext = require('../ComponentsContext');
|
||||
var getElementById = require('../util').$__getElementById;
|
||||
|
||||
module.exports = function render(input, out) {
|
||||
var componentsContext = ComponentsContext.$__getComponentsContext(out);
|
||||
var globalComponentsContext = out.global.components;
|
||||
|
||||
if (componentsContext.$__isRerenderInBrowser !== true && componentsContext.$__rerenderComponent !== undefined) {
|
||||
if (globalComponentsContext && globalComponentsContext.$__isRerenderInBrowser !== true && globalComponentsContext.$__rerenderComponent !== undefined) {
|
||||
var id = input.id;
|
||||
|
||||
// See if the DOM node with the given ID already exists.
|
||||
@ -29,7 +28,7 @@ module.exports = function render(input, out) {
|
||||
out.element(tagName, { id: id });
|
||||
}
|
||||
|
||||
componentsContext.$__preserveDOMNode(id, bodyOnly);
|
||||
globalComponentsContext.$__preserveDOMNode(id, bodyOnly);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,6 +96,10 @@ function nextComponentId() {
|
||||
return 'b' + ((markoGlobal.uid)++);
|
||||
}
|
||||
|
||||
function nextComponentIdProvider(out) {
|
||||
return nextComponentId;
|
||||
}
|
||||
|
||||
function getElementById(doc, id) {
|
||||
return doc.getElementById(id);
|
||||
}
|
||||
@ -104,9 +108,9 @@ function attachBubblingEvent(componentDef, handlerMethodName, extraArgs) {
|
||||
if (handlerMethodName) {
|
||||
var id = componentDef.id;
|
||||
if (extraArgs) {
|
||||
var isRerenderInBrowser = componentDef.$__out.global.components.$__isRerenderInBrowser;
|
||||
var isRerenderInBrowser = componentDef.$__globalComponentsContext.$__isRerenderInBrowser;
|
||||
|
||||
if (isRerenderInBrowser) {
|
||||
if (isRerenderInBrowser === true) {
|
||||
// If we are bootstrapping a page rendered on the server
|
||||
// we need to put the actual event args on the UI component
|
||||
// since we will not actually be updating the DOM
|
||||
@ -146,7 +150,7 @@ exports.$__getComponentForEl = getComponentForEl;
|
||||
exports.$__emitLifecycleEvent = emitLifecycleEvent;
|
||||
exports.$__destroyComponentForEl = destroyComponentForEl;
|
||||
exports.$__destroyElRecursive = destroyElRecursive;
|
||||
exports.$__nextComponentId = nextComponentId;
|
||||
exports.$__nextComponentIdProvider = nextComponentIdProvider;
|
||||
exports.$__getElementById = getElementById;
|
||||
exports.$__attachBubblingEvent = attachBubblingEvent;
|
||||
exports.$__getMarkoPropsFromEl = getMarkoPropsFromEl;
|
||||
|
||||
@ -1,17 +1,10 @@
|
||||
var KEY = Symbol();
|
||||
function nextComponentIdProvider(out) {
|
||||
var prefix = out.global.componentIdPrefix || 's'; // "s" is for server (we use "b" for the browser)
|
||||
var nextId = 0;
|
||||
|
||||
function UniqueId(out) {
|
||||
this.prefix = out.global.componentIdPrefix || 's'; // "s" is for server (we use "b" for the browser)
|
||||
this.nextId = 0;
|
||||
}
|
||||
|
||||
function nextComponentId(out) {
|
||||
var global = out.global;
|
||||
|
||||
var idProvider = global[KEY] ||
|
||||
(global[KEY] = new UniqueId(out));
|
||||
|
||||
return idProvider.prefix + (idProvider.nextId++);
|
||||
return function nextComponentId() {
|
||||
return prefix + (nextId++);
|
||||
};
|
||||
}
|
||||
|
||||
function attachBubblingEvent(componentDef, handlerMethodName, extraArgs) {
|
||||
@ -44,6 +37,6 @@ function attachBubblingEvent(componentDef, handlerMethodName, extraArgs) {
|
||||
}
|
||||
}
|
||||
|
||||
exports.$__nextComponentId = nextComponentId;
|
||||
exports.$__nextComponentIdProvider = nextComponentIdProvider;
|
||||
exports.$__isServer = true;
|
||||
exports.$__attachBubblingEvent = attachBubblingEvent;
|
||||
|
||||
@ -1 +1 @@
|
||||
<html><head><title>Welcome Frank</title></head><body><div id="s0">Hello</div><script>(function(){var w=window;w.$components=(w.$components||[]).concat({"w":[["s0",0,{},{"d":null,"b":null}]],"t":["/marko-test$1.0.0/autotests/async-render/components-await-title/components/hello/index.marko"]})||w.$components})()</script></body></html>
|
||||
<html><head><title>Welcome Frank</title></head><body><div id="s0">Hello</div><script>(function(){var w=window;w.$components=(w.$components||[]).concat({"w":[["s0",0,{},{"_":1}]],"t":["/marko-test$1.0.0/autotests/async-render/components-await-title/components/hello/index.marko"]})||w.$components})()</script></body></html>
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
class {
|
||||
}
|
||||
<div>
|
||||
<span.name>${out.global.name}</span>
|
||||
</div>
|
||||
@ -0,0 +1,12 @@
|
||||
class {
|
||||
onCreate() {
|
||||
this.state = {
|
||||
count: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<div>
|
||||
<hello/>
|
||||
<span.count>${state.count}</span>
|
||||
</div>
|
||||
@ -0,0 +1,18 @@
|
||||
var expect = require('chai').expect;
|
||||
|
||||
module.exports = function(helpers) {
|
||||
var component = helpers.mount(require('./index.marko'), {
|
||||
$global: {
|
||||
name: 'Frank'
|
||||
}
|
||||
});
|
||||
|
||||
expect(component.el.querySelector('.name').innerHTML).to.equal('Frank');
|
||||
expect(component.el.querySelector('.count').innerHTML).to.equal('1');
|
||||
|
||||
component.state.count++;
|
||||
component.update();
|
||||
|
||||
expect(component.el.querySelector('.name').innerHTML).to.equal('Frank');
|
||||
expect(component.el.querySelector('.count').innerHTML).to.equal('2');
|
||||
};
|
||||
@ -1,7 +0,0 @@
|
||||
var foo = require('./path/to/foo');
|
||||
|
||||
module.exports = {
|
||||
onServerCreate(input, out) {
|
||||
this.foo = foo.getValue(out);
|
||||
}
|
||||
};
|
||||
@ -1,7 +1,11 @@
|
||||
class {
|
||||
onCreate(input, out) {
|
||||
onCreate() {
|
||||
this.state = {
|
||||
count: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<div>
|
||||
<span.name>${out.global.name}</span>
|
||||
<span.count>${state.count}</span>
|
||||
</div>
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
class {
|
||||
|
||||
}
|
||||
|
||||
<div>
|
||||
</div>
|
||||
@ -4,5 +4,5 @@ class {
|
||||
}
|
||||
}
|
||||
<div>
|
||||
<app-wrapper/>
|
||||
<app-hello key="hello"/>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
lasso-page dependencies=data.browserDependencies lasso=data.lasso
|
||||
|
||||
$ {
|
||||
out.global.name = 'Frank';
|
||||
out.global.serializedGlobals = {
|
||||
name: true
|
||||
};
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
html lang="en"
|
||||
head
|
||||
|
||||
@ -4,67 +4,23 @@ var expect = require('chai').expect;
|
||||
describe(path.basename(__dirname), function() {
|
||||
it('should allow attributes to not be updated', function() {
|
||||
var app = window.app;
|
||||
var noUpdateComponent = app.getComponent('no-update-attr');
|
||||
var foo = noUpdateComponent.el.getAttribute('data-foo');
|
||||
expect(foo).to.equal('server');
|
||||
var helloComponent = app.getComponent('hello');
|
||||
|
||||
noUpdateComponent.input = {
|
||||
name: 'browser'
|
||||
};
|
||||
|
||||
noUpdateComponent.update();
|
||||
expect(helloComponent.el.querySelector('.name').innerHTML).to.equal('Frank');
|
||||
expect(helloComponent.el.querySelector('.count').innerHTML).to.equal('1');
|
||||
|
||||
expect(foo).to.equal('server');
|
||||
});
|
||||
helloComponent.state.count++;
|
||||
helloComponent.update();
|
||||
|
||||
it('should allow a root element to not be updated', function() {
|
||||
var app = window.app;
|
||||
var noUpdateComponent = app.getComponent('no-update-el');
|
||||
expect(helloComponent.el.querySelector('.name').innerHTML).to.equal('Frank');
|
||||
expect(helloComponent.el.querySelector('.count').innerHTML).to.equal('2');
|
||||
|
||||
expect(noUpdateComponent.getNoUpdateEl().getAttribute('data-foo')).to.equal('server');
|
||||
expect(noUpdateComponent.getNoUpdateEl().innerHTML).to.equal('server');
|
||||
app.forceUpdate();
|
||||
app.update();
|
||||
|
||||
noUpdateComponent.input = {
|
||||
name: 'browser'
|
||||
};
|
||||
|
||||
noUpdateComponent.update();
|
||||
|
||||
expect(noUpdateComponent.getNoUpdateEl().getAttribute('data-foo')).to.equal('server');
|
||||
expect(noUpdateComponent.getNoUpdateEl().innerHTML).to.equal('server');
|
||||
});
|
||||
|
||||
it('should allow a nested element to not be updated', function() {
|
||||
var app = window.app;
|
||||
var noUpdateComponent = app.getComponent('no-update-el-nested');
|
||||
|
||||
expect(noUpdateComponent.getNoUpdateEl().getAttribute('data-foo')).to.equal('server');
|
||||
expect(noUpdateComponent.getNoUpdateEl().innerHTML).to.equal('server');
|
||||
|
||||
noUpdateComponent.input = {
|
||||
name: 'browser'
|
||||
};
|
||||
|
||||
noUpdateComponent.update();
|
||||
|
||||
expect(noUpdateComponent.getNoUpdateEl().getAttribute('data-foo')).to.equal('server');
|
||||
expect(noUpdateComponent.getNoUpdateEl().innerHTML).to.equal('server');
|
||||
});
|
||||
|
||||
it('should allow a body element to not be updated', function() {
|
||||
var app = window.app;
|
||||
var noUpdateComponent = app.getComponent('no-update-body-el');
|
||||
|
||||
expect(noUpdateComponent.getNoUpdateEl().getAttribute('data-foo')).to.equal('server');
|
||||
expect(noUpdateComponent.getNoUpdateEl().innerHTML).to.equal('server');
|
||||
|
||||
noUpdateComponent.input = {
|
||||
name: 'browser'
|
||||
};
|
||||
|
||||
noUpdateComponent.update();
|
||||
|
||||
expect(noUpdateComponent.getNoUpdateEl().getAttribute('data-foo')).to.equal('browser');
|
||||
expect(noUpdateComponent.getNoUpdateEl().innerHTML).to.equal('server');
|
||||
helloComponent = app.getComponent('hello');
|
||||
expect(helloComponent.el.querySelector('.name').innerHTML).to.equal('Frank');
|
||||
expect(helloComponent.el.querySelector('.count').innerHTML).to.equal('2');
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user