diff --git a/benchmark/size/minify.js b/benchmark/size/minify.js index 3539b57c8..c1fead3dc 100644 --- a/benchmark/size/minify.js +++ b/benchmark/size/minify.js @@ -38,10 +38,10 @@ var minifiers = { const out = gcc.compile(options); - // if (out.errors && out.errors.length) { - // console.error(out.errors); - // throw new Error(`Minification failed for ${file}`); - // } + if (out.errors && out.errors.length) { + console.error(out.errors); + throw new Error(`Minification failed for ${file}`); + } return out.compiledCode; }, uglify: function minifyUglifyJS(src, file) { @@ -139,4 +139,4 @@ promiseChain.then(() => { } console.log('Minification complete.'); -}); \ No newline at end of file +}); diff --git a/benchmark/size/package.json b/benchmark/size/package.json index d9cbe6336..36dfff9bb 100644 --- a/benchmark/size/package.json +++ b/benchmark/size/package.json @@ -11,7 +11,7 @@ "build-react": "npm run bundle-react --silent && node minify.js react", "build-inferno": "npm run bundle-inferno --silent && node minify.js inferno", "bundle": "mkdir -p build/bundles && npm run bundle-marko && npm run bundle-react && npm run bundle-vue && npm run bundle-preact && npm run bundle-inferno", - "bundle-marko": "node ../../scripts/build && NODE_ENV=production rollup -c marko/rollup.config.js", + "bundle-marko": "node ../../scripts/build src && NODE_ENV=production rollup -c marko/rollup.config.js", "bundle-react": "NODE_ENV=production rollup -c react/rollup.config.js", "bundle-preact": "NODE_ENV=production rollup -c preact/rollup.config.js", "bundle-vue": "NODE_ENV=production rollup -c vue/rollup.config.js", diff --git a/package.json b/package.json index a72c1d3af..471a4a612 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ }, "scripts": { "build": "node scripts/build.js", + "build-src": "node scripts/build.js src", "prepublish": "npm run build", "test": "npm run jshint -s && npm run mocha -s && npm run test-components -s && npm run test-components-deprecated -s", "test-ci": "npm run test-generate-coverage && npm run build && NODE_ENV=production npm run test", diff --git a/scripts/build.js b/scripts/build.js index a16a6ce53..f04c6621e 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -16,34 +16,44 @@ const babelOptions = { ] }; -buildDir('src', 'dist', { - babelExclude: [ - '/taglibs/async/client-reorder-runtime.min.js' - ], - babelOptions -}); -var buildConstants = { - isDebug: false -}; +var target = process.argv[2]; + +var shouldBuildSrc = true; +var shouldBuildTest = true; + +if (target === 'src') { + shouldBuildTest = false; +} + +if (shouldBuildSrc) { + buildDir('src', 'dist', { + babelExclude: [ + '/taglibs/async/client-reorder-runtime.min.js' + ], + babelOptions + }); +} fs.writeFileSync( path.join(__dirname, '../dist/build.json'), JSON.stringify({ isDebug: false }, null, 4), { encoding: 'utf8' }); -buildDir('test', 'test-dist', { - babelExclude: [ - '*expected*.*', - 'input.js*' - ], - exclude: [ - '/generated', - '*.marko.js', - '*.skip', - '*.generated.*', - '*actual*.*', - 'actualized-expected.html*' - ], - babelOptions -}); +if (shouldBuildTest) { + buildDir('test', 'test-dist', { + babelExclude: [ + '*expected*.*', + 'input.js*' + ], + exclude: [ + '/generated', + '*.marko.js', + '*.skip', + '*.generated.*', + '*actual*.*', + 'actualized-expected.html*' + ], + babelOptions + }); +} diff --git a/src/compiler/Builder.js b/src/compiler/Builder.js index 47b264909..949ebb3fc 100644 --- a/src/compiler/Builder.js +++ b/src/compiler/Builder.js @@ -130,15 +130,22 @@ class Builder { return new MemberExpression({object, property, computed}); } + /** + * Generates code that joins all of the arguments using `+` (BinaryExpression) + * + * @param {Array} args If the args object is not an array then `arguments` is used + * @return {Node} The resulting Node + */ concat(args) { var prev; let operator = '+'; + args = Array.isArray(args) ? args : Array.prototype.slice.call(arguments, 0); - for (var i=1; i { + this.body.appendChild(node); + }); + } + insertBefore(newNode, referenceNode) { ok(this.body, 'Node does not support child nodes: ' + this); this.body.insertBefore(newNode, referenceNode); diff --git a/src/compiler/util/vdom/VDOMOptimizer.js b/src/compiler/util/vdom/VDOMOptimizer.js index 47fb8fed0..e07da4e3d 100644 --- a/src/compiler/util/vdom/VDOMOptimizer.js +++ b/src/compiler/util/vdom/VDOMOptimizer.js @@ -53,19 +53,23 @@ class OptimizerContext { } class NodeVDOM extends Node { - constructor(variableIdentifier) { + constructor(variableIdentifier, isComponent) { super('NodeVDOM'); this.variableIdentifier = variableIdentifier; + this.isComponent = isComponent; } writeCode(writer) { var builder = writer.builder; + var funcCallArgs = [ this.variableIdentifier ]; + + if (this.isComponent) { + funcCallArgs.push(builder.identifier('component')); + } let funcCall = builder.functionCall( builder.identifier('n'), - [ - this.variableIdentifier - ]); + funcCallArgs); if (this.isChild) { writer.write('.'); @@ -89,16 +93,16 @@ function generateNodesForArray(nodes, context, options) { function generateStaticNode(node) { if (node.type === 'HtmlElementVDOM') { node.createElementId = context.helper('createElement'); + + node.setConstId(builder.functionCall(optimizerContext.nextConstIdFunc, [])); }/* else { node.createTextId = context.importModule('marko_createText', 'marko/vdom/createText'); }*/ - node.nextConstId = builder.functionCall(optimizerContext.nextConstIdFunc, []); - node.isStaticRoot = true; let staticNodeId = context.addStaticVar('marko_node' + (optimizerContext.nextNodeId++), node); - return new NodeVDOM(staticNodeId); + return new NodeVDOM(staticNodeId, context.isComponent); } function handleStaticAttributes(node) { @@ -131,6 +135,7 @@ function generateNodesForArray(nodes, context, options) { finalNodes.push(node); } + node.finalizeProperties(context); } else { finalNodes.push(node); } @@ -157,4 +162,4 @@ class VDOMOptimizer { } } -module.exports = VDOMOptimizer; \ No newline at end of file +module.exports = VDOMOptimizer; diff --git a/src/components/Component.js b/src/components/Component.js index 257704198..533511b3e 100644 --- a/src/components/Component.js +++ b/src/components/Component.js @@ -7,53 +7,27 @@ var getComponentsContext = require('./ComponentsContext').___getComponentsContex var componentsUtil = require('./util'); var componentLookup = componentsUtil.___componentLookup; var emitLifecycleEvent = componentsUtil.___emitLifecycleEvent; -var destroyComponentForEl = componentsUtil.___destroyComponentForEl; -var destroyElRecursive = componentsUtil.___destroyElRecursive; -var getElementById = componentsUtil.___getElementById; +var destroyNodeRecursive = componentsUtil.___destroyNodeRecursive; var EventEmitter = require('events-light'); var RenderResult = require('../runtime/RenderResult'); var SubscriptionTracker = require('listener-tracker'); var inherit = require('raptor-util/inherit'); var updateManager = require('./update-manager'); var morphdom = require('../morphdom'); -var eventDelegation = require('./event-delegation'); var slice = Array.prototype.slice; -var MORPHDOM_SKIP = true; - var COMPONENT_SUBSCRIBE_TO_OPTIONS; var NON_COMPONENT_SUBSCRIBE_TO_OPTIONS = { addDestroyListener: false }; -function outNoop() { /* jshint -W040 */ return this; } - var emit = EventEmitter.prototype.emit; function removeListener(removeEventListenerHandle) { removeEventListenerHandle(); } -function checkCompatibleComponent(globalComponentsContext, el) { - var component = el._w; - while(component) { - var id = component.id; - var newComponentDef = globalComponentsContext.___componentsById[id]; - if (newComponentDef && component.___type == newComponentDef.___component.___type) { - break; - } - - var rootFor = component.___rootFor; - if (rootFor) { - component = rootFor; - } else { - component.___destroyShallow(); - break; - } - } -} - function handleCustomEventWithMethodListener(component, targetMethodName, args, extraArgs) { // Remove the "eventType" argument args.push(component); @@ -72,16 +46,12 @@ function handleCustomEventWithMethodListener(component, targetMethodName, args, targetMethod.apply(targetComponent, args); } -function getElIdHelper(component, componentElId, index) { - var id = component.id; +function resolveKeyHelper(key, index) { + return index ? key + '_' + index : key; +} - var elId = componentElId != null ? id + '-' + componentElId : id; - - if (index != null) { - elId += '[' + index + ']'; - } - - return elId; +function resolveComponentIdHelper(component, key, index) { + return component.id + '-' + resolveKeyHelper(key, index); } /** @@ -158,46 +128,10 @@ function checkInputChanged(existingComponent, oldInput, newInput) { return false; } -function onNodeDiscarded(node) { - if (node.nodeType === 1) { - destroyComponentForEl(node); - } -} - -function onBeforeNodeDiscarded(node) { - return eventDelegation.___handleNodeDetach(node); -} - -function onBeforeElUpdated(fromEl, key, globalComponentsContext) { - if (key) { - var preserved = globalComponentsContext.___preserved[key]; - - if (preserved === true) { - // Don't morph elements that are associated with components that are being - // reused or elements that are being preserved. For components being reused, - // the morphing will take place when the reused component updates. - return MORPHDOM_SKIP; - } else { - // We may need to destroy a Component associated with the current element - // if a new UI component was rendered to the same element and the types - // do not match - checkCompatibleComponent(globalComponentsContext, fromEl); - } - } -} - -function onBeforeElChildrenUpdated(el, key, globalComponentsContext) { - if (key) { - var preserved = globalComponentsContext.___preservedBodies[key]; - if (preserved === true) { - // Don't morph the children since they are preserved - return MORPHDOM_SKIP; - } - } -} - -function onNodeAdded(node, globalComponentsContext) { - eventDelegation.___handleNodeAttach(node, globalComponentsContext.___out); +function getNodes(component) { + var nodes = []; + component.___forEachNode(nodes.push.bind(nodes)); + return nodes; } var componentProto; @@ -210,9 +144,9 @@ var componentProto; function Component(id) { EventEmitter.call(this); this.id = id; - this.el = null; this.___state = null; - this.___roots = null; + this.___startNode = null; + this.___endNode = null; this.___subscriptions = null; this.___domEventListenerHandles = null; this.___bubblingDomEvents = null; // Used to keep track of bubbling DOM events for components rendered on the server @@ -229,6 +163,8 @@ function Component(id) { this.___settingInput = false; this.___document = undefined; + + this.___keyedElements = {}; } Component.prototype = componentProto = { @@ -264,63 +200,57 @@ Component.prototype = componentProto = { return emit.apply(this, arguments); } }, - getElId: function (componentElId, index) { - return getElIdHelper(this, componentElId, index); + getElId: function (key, index) { + return resolveComponentIdHelper(this, key, index); }, - getEl: function (componentElId, index) { - var doc = this.___document; - - if (componentElId != null) { - return getElementById(doc, getElIdHelper(this, componentElId, index)); + getEl: function (key, index) { + if (key) { + return this.___keyedElements[resolveKeyHelper(key, index)]; } else { - return this.el || getElementById(doc, getElIdHelper(this)); + return this.___startNode; } }, - getEls: function(id) { + getEls: function(key) { + key = key + '[]'; + var els = []; var i = 0; var el; - while((el = this.getEl(id, i))) { + while((el = this.getEl(key, i))) { els.push(el); i++; } return els; }, - getComponent: function(id, index) { - return componentLookup[getElIdHelper(this, id, index)]; + getComponent: function(key, index) { + return componentLookup[resolveComponentIdHelper(this, key, index)]; }, - getComponents: function(id) { + getComponents: function(key) { + key = key + '[]'; + var components = []; var i = 0; var component; - while((component = componentLookup[getElIdHelper(this, id, i)])) { + while((component = componentLookup[resolveComponentIdHelper(this, key, i)])) { components.push(component); i++; } return components; }, - destroy: function() { + destroy: function(onBeforeNodeDiscarded) { if (this.___destroyed) { return; } - var els = this.els; + var nodes = getNodes(this); this.___destroyShallow(); - var rootComponents = this.___rootComponents; - if (rootComponents) { - rootComponents.forEach(function(rootComponent) { - rootComponent.___destroy(); - }); - } + nodes.forEach(function(node) { + destroyNodeRecursive(node); - els.forEach(function(el) { - destroyElRecursive(el); - - var parentNode = el.parentNode; - if (parentNode) { - parentNode.removeChild(el); + if (!onBeforeNodeDiscarded || onBeforeNodeDiscarded(node) != false) { + node.parentNode.removeChild(node); } }); }, @@ -333,7 +263,9 @@ Component.prototype = componentProto = { emitLifecycleEvent(this, 'destroy'); this.___destroyed = true; - this.el = null; + this.___startNode.___markoComponent = undefined; + + this.___startNode = this.___endNode = null; // Unsubscribe from all DOM events this.___removeDOMEventListeners(); @@ -452,6 +384,7 @@ Component.prototype = componentProto = { ___queueUpdate: function() { if (!this.___updateQueued) { + this.___updateQueued = true; updateManager.___queueComponentUpdate(this); } }, @@ -512,7 +445,10 @@ Component.prototype = componentProto = { if (!renderer) { throw TypeError(); } - var fromEls = self.___getRootEls({}); + + var startNode = this.___startNode; + var endNodeNextSibling = this.___endNode.nextSibling; + var doc = self.___document; var input = this.___renderInput || this.___input; var globalData = this.___global; @@ -523,18 +459,6 @@ Component.prototype = componentProto = { out.sync(); out.___document = self.___document; - if (isRerenderInBrowser === true) { - out.e = - out.be = - out.ee = - out.t = - out.h = - out.w = - out.write = - out.html = - outNoop; - } - var componentsContext = getComponentsContext(out); var globalComponentsContext = componentsContext.___globalContext; globalComponentsContext.___rerenderComponent = self; @@ -544,68 +468,40 @@ Component.prototype = componentProto = { var result = new RenderResult(out); - if (isRerenderInBrowser !== true) { - var targetNode = out.___getOutput(); + var targetNode = out.___getOutput(); - var fromEl; - - var targetEl = targetNode.___firstChild; - while (targetEl) { - var nodeName = targetEl.___nodeName; - - if (nodeName === 'HTML') { - fromEl = document.documentElement; - } else if (nodeName === 'BODY') { - fromEl = document.body; - } else if (nodeName === 'HEAD') { - fromEl = document.head; - } else { - fromEl = fromEls[targetEl.id]; - } - - if (fromEl) { - morphdom( - fromEl, - targetEl, - globalComponentsContext, - onNodeAdded, - onBeforeElUpdated, - onBeforeNodeDiscarded, - onNodeDiscarded, - onBeforeElChildrenUpdated); - } - - targetEl = targetEl.___nextSibling; - } - } + morphdom( + startNode.parentNode, + startNode, + endNodeNextSibling, + targetNode, + doc, + componentsContext); result.afterInsert(doc); - - out.emit('___componentsInitialized'); }); this.___reset(); }, - ___getRootEls: function(rootEls) { - var i, len; + ___detach: function() { + var fragment = this.___document.createDocumentFragment(); + this.___forEachNode(fragment.appendChild.bind(fragment)); + return fragment; + }, - var componentEls = this.els; + ___forEachNode: function(callback) { + var currentNode = this.___startNode; + var endNode = this.___endNode; - for (i=0, len=componentEls.length; i 1) { - var fragment = component.___document.createDocumentFragment(); - els.forEach(function(el) { - fragment.appendChild(el); - }); - return fragment; - } else { - return els[0]; - } + return component.___detach(); }, function afterInsert(component) { return component; diff --git a/src/components/ComponentDef.js b/src/components/ComponentDef.js index e1ef621ee..b005d376b 100644 --- a/src/components/ComponentDef.js +++ b/src/components/ComponentDef.js @@ -3,48 +3,50 @@ var repeatedRegExp = /\[\]$/; var componentUtil = require('./util'); var attachBubblingEvent = componentUtil.___attachBubblingEvent; var extend = require('raptor-util/extend'); +var KeySequence = require('./KeySequence'); + +/* +var FLAG_WILL_RERENDER_IN_BROWSER = 1; +var FLAG_HAS_BODY_EL = 2; +var FLAG_HAS_HEAD_EL = 4; +*/ /** * A ComponentDef is used to hold the metadata collected at runtime for * 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, globalComponentsContext, componentStack, componentStackLen) { +function ComponentDef(component, componentId, globalComponentsContext) { this.___globalComponentsContext = globalComponentsContext; // The AsyncWriter that this component is associated with - this.___componentStack = componentStack; - this.___componentStackLen = componentStackLen; this.___component = component; this.id = componentId; - this.___roots = null; // IDs of root elements if there are multiple root elements - this.___children = null; // An array of nested ComponentDef instances this.___domEvents = undefined; // An array of DOM events that need to be added (in sets of three) this.___isExisting = false; - this.___willRerenderInBrowser = false; + this.___renderBoundary = false; + this.___flags = 0; this.___nextIdIndex = 0; // The unique integer to use for the next scoped ID + + this.___keySequence = null; + + this.___preservedDOMNodes = null; } ComponentDef.prototype = { - ___end: function() { - this.___componentStack.length = this.___componentStackLen; + + ___nextKey: function(key) { + var keySequence = this.___keySequence || (this.___keySequence = new KeySequence()); + return keySequence.___nextKey(key); }, - /** - * Register a nested component for this component. We maintain a tree of components - * so that we can instantiate nested components before their parents. - */ - ___addChild: function (componentDef) { - var children = this.___children; - - if (children) { - children.push(componentDef); - } else { - this.___children = [componentDef]; - } + ___preserveDOMNode: function(key, bodyOnly) { + var lookup = this.___preservedDOMNodes || (this.___preservedDOMNodes = {}); + lookup[key] = bodyOnly ? 2 : 1; }, + /** * This helper method generates a unique and fully qualified DOM element ID * that is unique within the scope of the current component. This method prefixes @@ -88,15 +90,15 @@ ComponentDef.prototype = { * Returns the next auto generated unique ID for a nested DOM element or nested DOM component */ ___nextComponentId: function() { - var id = this.id; - - return id === null ? - this.___globalComponentsContext.___nextComponentId(this.___out) : - id + '-c' + (this.___nextIdIndex++); + return this.id + '-c' + (this.___nextIdIndex++); }, d: function(handlerMethodName, extraArgs) { return attachBubblingEvent(this, handlerMethodName, extraArgs); + }, + + get ___type() { + return this.___component.___type; } }; @@ -146,10 +148,11 @@ ComponentDef.___deserialize = function(o, types, globals, registry) { component.___global = globals; return { + id: id, ___component: component, - ___roots: extra.r, + ___boundary: extra.r, ___domEvents: extra.d, - ___willRerenderInBrowser: extra._ === 1 + ___flags: extra.f || 0 }; }; diff --git a/src/components/ComponentsContext.js b/src/components/ComponentsContext.js index abf7545eb..32a6f4fd7 100644 --- a/src/components/ComponentsContext.js +++ b/src/components/ComponentsContext.js @@ -1,117 +1,47 @@ 'use strict'; +var GlobalComponentsContext = require('./GlobalComponentsContext'); -var ComponentDef = require('./ComponentDef'); -var componentsUtil = require('./util'); +function ComponentsContext(out, parentComponentsContext) { + var globalComponentsContext; + var componentDef; + var components; -var beginComponent = require('./beginComponent'); + if (parentComponentsContext) { + components = parentComponentsContext.___components; + globalComponentsContext = parentComponentsContext.___globalContext; + componentDef = parentComponentsContext.___componentDef; + } else { + globalComponentsContext = out.global.___components; + if (globalComponentsContext === undefined) { + out.global.___components = globalComponentsContext = new GlobalComponentsContext(out); + } + components = []; + } -var EMPTY_OBJECT = {}; - -function GlobalComponentsContext(out) { - this.___roots = []; - this.___preserved = EMPTY_OBJECT; - this.___preservedBodies = EMPTY_OBJECT; - this.___componentsById = {}; + this.___globalContext = globalComponentsContext; + this.___components = components; this.___out = out; - this.___rerenderComponent = undefined; - this.___nextIdLookup = null; - this.___nextComponentId = componentsUtil.___nextComponentIdProvider(out); + this.___componentDef = componentDef; } -GlobalComponentsContext.prototype = { +ComponentsContext.prototype = { ___initComponents: function(doc) { - var topLevelComponentDefs = null; + var componentDefs = this.___components; - this.___roots.forEach(function(root) { - var children = root.___children; - if (children) { - // NOTE: ComponentsContext.___initClientRendered is provided by - // index-browser.js to avoid a circular dependency - ComponentsContext.___initClientRendered(children, doc); - if (topLevelComponentDefs === null) { - topLevelComponentDefs = children; - } else { - topLevelComponentDefs = topLevelComponentDefs.concat(children); - } - } - }); + ComponentsContext.___initClientRendered(componentDefs, doc); - this.___roots = null; + this.___out.emit('___componentsInitialized'); // Reset things stored in global since global is retained for // future renders this.___out.global.___components = undefined; - return topLevelComponentDefs; + return componentDefs; }, - ___preserveDOMNode: function(elId, bodyOnly) { - var preserved = bodyOnly === true ? this.___preservedBodies : this.___preserved; - if (preserved === EMPTY_OBJECT) { - if (bodyOnly === true) { - preserved = this.___preservedBodies = {}; - } else { - preserved = this.___preserved = {}; - } - } - 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 + ']'; - } -}; - -function ComponentsContext(out, parentComponentsContext, shouldAddGlobalRoot) { - var root; - - var globalComponentsContext; - - if (parentComponentsContext === undefined) { - 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); - } - } else { - globalComponentsContext = parentComponentsContext.___globalContext; - var parentComponentStack = parentComponentsContext.___componentStack; - root = parentComponentStack[parentComponentStack.length-1]; - } - - this.___globalContext = globalComponentsContext; - this.___out = out; - this.___componentStack = [root]; -} - -ComponentsContext.prototype = { - ___createNestedComponentsContext: function(nestedOut) { - return new ComponentsContext(nestedOut, this); - }, - ___beginComponent: beginComponent, - - ___nextComponentId: function() { - var componentStack = this.___componentStack; - var parentComponentDef = componentStack[componentStack.length - 1]; - return parentComponentDef.___nextComponentId(); - } }; function getComponentsContext(out) { - return out.data.___components || (out.data.___components = new ComponentsContext(out)); + return out.___components || (out.___components = new ComponentsContext(out)); } module.exports = exports = ComponentsContext; diff --git a/src/components/GlobalComponentsContext.js b/src/components/GlobalComponentsContext.js new file mode 100644 index 000000000..1e2188372 --- /dev/null +++ b/src/components/GlobalComponentsContext.js @@ -0,0 +1,18 @@ +var nextComponentIdProvider = require('./util').___nextComponentIdProvider; +var KeySequence = require('./KeySequence'); + +function GlobalComponentsContext(out) { + this.___preservedEls = {}; + this.___preservedElBodies = {}; + this.___renderedComponentsById = {}; + this.___rerenderComponent = undefined; + this.___nextComponentId = nextComponentIdProvider(out); +} + +GlobalComponentsContext.prototype = { + ___createKeySequence: function() { + return new KeySequence(); + } +}; + +module.exports = GlobalComponentsContext; diff --git a/src/components/KeySequence.js b/src/components/KeySequence.js new file mode 100644 index 000000000..ed73040da --- /dev/null +++ b/src/components/KeySequence.js @@ -0,0 +1,27 @@ + function KeySequence() { + this.___lookup = {}; +} + +KeySequence.prototype = { + ___nextKey: function(key) { + // var len = key.length; + // var lastChar = key[len-1]; + // if (lastChar === ']') { + // key = key.substring(0, len-2); + // } + var lookup = this.___lookup; + + var currentIndex = lookup[key]++; + if (!currentIndex) { + lookup[key] = 1; + currentIndex = 0; + return key; + } else { + return key + '_' + currentIndex; + } + + + } +}; + +module.exports = KeySequence; diff --git a/src/components/attach-detach.js b/src/components/attach-detach.js index 21309a2b0..8d82e0eff 100644 --- a/src/components/attach-detach.js +++ b/src/components/attach-detach.js @@ -2,14 +2,15 @@ var eventDelegation = require('./event-delegation'); var delegateEvent = eventDelegation.___delegateEvent; var getEventFromEl = eventDelegation.___getEventFromEl; -var componentsUtil = require('./util'); -var destroyElRecursive = componentsUtil.___destroyElRecursive; -var destroyComponentForEl = componentsUtil.___destroyComponentForEl; +// var componentsUtil = require('./util'); +// var destroyNodeRecursive = componentsUtil.___destroyNodeRecursive; +// var destroyComponentForNode = componentsUtil.___destroyComponentForNode; -function handleNodeAttach(node, out) { +function handleNodeAttach(node, componentsContext) { if (node.nodeType === 1) { var target = getEventFromEl(node, 'onattach'); if (target) { + var out = componentsContext.___out; var data = out.data; var attachTargets = data.___attachTargets; @@ -39,8 +40,6 @@ function handleNodeDetach(node) { delegateEvent(node, target, { preventDefault: function() { allowDetach = false; - destroyComponentForEl(node); - destroyElRecursive(node); }, detach: function() { var parentNode = node.parentNode; diff --git a/src/components/beginComponent-browser.js b/src/components/beginComponent-browser.js index c4ba643a9..b4e61922f 100644 --- a/src/components/beginComponent-browser.js +++ b/src/components/beginComponent-browser.js @@ -1,17 +1,14 @@ var ComponentDef = require('./ComponentDef'); -module.exports = function(component, isSplitComponent) { - var componentStack = this.___componentStack; - var origLength = componentStack.length; - var parentComponentDef = componentStack[origLength - 1]; - +module.exports = function beginComponent(componentsContext, component, isSplitComponen, parentComponentDeft) { var componentId = component.id; - var componentDef = new ComponentDef(component, componentId, this.___globalContext, componentStack, origLength); - parentComponentDef.___addChild(componentDef); - this.___globalContext.___componentsById[componentId] = componentDef; - - componentStack.push(componentDef); + var globalContext = componentsContext.___globalContext; + var componentDef = componentsContext.___componentDef = new ComponentDef(component, componentId, globalContext); + globalContext.___renderedComponentsById[componentId] = true; + componentsContext.___components.push(componentDef); + var out = componentsContext.___out; + out.bc(component); return componentDef; }; diff --git a/src/components/beginComponent.js b/src/components/beginComponent.js index ee9f67b53..dba1c8766 100644 --- a/src/components/beginComponent.js +++ b/src/components/beginComponent.js @@ -3,8 +3,13 @@ const ComponentDef = require('./ComponentDef'); const hasRenderBodyKey = Symbol.for("hasRenderBody"); +var FLAG_WILL_RERENDER_IN_BROWSER = 1; +// var FLAG_HAS_BODY_EL = 2; +// var FLAG_HAS_HEAD_EL = 4; + function isInputSerializable(component) { var input = component.___input; + if (!input) { return true; } @@ -16,29 +21,33 @@ function isInputSerializable(component) { } } -module.exports = function beginComponent(component, isSplitComponent) { - var componentStack = this.___componentStack; - var origLength = componentStack.length; - var parentComponentDef = componentStack[origLength - 1]; +module.exports = function beginComponent(componentsContext, component, isSplitComponent, parentComponentDef) { + var globalContext = componentsContext.___globalContext; var componentId = component.id; - var componentDef = new ComponentDef(component, componentId, this.___globalContext, componentStack, origLength); + var componentDef = componentsContext.___componentDef = new ComponentDef(component, componentId, globalContext); // On the server - if (parentComponentDef.___willRerenderInBrowser === true) { - componentDef.___willRerenderInBrowser = true; - } else { - parentComponentDef.___addChild(componentDef); - if (isSplitComponent === false && - this.___out.global.noBrowserRerender !== true && - isInputSerializable(component)) { - - componentDef.___willRerenderInBrowser = true; - } + if (parentComponentDef && (parentComponentDef.___flags & FLAG_WILL_RERENDER_IN_BROWSER)) { + componentDef.___flags |= FLAG_WILL_RERENDER_IN_BROWSER; + return componentDef; } - componentStack.push(componentDef); + componentsContext.___components.push(componentDef); + + let out = componentsContext.___out; + + componentDef.___renderBoundary = true; + + if (isSplitComponent === false && + out.global.noBrowserRerender !== true && + isInputSerializable(component)) { + componentDef.___flags |= FLAG_WILL_RERENDER_IN_BROWSER; + out.w(''); + } else { + out.w(''); + } return componentDef; }; diff --git a/src/components/endComponent-browser.js b/src/components/endComponent-browser.js new file mode 100644 index 000000000..eae21057a --- /dev/null +++ b/src/components/endComponent-browser.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function endComponent(out) { + out.ee(); // endElement() (also works for VComponent nodes pushed on to the stack) +}; diff --git a/src/components/endComponent.js b/src/components/endComponent.js new file mode 100644 index 000000000..34d224b94 --- /dev/null +++ b/src/components/endComponent.js @@ -0,0 +1,7 @@ +'use strict'; + +module.exports = function endComponent(out, componentDef) { + if (componentDef.___renderBoundary) { + out.w(''); + } +}; diff --git a/src/components/index.js b/src/components/index.js index 6da4a563d..dacf6d7d5 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -3,12 +3,34 @@ var warp10 = require('warp10'); var escapeEndingScriptTagRegExp = /<\//g; -function flattenHelper(components, flattened, typesArray, typesLookup) { - for (var i = 0, len = components.length; i < len; i++) { + + +function getRenderedComponents(out, shouldIncludeAll) { + var componentsContext = out.___components; + if (componentsContext === null) { + return; + } + + // console.log('componentsContext:', componentsContext); + + var components = componentsContext.___components; + if (components.length === 0) { + return; + } + + // console.log('components:', components.map((componentDef) => { + // return { id: componentDef.id, type: componentDef.type}; + // })); + + var componentsFinal = []; + var typesLookup = {}; + var typesArray = []; + + for (var i = components.length - 1; i >= 0; i--) { var componentDef = components[i]; var id = componentDef.id; var component = componentDef.___component; - var rerenderInBrowser = componentDef.___willRerenderInBrowser; + var flags = componentDef.___flags; var state = component.state; var input = component.input; var typeName = component.typeName; @@ -36,14 +58,6 @@ function flattenHelper(components, flattened, typesArray, typesLookup) { typesLookup[typeName] = typeIndex; } - var children = componentDef.___children; - - if (children !== null) { - // Depth-first search (children should be initialized before parent) - flattenHelper(children, flattened, typesArray, typesLookup); - componentDef.___children = null; - } - var hasProps = false; let componentKeys = Object.keys(component); @@ -81,71 +95,23 @@ function flattenHelper(components, flattened, typesArray, typesLookup) { b: bubblingDomEvents, d: componentDef.___domEvents, e: customEvents, + f: flags ? flags : undefined, p: customEvents && scope, // Only serialize scope if we need to attach custom events - r: componentDef.___roots, + r: componentDef.___boundary, s: state, u: undefinedPropNames, - w: hasProps ? component : undefined, - _: rerenderInBrowser ? 1 : undefined + w: hasProps ? component : undefined }; - flattened.push([ + componentsFinal.push([ id, // 0 = id typeIndex, // 1 = type input, // 2 = input extra // 3 ]); } -} -function getRenderedComponents(out, shouldIncludeAll) { - var componentDefs; - var globalComponentsContext; - var outGlobal = out.global; - - if (shouldIncludeAll === true) { - globalComponentsContext = outGlobal.___components; - - if (globalComponentsContext === undefined) { - return undefined; - } - } else { - let componentsContext = out.data.___components; - if (componentsContext === undefined) { - return undefined; - } - let rootComponentDef = componentsContext.___componentStack[0]; - componentDefs = rootComponentDef.___children; - - if (componentDefs === null) { - return undefined; - } - - rootComponentDef.___children = null; - } - - var flattened = []; - var typesLookup = {}; - var typesArray = []; - - if (shouldIncludeAll === true) { - let roots = globalComponentsContext.___roots; - for (let i=0, len=roots.length; i=0; i--) { var componentDef = componentDefs[i]; - - if (componentDef.___children) { - initClientRendered(componentDef.___children, doc); - } - initComponent( componentDef, doc); @@ -172,9 +178,12 @@ function initServerRendered(renderedComponents, doc) { return; } + + doc = doc || defaultDocument; + // Ensure that event handlers to handle delegating events are // always attached before initializing any components - eventDelegation.___init(doc || defaultDocument); + eventDelegation.___init(doc); renderedComponents = warp10Finalize(renderedComponents); @@ -188,6 +197,65 @@ function initServerRendered(renderedComponents, doc) { componentDefs.forEach(function(componentDef) { componentDef = ComponentDef.___deserialize(componentDef, typesArray, serverRenderedGlobals, registry); + var componentId = componentDef.id; + var component = componentDef.___component; + + var startNode; + var endNode; + var flags = componentDef.___flags; + if ((flags & 6) === 6) { + startNode = document.head; + endNode = document.body; + } else if (flags & FLAG_HAS_BODY_EL) { + startNode = endNode = document.body; + } else if (flags & FLAG_HAS_HEAD_EL) { + startNode = endNode = document.head; + } else { + var startNodeComment = serverComponentStartNodes[componentId]; + if (!startNodeComment) { + indexServerComponentBoundaries(doc); + startNodeComment = serverComponentStartNodes[componentId]; + } + var endNodeComment = serverComponentEndNodes[componentId]; + + startNode = startNodeComment.nextSibling; + + if (startNode === endNodeComment) { + // Component has no output nodes so just mount to the start comment node + // and we will remove the end comment node + startNode = endNode = startNodeComment; + } else { + startNodeComment.parentNode.removeChild(startNodeComment); + + if (startNode.parentNode === document) { + endNode = startNode = document.documentElement; + } else { + // Remove the start and end comment nodes and use the inner nodes + // as the boundary + endNode = endNodeComment.previousSibling; + } + } + + if (endNodeComment) { + endNodeComment.parentNode.removeChild(endNodeComment); + } + } + + component.___keyedElements = keyedElementsByComponentId[componentId] || {}; + component.___startNode = startNode; + component.___endNode = endNode; + + delete keyedElementsByComponentId[componentId]; + + // Mark the start node so that we know we need to skip past this + // node when matching up children + startNode.___startNode = true; + + // Mark the end node so that when we attempt to find boundaries + // for nested UI components we don't accidentally go outside the boundary + // of the parent component + endNode.___endNode = true; + initComponent(componentDef, doc || defaultDocument); }); } diff --git a/src/components/jquery.js b/src/components/jquery.js index 33495b3b2..88d98126e 100644 --- a/src/components/jquery.js +++ b/src/components/jquery.js @@ -23,11 +23,11 @@ exports.patchComponent = function(jQuery) { var match = idRegExp.exec(arg); //Reset the search to 0 so the next call to exec will start from the beginning for the new string if (match != null) { - var componentElId = match[1]; + var key = match[1]; if (match[2] == null) { - return jQuery(self.getEl(componentElId)); + return jQuery(self.getEl(key)); } else { - return jQuery('#' + self.getElId(componentElId) + match[2]); + return jQuery(match[2].trim(), self.getEl(key)); } } else { var rootEl = self.getEl(); diff --git a/src/components/legacy/renderer-legacy.js b/src/components/legacy/renderer-legacy.js index 62ce853ff..ae6202672 100644 --- a/src/components/legacy/renderer-legacy.js +++ b/src/components/legacy/renderer-legacy.js @@ -4,8 +4,9 @@ var componentLookup = componentsUtil.___componentLookup; var registry = require('../registry'); var modernRenderer = require('../renderer'); var resolveComponentKey = modernRenderer.___resolveComponentKey; -var preserveComponentEls = modernRenderer.___preserveComponentEls; var handleBeginAsync = modernRenderer.___handleBeginAsync; +var beginComponent = require('../beginComponent'); +var endComponent = require('../endComponent'); var WIDGETS_BEGIN_ASYNC_ADDED_KEY = '$wa'; @@ -13,6 +14,7 @@ function createRendererFunc(templateRenderFunc, componentProps) { var typeName = componentProps.type; var roots = componentProps.roots; var assignedId = componentProps.id; + var isSplit = componentProps.split === true; return function renderer(input, out, renderingLogic) { var outGlobal = out.global; @@ -44,39 +46,46 @@ function createRendererFunc(templateRenderFunc, componentProps) { var globalComponentsContext = componentsContext.___globalContext; var component = globalComponentsContext.___rerenderComponent; - var fakeComponent; + var isRerender = component !== undefined; var id = assignedId; var isExisting; var customEvents; var scope; + var parentComponentDef; if (component) { id = component.id; isExisting = true; globalComponentsContext.___rerenderComponent = null; } else { + parentComponentDef = componentsContext.___componentDef; var componentArgs = out.___componentArgs; if (componentArgs) { + scope = parentComponentDef.id; out.___componentArgs = null; - scope = componentArgs[0]; - if (scope) { - scope = scope.id; + var key; + + if (typeof componentArgs === 'string') { + key = componentArgs; + } else { + key = componentArgs[0]; + customEvents = componentArgs[1]; } - var ref = componentArgs[1]; - if (ref != null) { - ref = ref.toString(); + if (key != null) { + key = key.toString(); } - id = id || resolveComponentKey(globalComponentsContext, ref, scope); - customEvents = componentArgs[2]; + id = id || resolveComponentKey(globalComponentsContext, key, parentComponentDef); + } else if (parentComponentDef) { + id = parentComponentDef.___nextComponentId(); + } else { + id = globalComponentsContext.___nextComponentId(); } } - id = id || componentsContext.___nextComponentId(); - if (registry.___isServer && typeName) { component = { id:id, typeName:typeName }; } else { @@ -101,6 +110,10 @@ function createRendererFunc(templateRenderFunc, componentProps) { } } + if (component) { + component.___updateQueued = true; + } + if (input) { if (getWidgetConfig) { // If getWidgetConfig() was implemented then use that to @@ -151,14 +164,23 @@ function createRendererFunc(templateRenderFunc, componentProps) { component.___setCustomEvents(customEvents, scope); } - preserveComponentEls(component, out, globalComponentsContext); + // We put a placeholder element in the output stream to ensure that the existing + // DOM node is matched up correctly when using morphdom. We flag the VElement + // node to track that it is a preserve marker + out.___preserveComponent(component); + globalComponentsContext.___renderedComponentsById[id] = true; + component.___reset(); // The component is no longer dirty so reset internal flags return; } } + var isFakeComponent = false; + if (!component) { - fakeComponent = { - id: id + isFakeComponent = true; + component = { + id: id, + ___keyedElements: {} }; } else { componentState = component.___rawState || componentState; @@ -168,17 +190,22 @@ function createRendererFunc(templateRenderFunc, componentProps) { getTemplateData(componentState, input, out) : componentState || input || {}; - var componentDef = componentsContext.___beginComponent(component || fakeComponent); + var componentDef = beginComponent(componentsContext, component, isSplit, parentComponentDef); + + // This is a hack, but we have to swap out the component instance stored with this node + var vComponentNode = out.___parent; + componentDef.___roots = roots; - componentDef.___component = fakeComponent ? null : component; + componentDef.___component = isFakeComponent ? null : component; componentDef.___isExisting = isExisting; componentDef.b = componentBody; componentDef.c = function(widgetConfig) { component.$c = widgetConfig; }; + componentDef.t = function(typeName) { if (typeName) { - this.___component = component = registry.___createComponent(typeName, fakeComponent.id); + vComponentNode.___component = this.___component = component = registry.___createComponent(typeName, component.id); } }; @@ -188,7 +215,7 @@ function createRendererFunc(templateRenderFunc, componentProps) { // Render the template associated with the component using the final template // data that we constructed - templateRenderFunc(templateInput, out, componentDef, componentDef); + templateRenderFunc(templateInput, out, componentDef, componentDef, component); if (customEvents && componentDef.___component) { if (registry.___isServer) { @@ -199,7 +226,8 @@ function createRendererFunc(templateRenderFunc, componentProps) { } } - componentDef.___end(); + endComponent(out, componentDef); + componentsContext.___componentDef = parentComponentDef; }; } diff --git a/src/components/package.json b/src/components/package.json index 88c5cbfe6..180abc321 100644 --- a/src/components/package.json +++ b/src/components/package.json @@ -1,6 +1,7 @@ { "browser": { "./beginComponent.js": "./beginComponent-browser.js", + "./endComponent.js": "./endComponent-browser.js", "./helpers.js": "./helpers-browser.js", "./index.js": "./index-browser.js", "./init-components.js": "./init-components-browser.js", diff --git a/src/components/renderer.js b/src/components/renderer.js index 68f08b5ad..b5ff19282 100644 --- a/src/components/renderer.js +++ b/src/components/renderer.js @@ -4,50 +4,26 @@ var emitLifecycleEvent = componentsUtil.___emitLifecycleEvent; var ComponentsContext = require('./ComponentsContext'); var getComponentsContext = ComponentsContext.___getComponentsContext; -var repeatedRegExp = /\[\]$/; var registry = require('./registry'); var copyProps = require('raptor-util/copyProps'); var isServer = componentsUtil.___isServer === true; +var beginComponent = require('./beginComponent'); +var endComponent = require('./endComponent'); var COMPONENT_BEGIN_ASYNC_ADDED_KEY = '$wa'; -function resolveComponentKey(globalComponentsContext, key, scope) { - if (key[0] == '#') { +function resolveComponentKey(globalComponentsContext, key, parentComponentDef) { + if (key[0] === '#') { return key.substring(1); } else { - var resolvedId; - - if (repeatedRegExp.test(key)) { - resolvedId = globalComponentsContext.___nextRepeatedId(scope, key); - } else { - resolvedId = scope + '-' + key; - } - - return resolvedId; + return parentComponentDef.id + '-' + parentComponentDef.___nextKey(key); } } -function preserveComponentEls(existingComponent, out, globalComponentsContext) { - var rootEls = existingComponent.___getRootEls({}); - - for (var elId in rootEls) { - var el = rootEls[elId]; - - // We put a placeholder element in the output stream to ensure that the existing - // DOM node is matched up correctly when using morphdom. - out.element(el.tagName, { id: elId }); - - globalComponentsContext.___preserveDOMNode(elId); // Mark the element as being preserved (for morphdom) - } - - existingComponent.___reset(); // The component is no longer dirty so reset internal flags - return true; -} - function handleBeginAsync(event) { var parentOut = event.parentOut; var asyncOut = event.out; - var componentsContext = parentOut.data.___components; + var componentsContext = parentOut.___components; if (componentsContext !== undefined) { // All of the components in this async block should be @@ -58,8 +34,7 @@ function handleBeginAsync(event) { // stack (to begin with). This will result in top-level components // of the async block being added as children of the component in the // parent block. - var nestedComponentsContext = componentsContext.___createNestedComponentsContext(asyncOut); - asyncOut.data.___components = nestedComponentsContext; + asyncOut.___components = new ComponentsContext(asyncOut, componentsContext); } // Carry along the component arguments asyncOut.___componentArgs = parentOut.___componentArgs; @@ -69,8 +44,6 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic) renderingLogic = renderingLogic || {}; var onInput = renderingLogic.onInput; var typeName = componentProps.type; - var roots = componentProps.roots; - var assignedId = componentProps.id; var isSplit = componentProps.split === true; var shouldApplySplitMixins = isSplit; @@ -89,38 +62,46 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic) var component = globalComponentsContext.___rerenderComponent; var isRerender = component !== undefined; - var id = assignedId; + var id; var isExisting; var customEvents; var scope; + var parentComponentDef; if (component) { id = component.id; isExisting = true; globalComponentsContext.___rerenderComponent = null; } else { + parentComponentDef = componentsContext.___componentDef; var componentArgs = out.___componentArgs; - if (componentArgs) { + // console.log('componentArgs:', componentArgs); + scope = parentComponentDef.id; out.___componentArgs = null; - scope = componentArgs[0]; + var key; - if (scope) { - scope = scope.id; + if (typeof componentArgs === 'string') { + key = componentArgs; + } else { + key = componentArgs[0]; + customEvents = componentArgs[1]; } - var key = componentArgs[1]; if (key != null) { key = key.toString(); + id = resolveComponentKey(globalComponentsContext, key, parentComponentDef); + } else { + id = parentComponentDef.___nextComponentId(); } - id = id || resolveComponentKey(globalComponentsContext, key, scope); - customEvents = componentArgs[2]; + } else if (parentComponentDef) { + id = parentComponentDef.___nextComponentId(); + } else { + id = globalComponentsContext.___nextComponentId(); } } - id = id || componentsContext.___nextComponentId(); - if (isServer) { component = registry.___createComponent( renderingLogic, @@ -134,12 +115,10 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic) component.___updatedInput = undefined; // We don't want ___updatedInput to be serialized to the browser } else { if (!component) { - if (isRerender) { - // Look in in the DOM to see if a component with the same ID and type already exists. - component = componentLookup[id]; - if (component && component.___type !== typeName) { - component = undefined; - } + if (isRerender && (component = componentLookup[id]) && component.___type !== typeName) { + // Destroy the existing component since + component.destroy(); + component = undefined; } if (component) { @@ -178,7 +157,12 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic) if (isExisting === true) { if (component.___isDirty === false || component.shouldUpdate(input, component.___state) === false) { - preserveComponentEls(component, out, globalComponentsContext); + // We put a placeholder element in the output stream to ensure that the existing + // DOM node is matched up correctly when using morphdom. We flag the VElement + // node to track that it is a preserve marker + out.___preserveComponent(component); + globalComponentsContext.___renderedComponentsById[id] = true; + component.___reset(); // The component is no longer dirty so reset internal flags return; } } @@ -189,15 +173,17 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic) emitLifecycleEvent(component, 'render', out); } - var componentDef = componentsContext.___beginComponent(component, isSplit); - componentDef.___roots = roots; + var componentDef = + beginComponent(componentsContext, component, isSplit, parentComponentDef); + componentDef.___isExisting = isExisting; // Render the template associated with the component using the final template // data that we constructed templateRenderFunc(input, out, componentDef, component, component.___rawState); - componentDef.___end(); + endComponent(out, componentDef); + componentsContext.___componentDef = parentComponentDef; }; } @@ -205,5 +191,4 @@ module.exports = createRendererFunc; // exports used by the legacy renderer createRendererFunc.___resolveComponentKey = resolveComponentKey; -createRendererFunc.___preserveComponentEls = preserveComponentEls; createRendererFunc.___handleBeginAsync = handleBeginAsync; diff --git a/src/components/taglib/TransformHelper/ComponentArgs.js b/src/components/taglib/TransformHelper/ComponentArgs.js index 793331db9..dad09d7cf 100644 --- a/src/components/taglib/TransformHelper/ComponentArgs.js +++ b/src/components/taglib/TransformHelper/ComponentArgs.js @@ -2,23 +2,15 @@ class ComponentArgs { constructor() { - this.id = null; + this.key = null; this.customEvents = null; - this.empty = true; } - setId(id) { - this.empty = false; - this.id = id; - } - - getId() { - return this.id; + setKey(key) { + this.key = key; } addCustomEvent(eventType, targetMethod, extraArgs) { - this.empty = false; - if (!this.customEvents) { this.customEvents = []; } @@ -27,7 +19,7 @@ class ComponentArgs { } compile(transformHelper) { - if (this.empty) { + if (!this.key && !this.customEvents) { return; } @@ -35,29 +27,14 @@ class ComponentArgs { var builder = transformHelper.builder; - var id = this.id; - var customEvents = this.customEvents; + var args; - // Make sure the nested component has access to the ID of the containing - // component if it is needed - var shouldProvideScope = id || customEvents; - - var args = []; - - if (shouldProvideScope) { - args.push(builder.identifier('__component')); + if (this.key && this.customEvents) { + args = builder.literal([ this.key, builder.literal(this.customEvents) ]); + } else if (this.customEvents) { + args = builder.literal([ builder.literalNull(), builder.literal(this.customEvents) ]); } else { - args.push(builder.literalNull()); - } - - if (id != null) { - args.push(id); - } else { - args.push(builder.literalNull()); - } - - if (customEvents) { - args.push(builder.literal(customEvents)); + args = this.key; } if (el.type === 'CustomTag') { @@ -66,7 +43,7 @@ class ComponentArgs { el.generateRenderTagCode = function(codegen, tagVar, tagArgs) { tagArgs = [tagVar].concat(tagArgs); - tagArgs.push(builder.literal(args)); + tagArgs.push(args); return codegen.builder.functionCall( renderComponentHelper, @@ -75,7 +52,7 @@ class ComponentArgs { } else { el.onBeforeGenerateCode((event) => { let funcTarget = builder.memberExpression(builder.identifierOut(), builder.identifier('c')); - let funcArgs = [builder.literal(args)]; + let funcArgs = [args]; event.insertCode(builder.functionCall(funcTarget, funcArgs)); }); diff --git a/src/components/taglib/TransformHelper/assignComponentId.js b/src/components/taglib/TransformHelper/assignComponentId.js index aabb801da..c538587ec 100644 --- a/src/components/taglib/TransformHelper/assignComponentId.js +++ b/src/components/taglib/TransformHelper/assignComponentId.js @@ -12,7 +12,11 @@ module.exports = function assignComponentId(isRepeated) { var context = this.context; var builder = this.builder; - let componentRef; + if (el.noOutput || (el.tagDef && el.tagDef.noOutput)) { + return; + } + + let assignedKey; var nestedIdExpression; var idExpression; @@ -27,6 +31,9 @@ module.exports = function assignComponentId(isRepeated) { this.getMarkoComponentsRequirePath('marko/components/taglib/helpers/getCurrentComponent')); context.addVar('__component', builder.functionCall(getCurrentComponentVar, [builder.identifierOut()])); + context.addVar('component', builder.memberExpression( + builder.identifier('__component'), + builder.identifier('___component'))); } } @@ -42,72 +49,80 @@ module.exports = function assignComponentId(isRepeated) { // 3) The HTML does not have an "id" or "ref" attribute. We must add // an "id" attribute with a unique ID. - var isCustomTag = el.type !== 'HtmlElement'; + var isHtmlElement = el.type === 'HtmlElement'; + var isCustomTag = el.type === 'CustomTag'; - if (el.hasAttribute('key')) { - componentRef = el.getAttributeValue('key'); - el.removeAttribute('key'); - } else if (el.hasAttribute('ref')) { - context.deprecate('The "ref" attribute is deprecated. Please use "key" instead.'); - componentRef = el.getAttributeValue('ref'); - el.removeAttribute('ref'); + // LEGACY -- Remove in Marko 5.0 + if (!isCustomTag && el.tagName === 'invoke') { + isCustomTag = true; + } + + if (!isCustomTag && !isHtmlElement) { + return; } if (el.hasAttribute('w-id')) { context.deprecate('The "w-id" attribute is deprecated. Please use "key" instead.'); - if (componentRef) { - this.addError('The "w-id" attribute cannot be used in conjuction with the "ref" or "key" attributes.'); + if (el.hasAttribute('key')) { + this.addError('The "w-id" attribute cannot be used in conjunction with the "key" attributes.'); return; } - componentRef = el.getAttributeValue('w-id'); + if (el.hasAttribute('ref')) { + this.addError('The "w-id" attribute cannot be used in conjunction with the "ref" attributes.'); + return; + } + + assignedKey = el.getAttributeValue('w-id'); el.removeAttribute('w-id'); + } else if (el.hasAttribute('key')) { + assignedKey = el.getAttributeValue('key'); + el.removeAttribute('key'); + } else if (el.hasAttribute('ref')) { + context.deprecate('The "ref" attribute is deprecated. Please use "key" instead.'); + assignedKey = el.getAttributeValue('ref'); + el.removeAttribute('ref'); } - if (componentRef) { - idExpression = this.buildComponentElIdFunctionCall(componentRef); - - nestedIdExpression = componentRef; + if (assignedKey) { + nestedIdExpression = assignedKey; if (isCustomTag) { + idExpression = this.buildComponentElIdFunctionCall(assignedKey); // The element is a custom tag - this.getComponentArgs().setId(nestedIdExpression); + this.getComponentArgs().setKey(nestedIdExpression); } else { - if (el.hasAttribute('id')) { - this.addError('The "ref", "key", and "w-id" attributes cannot be used in conjuction with the "id" attribute.'); - return; + idExpression = assignedKey; + if (context.data.hasLegacyForKey && el.data.userAssignedKey !== false) { + el.setAttributeValue('id', this.buildComponentElIdFunctionCall(assignedKey)); } - el.setAttributeValue('id', idExpression); - } - } else if (el.hasAttribute('id')) { - idExpression = el.getAttributeValue('id'); - if (el.isFlagSet('hasComponentBind')) { - // We have to attach a listener to the root element of the component - // We will use an empty string as an indicator that it is the root component - // element. - nestedIdExpression = builder.literal(''); - } else { - // Convert the raw String to a JavaScript expression. we need to prefix - // with '#' to make it clear this is a fully resolved element ID - nestedIdExpression = builder.concat( - builder.literal('#'), - idExpression); + if (context.isServerTarget()) { + var markoKeyAttrVar = context.importModule('marko_keyAttr', + this.getMarkoComponentsRequirePath('marko/components/taglib/helpers/markoKeyAttr')); + + el.setAttributeValue('data-marko-key', builder.functionCall(markoKeyAttrVar, [ + idExpression, + builder.identifier('__component') + ])); + } + + el.setKey(assignedKey); } } else { // Case 3 - We need to add a unique "id" attribute let uniqueElId = this.nextUniqueId(); - nestedIdExpression = isRepeated ? builder.literal(uniqueElId + '[]') : builder.literal(uniqueElId); + nestedIdExpression = isRepeated ? builder.literal(uniqueElId + '[]') : builder.literal(uniqueElId.toString()); - idExpression = this.buildComponentElIdFunctionCall(nestedIdExpression); + idExpression = builder.literal(uniqueElId.toString()); if (isCustomTag) { - this.getComponentArgs().setId(nestedIdExpression); + this.getComponentArgs().setKey(nestedIdExpression); } else { - el.setAttributeValue('id', idExpression); + el.setKey(idExpression); } } @@ -123,13 +138,17 @@ module.exports = function assignComponentId(isRepeated) { } let uniqueElId = transformHelper.nextUniqueId(); - let idVarName = '__componentId' + uniqueElId; + let idVarName = '__key' + uniqueElId; let idVar = builder.identifier(idVarName); this.idVarNode = builder.vars([ { id: idVarName, - init: idExpression + init: builder.functionCall( + builder.memberExpression( + builder.identifier('__component'), + builder.identifier('___nextKey')), + [ idExpression ]) } ]); @@ -140,9 +159,9 @@ module.exports = function assignComponentId(isRepeated) { idVar); if (isCustomTag) { - transformHelper.getComponentArgs().setId(nestedIdExpression); + transformHelper.getComponentArgs().setKey(nestedIdExpression); } else { - el.setAttributeValue('id', idExpression); + el.setKey(idExpression); } return this.idVarNode; diff --git a/src/components/taglib/TransformHelper/convertToComponent.js b/src/components/taglib/TransformHelper/convertToComponent.js new file mode 100644 index 000000000..2d6ab557c --- /dev/null +++ b/src/components/taglib/TransformHelper/convertToComponent.js @@ -0,0 +1,158 @@ +'use strict'; +const generateRegisterComponentCode = require('../util/generateRegisterComponentCode'); + +// var FLAG_WILL_RERENDER_IN_BROWSER = 1; +var FLAG_HAS_BODY_EL = 2; +var FLAG_HAS_HEAD_EL = 4; + +module.exports = function handleComponentBind(options) { + if (this.firstBind) { + return; + } + + this.firstBind = true; + + let context = this.context; + let builder = this.builder; + + let isLegacyComponent = this.isLegacyComponent = options.isLegacyComponent === true; + let componentModule = options.componentModule; + let rendererModule = options.rendererModule; + let componentProps = options.componentProps || {}; + let rootNodes = options.rootNodes; + let isLegacyInnerBind = options.isLegacyInnerBind; + + var isSplit = false; + + if ((rendererModule && rendererModule !== componentModule) || + (!rendererModule && componentModule)) { + componentProps.split = isSplit = true; + } + + if (componentModule) { + let componentTypeNode; + let dependencyModule = isLegacyComponent || isSplit ? componentModule : this.getTemplateModule(); + + if (dependencyModule.requirePath) { + context.addDependency({ type:'require', path: dependencyModule.requirePath }); + } + + if (isSplit) { + context.addDependency({ type:'require', path: context.markoModulePrefix + 'components' }); + } + + componentTypeNode = context.addStaticVar( + 'marko_componentType', + generateRegisterComponentCode(componentModule, this, isSplit)); + + componentProps.type = componentTypeNode; + } + + if (isLegacyInnerBind) { + let el = rootNodes[0]; + el.setAttributeValue('id', + builder.memberExpression( + builder.identifier('__component'), + builder.identifier('id'))); + + // TODO Deprecation warning for inner binds + let componentNode = context.createNodeForEl('_component', { + props: builder.literal(componentProps) + }); + el.wrapWith(componentNode); + return; + } + + var flags = 0; + + + + rootNodes.forEach((rootNode) => { + if (rootNode.type === 'HtmlElement') { + if (rootNode.tagName === 'body') { + flags |= FLAG_HAS_BODY_EL; + } else if (rootNode.tagName === 'head') { + flags |= FLAG_HAS_HEAD_EL; + } + } + }); + + if (flags) { + context.root.appendChild( + builder.assignment( + builder.memberExpression( + builder.identifier('__component'), + builder.identifier('___flags')), + builder.literal(flags), + '|=')); + } + + let markoComponentVar; + + if (rendererModule) { + if (rendererModule.inlineId) { + markoComponentVar = rendererModule.inlineId; + } else { + markoComponentVar = context.addStaticVar('marko_component', builder.require(builder.literal(rendererModule.requirePath))); + } + } + + this.setHasBoundComponentForTemplate(); + + var rendererHelper = isLegacyComponent ? + this.context.helper('rendererLegacy') : + this.context.helper('renderer'); + + var defineComponentHelper; + + if (!isSplit && !isLegacyComponent) { + defineComponentHelper = this.context.helper('defineComponent'); + } + + this.context.on('beforeGenerateCode:TemplateRoot', function(eventArgs) { + eventArgs.node.addRenderFunctionParam(builder.identifier('__component')); + + if (isLegacyComponent) { + eventArgs.node.addRenderFunctionParam(builder.identifier('widget')); + eventArgs.node.addRenderFunctionParam(builder.identifier('component')); + } else { + eventArgs.node.addRenderFunctionParam(builder.identifier('component')); + eventArgs.node.addRenderFunctionParam(builder.identifier('state')); + } + + eventArgs.node.generateAssignRenderCode = (eventArgs) => { + const nodes = []; + const templateVar = eventArgs.templateVar; + const templateRendererMember = eventArgs.templateRendererMember; + const renderFunctionVar = eventArgs.renderFunctionVar; + + const createRendererArgs = [ + renderFunctionVar, + builder.literal(componentProps) + ]; + + if (markoComponentVar) { + createRendererArgs.push(markoComponentVar); + } + + nodes.push(builder.assignment( + templateRendererMember, + builder.functionCall( + rendererHelper, + createRendererArgs))); + + if (!isSplit && !isLegacyComponent) { + nodes.push(builder.assignment( + builder.memberExpression(templateVar, builder.identifier('Component')), + builder.functionCall( + defineComponentHelper, + [ + markoComponentVar, + templateRendererMember + ]))); + } + + return nodes; + }; + }); +}; diff --git a/src/components/taglib/TransformHelper/handleComponentBind.js b/src/components/taglib/TransformHelper/handleComponentBind.js deleted file mode 100644 index 41c25d475..000000000 --- a/src/components/taglib/TransformHelper/handleComponentBind.js +++ /dev/null @@ -1,287 +0,0 @@ -'use strict'; -const resolveFrom = require('resolve-from'); -const generateRegisterComponentCode = require('../util/generateRegisterComponentCode'); - -function legacyGetDefaultComponentModule(dirname) { - var filename; - var legacy = true; - - if ((filename = resolveFrom(dirname, './widget'))) { - return { - filename, - requirePath: './widget', - legacy - }; - } else if ((filename = resolveFrom(dirname, './component'))) { - return { - filename, - requirePath: './component', - legacy - }; - } else if ((filename = resolveFrom(dirname, './'))) { - return { - filename, - requirePath: './', - legacy - }; - } else { - return null; - } -} - -function checkIsInnerBind(el) { - var curNode = el; - - while (true) { - if (curNode.data.hasBoundComponent) { - return true; - } - - curNode = curNode.parentNode; - - if (!curNode) { - break; - } - } - - return false; -} - -module.exports = function handleComponentBind() { - let el = this.el; - let context = this.context; - let builder = this.builder; - - let componentModule; - let rendererModulePath; - let rendererModule = this.getRendererModule(); - let isLegacyComponent = false; - - if (el.hasAttribute('w-bind')) { - let bindAttr = el.getAttribute('w-bind'); - - context.deprecate('Legacy components using w-bind and defineRenderer/defineComponent or defineComponent are deprecated. See: https://github.com/marko-js/marko/issues/421'); - this.isLegacyComponent = isLegacyComponent = true; - - // Remove the w-bind attribute since we don't want it showing up in the output DOM - el.removeAttribute('w-bind'); - - // Read the value for the w-bind attribute. This will be an AST node for the parsed JavaScript - let bindAttrValue = bindAttr.value; - - const hasWidgetTypes = context.isFlagSet('hasWidgetTypes'); - - if (hasWidgetTypes) { - context.deprecate('The tag is deprecated. Please remove it. See: https://github.com/marko-js/marko/issues/514'); - } - - if (bindAttrValue == null) { - componentModule = legacyGetDefaultComponentModule(this.dirname); - if (!componentModule) { - this.addError('No corresponding JavaScript module found in the same directory (either "component.js" or "index.js").'); - return; - } - } else if (bindAttr.isLiteralValue()) { - if (typeof bindAttr.literalValue !== 'string') { - this.addError('The value for the "w-bind" attribute should be a string. Actual: ' + componentModule); - return; - } - - let requirePath = bindAttr.literalValue; - let filename = resolveFrom(this.dirname, requirePath); - - if (!filename) { - this.addError('Target file not found: ' + requirePath + ' (from: ' + this.dirname + ')'); - return; - } - - componentModule = { - legacy: true, - filename, - requirePath - }; - } else { - // This is a dynamic expression. The should have been found. - if (!hasWidgetTypes) { - this.addError('The tag must be used to declare components when the value of the "w-bind" attribute is a dynamic expression.'); - return; - } - - el.insertSiblingBefore( - builder.functionCall( - builder.memberExpression(builder.identifier('__component'), builder.identifier('t')), - [ - builder.memberExpression( - builder.identifier('marko_componentTypes'), - bindAttrValue, - true /* computed */) - ])); - } - } else if (el.isFlagSet('hasComponentBind')) { - componentModule = this.getComponentModule(); - rendererModulePath = this.getRendererModule(); - - - if (context.isFlagSet('hasWidgetTypes')) { - context.addError('The tag is no longer supported. See: https://github.com/marko-js/marko/issues/514'); - } - } else { - return; - } - - this.setHasBoundComponentForTemplate(); - - let isInnerBind = checkIsInnerBind(el.parentNode); - - el.data.hasBoundComponent = true; - - // A component is bound to the el... - - var componentProps = isInnerBind ? {} : this.getComponentProps(); - let transformHelper = this; - - var isSplit = false; - - if ((rendererModule && rendererModule !== componentModule) || - (!rendererModule && componentModule)) { - componentProps.split = isSplit = true; - } - - if (componentModule) { - let componentTypeNode; - let dependencyModule = isLegacyComponent || isSplit ? componentModule : this.getTemplateModule(); - - if (dependencyModule.requirePath) { - context.addDependency({ type:'require', path: dependencyModule.requirePath }); - } - - if (isSplit) { - context.addDependency({ type:'require', path: context.markoModulePrefix + 'components' }); - } - - componentTypeNode = context.addStaticVar( - 'marko_componentType', - generateRegisterComponentCode(componentModule, this, isSplit)); - - componentProps.type = componentTypeNode; - } - - if (el.hasAttribute('w-config')) { - el.insertSiblingBefore( - builder.functionCall( - builder.memberExpression(builder.identifier('__component'), builder.identifier('c')), - [ - el.getAttributeValue('w-config') - ])); - - el.removeAttribute('w-config'); - } - - let id = el.getAttributeValue('id'); - - if (id) { - componentProps.id = id; - } - - let markoComponentVar; - - if (rendererModule) { - if (rendererModule.inlineId) { - markoComponentVar = rendererModule.inlineId; - } else { - markoComponentVar = context.addStaticVar('marko_component', builder.require(builder.literal(rendererModule.requirePath))); - } - } - - if (isInnerBind) { - el.setAttributeValue('id', - builder.memberExpression( - builder.identifier('__component'), - builder.identifier('id'))); - - // TODO Deprecation warning for inner binds - let componentNode = context.createNodeForEl('_component', { - props: builder.literal(componentProps) - }); - el.wrapWith(componentNode); - return; - } - - if (this.firstBind) { - - var rendererHelper = isLegacyComponent ? - transformHelper.context.helper('rendererLegacy') : - transformHelper.context.helper('renderer'); - - var defineComponentHelper; - - if (!isSplit && !isLegacyComponent) { - defineComponentHelper = transformHelper.context.helper('defineComponent'); - } - - this.context.on('beforeGenerateCode:TemplateRoot', function(eventArgs) { - eventArgs.node.addRenderFunctionParam(builder.identifier('__component')); - - if (isLegacyComponent) { - eventArgs.node.addRenderFunctionParam(builder.identifier('widget')); - } else { - eventArgs.node.addRenderFunctionParam(builder.identifier('component')); - eventArgs.node.addRenderFunctionParam(builder.identifier('state')); - } - - eventArgs.node.generateAssignRenderCode = function(eventArgs) { - let nodes = []; - let templateVar = eventArgs.templateVar; - let templateRendererMember = eventArgs.templateRendererMember; - let renderFunctionVar = eventArgs.renderFunctionVar; - - let createRendererArgs = [ - renderFunctionVar, - builder.literal(componentProps) - ]; - - if (markoComponentVar) { - createRendererArgs.push(markoComponentVar); - } - - nodes.push(builder.assignment( - templateRendererMember, - builder.functionCall( - rendererHelper, - createRendererArgs))); - - if (!isSplit && !isLegacyComponent) { - nodes.push(builder.assignment( - builder.memberExpression(templateVar, builder.identifier('Component')), - builder.functionCall( - defineComponentHelper, - [ - markoComponentVar, - templateRendererMember - ]))); - } - - return nodes; - }; - }); - } - - if (el.hasAttribute('key')) { - if (!componentProps.roots) { - componentProps.roots = []; - } - var key = el.getAttributeValue('key'); - componentProps.roots.push(key); - } else if (el.hasAttribute('ref')) { - if (!componentProps.roots) { - componentProps.roots = []; - } - var ref = el.getAttributeValue('ref'); - componentProps.roots.push(ref); - } else { - el.setAttributeValue('id', - builder.memberExpression( - builder.identifier('__component'), - builder.identifier('id'))); - } -}; diff --git a/src/components/taglib/TransformHelper/handleComponentKeyAttrs.js b/src/components/taglib/TransformHelper/handleComponentKeyAttrs.js deleted file mode 100644 index d0f2a8f01..000000000 --- a/src/components/taglib/TransformHelper/handleComponentKeyAttrs.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; - -const keySuffix = ':key'; - -module.exports = function handleComponentKeyAttrs() { - let el = this.el; - let context = this.context; - - const filePosition = el.pos ? context.getPosInfo(el.pos) : context.filename; - - // BEGIN support for deprecated for attributes - - let deprecatedForAttributes = ['for-ref', 'for-key', 'w-for']; - - deprecatedForAttributes.forEach(attributeName => { - if (el.hasAttribute(attributeName)) { - context.deprecate(`The "${attributeName}" tag is deprecated. Please use "for:key" instead.`); - - let incompatibleAttributes = ['for', 'for:key'] - .concat(deprecatedForAttributes.filter(a => a != attributeName)) - .filter(a => el.hasAttribute(a)); - - if (incompatibleAttributes.length) { - this.addError(`The "${attributeName}" tag cannot be used with "${incompatibleAttributes.join('" or "')}". (${filePosition})`); - } else { - el.setAttributeValue('for:key', el.getAttributeValue(attributeName)); - } - - el.removeAttribute(attributeName); - } - }); - - // END support for deprecated for attributes - - el.attributes.forEach(attribute => { - const attributeName = attribute.name; - - if (attributeName && attributeName !== keySuffix && attributeName.endsWith(keySuffix)) { - const unfixedName = attributeName.replace(keySuffix, ''); - - el.removeAttribute(attributeName); - if (el.hasAttribute(unfixedName)) { - this.addError(`The "${attributeName}" attribute cannot be used in conjuction with the "${unfixedName}" attribute. (${filePosition})`); - } else { - el.setAttributeValue( - unfixedName, - this.buildComponentElIdFunctionCall(attribute.value)); - } - } - }); -}; diff --git a/src/components/taglib/TransformHelper/handleComponentPreserve.js b/src/components/taglib/TransformHelper/handleComponentPreserve.js index ac9684f56..6ef5f32d4 100644 --- a/src/components/taglib/TransformHelper/handleComponentPreserve.js +++ b/src/components/taglib/TransformHelper/handleComponentPreserve.js @@ -15,12 +15,17 @@ function addPreserve(transformHelper, bodyOnly, condition) { preserveAttrs['if'] = condition; } - let componentIdInfo = transformHelper.assignComponentId(true /* repeated */); + let componentIdInfo = transformHelper.assignComponentId(); let idVarNode = componentIdInfo.idVarNode ? null : componentIdInfo.createIdVarNode(); - preserveAttrs.id = transformHelper.getIdExpression(); + if (el.type === 'HtmlElement') { + preserveAttrs.key = transformHelper.getIdExpression(); + } else { + preserveAttrs.cid = transformHelper.getIdExpression(); + } - let preserveNode = context.createNodeForEl('w-preserve', preserveAttrs); + + let preserveNode = context.createNodeForEl('_preserve', preserveAttrs); let idVarNodeTarget; if (bodyOnly) { diff --git a/src/components/taglib/TransformHelper/handleIncludeNode.js b/src/components/taglib/TransformHelper/handleIncludeNode.js deleted file mode 100644 index c9c9189e9..000000000 --- a/src/components/taglib/TransformHelper/handleIncludeNode.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -var includeTagForComponents = require.resolve('../include-tag'); - -module.exports = function(includeNode) { - var context = this.context; - - if (!this.hasBoundComponentForTemplate()) { - return; - } - - var parentNode = includeNode.parentNode; - - if (!parentNode.hasAttribute) { - return; - } - - parentNode._normalizeChildTextNodes(context, true /* force trim */); - - if (parentNode.childCount === 1) { - if (includeNode.hasAttribute('key') || includeNode.hasAttribute('ref')) { - this.assignComponentId(); - } - - let parentTransformHelper = this.getTransformHelper(parentNode); - - if (includeNode.data.bodySlot) { - parentTransformHelper.assignComponentId(false /* not repeated */); - var componentProps = this.getComponentProps(); - componentProps.body = parentTransformHelper.getNestedIdExpression(); - } else { - let componentIdInfo = parentTransformHelper.assignComponentId(true /* repeated */); - if (!componentIdInfo.idVarNode) { - let idVarNode = componentIdInfo.createIdVarNode(); - parentNode.onBeforeGenerateCode((event) => { - event.insertCode(idVarNode); - }); - } - } - - includeNode.setRendererPath(includeTagForComponents); - - includeNode.onBeforeGenerateCode(function() { - includeNode.addProp('_elId', parentTransformHelper.getIdExpression()); - }); - } - - - - // includeNode.generateCodeForDynamicInclude = (options, codegen) => { - // var target = options.target; - // var data = options.data; - // - // if (!data) { - // data = builder.literal(null); - // } - // - // let includeVar = context.importModule('marko_component_include', this.getMarkoComponentsRequirePath('marko/components/taglib/helpers/include')); - // - // let includeArgs = [ - // target, - // builder.identifierOut(), - // data - // ]; - // - // if (parentTransformHelper) { - // includeArgs = includeArgs.concat([ - // parentTransformHelper.getIdExpression(), - // - // ]); - // } - // - // return builder.functionCall(includeVar, includeArgs); - // }; -}; diff --git a/src/components/taglib/TransformHelper/handleLegacyBind.js b/src/components/taglib/TransformHelper/handleLegacyBind.js new file mode 100644 index 000000000..82897ed5a --- /dev/null +++ b/src/components/taglib/TransformHelper/handleLegacyBind.js @@ -0,0 +1,155 @@ +'use strict'; +const resolveFrom = require('resolve-from'); + +function legacyGetDefaultComponentModule(dirname) { + var filename; + var legacy = true; + + if ((filename = resolveFrom(dirname, './widget'))) { + return { + filename, + requirePath: './widget', + legacy + }; + } else if ((filename = resolveFrom(dirname, './component'))) { + return { + filename, + requirePath: './component', + legacy + }; + } else if ((filename = resolveFrom(dirname, './'))) { + return { + filename, + requirePath: './', + legacy + }; + } else { + return null; + } +} + +function checkIsInnerBind(el) { + var curNode = el; + + while (true) { + if (curNode.data.hasBoundComponent) { + return true; + } + + curNode = curNode.parentNode; + + if (!curNode) { + break; + } + } + + return false; +} + +module.exports = function handleLegacyBind() { + let el = this.el; + let context = this.context; + let builder = this.builder; + + let componentModule; + let rendererModule; + + let isLegacyComponent = false; + + if (el.hasAttribute('w-bind')) { + let bindAttr = el.getAttribute('w-bind'); + + context.deprecate('Legacy components using w-bind and defineRenderer/defineComponent or defineComponent are deprecated. See: https://github.com/marko-js/marko/issues/421'); + this.isLegacyComponent = isLegacyComponent = true; + + // Remove the w-bind attribute since we don't want it showing up in the output DOM + el.removeAttribute('w-bind'); + + // Read the value for the w-bind attribute. This will be an AST node for the parsed JavaScript + let bindAttrValue = bindAttr.value; + + const hasWidgetTypes = context.isFlagSet('hasWidgetTypes'); + + if (hasWidgetTypes) { + context.deprecate('The tag is deprecated. Please remove it. See: https://github.com/marko-js/marko/issues/514'); + } + + if (bindAttrValue == null) { + componentModule = legacyGetDefaultComponentModule(this.dirname); + if (!componentModule) { + this.addError('No corresponding JavaScript module found in the same directory (either "component.js" or "index.js").'); + return; + } + } else if (bindAttr.isLiteralValue()) { + if (typeof bindAttr.literalValue !== 'string') { + this.addError('The value for the "w-bind" attribute should be a string. Actual: ' + componentModule); + return; + } + + let requirePath = bindAttr.literalValue; + let filename = resolveFrom(this.dirname, requirePath); + + if (!filename) { + this.addError('Target file not found: ' + requirePath + ' (from: ' + this.dirname + ')'); + return; + } + + componentModule = { + legacy: true, + filename, + requirePath + }; + } else { + // This is a dynamic expression. The should have been found. + if (!hasWidgetTypes) { + this.addError('The tag must be used to declare components when the value of the "w-bind" attribute is a dynamic expression.'); + return; + } + + el.insertSiblingBefore( + builder.functionCall( + builder.memberExpression(builder.identifier('__component'), builder.identifier('t')), + [ + builder.memberExpression( + builder.identifier('marko_componentTypes'), + bindAttrValue, + true /* computed */) + ])); + } + } else { + return; + } + + let isLegacyInnerBind = checkIsInnerBind(el.parentNode); + + el.data.hasBoundComponent = true; + + // A component is bound to the el... + + if (el.hasAttribute('w-config')) { + el.insertSiblingBefore( + builder.functionCall( + builder.memberExpression(builder.identifier('__component'), builder.identifier('c')), + [ + el.getAttributeValue('w-config') + ])); + + el.removeAttribute('w-config'); + } + + let componentProps = {}; + + let id = el.getAttributeValue('id'); + + if (id) { + componentProps.id = id; + } + + this.convertToComponent({ + isLegacyInnerBind, + componentModule, + rendererModule, + isLegacyComponent: true, + rootNodes: [el] + }); +}; diff --git a/src/components/taglib/TransformHelper/handleRootNodes.js b/src/components/taglib/TransformHelper/handleRootNodes.js index d92631fde..0294de34f 100644 --- a/src/components/taglib/TransformHelper/handleRootNodes.js +++ b/src/components/taglib/TransformHelper/handleRootNodes.js @@ -1,7 +1,7 @@ 'use strict'; -var path = require('path'); -var getComponentFiles = require('./getComponentFiles'); +let path = require('path'); +let getComponentFiles = require('./getComponentFiles'); const esprima = require('esprima'); const escodegen = require('escodegen'); @@ -12,16 +12,16 @@ function handleStyleElement(styleEl, transformHelper) { return; } - var attrs = styleEl.attributes; + let attrs = styleEl.attributes; - var styleCode; - var lang = 'css'; + let styleCode; + let lang = 'css'; - var hasStyleBlock = false; + let hasStyleBlock = false; - for (var i=attrs.length-1; i>=0; i--) { - var attr = attrs[i]; - var name = attr.name; + for (let i=attrs.length-1; i>=0; i--) { + let attr = attrs[i]; + let name = attr.name; if (name.startsWith('{')) { hasStyleBlock = true; @@ -47,7 +47,7 @@ function handleStyleElement(styleEl, transformHelper) { styleEl.setFlag(FLAG_COMPONENT_STYLE); if (styleCode) { - var context = transformHelper.context; + let context = transformHelper.context; context.addDependency({ type: lang, code: styleCode, @@ -95,15 +95,15 @@ function classToObject(cls, el, transformHelper) { function handleClassDeclaration(classEl, transformHelper) { let tree; - var wrappedSrc = '('+classEl.tagString+'\n)'; + let wrappedSrc = '('+classEl.tagString+'\n)'; try { tree = esprima.parse(wrappedSrc); } catch(err) { - var message = 'Unable to parse JavaScript for component class. ' + err; + let message = 'Unable to parse JavaScript for component class. ' + err; if (err.index != null) { - var errorIndex = err.index; + let errorIndex = err.index; // message += '\n' + err.description; if (errorIndex != null && errorIndex >= 0) { transformHelper.context.addError({ @@ -127,36 +127,28 @@ function handleClassDeclaration(classEl, transformHelper) { let object = classToObject(expression, classEl, transformHelper); let componentVar = transformHelper.context.addStaticVar('marko_component', escodegen.generate(object)); - if (transformHelper.getRendererModule() != null) { - transformHelper.context.addError(classEl, 'The component has both an inline component `class` and a separate `component.js`. This is not allowed. See: https://github.com/marko-js/marko/wiki/Error:-Component-inline-and-external'); - return; - } - - var moduleInfo = { + let moduleInfo = { inlineId: componentVar, filename: transformHelper.filename, requirePath: './' + path.basename(transformHelper.filename) }; - if (transformHelper.getComponentModule() == null) { - transformHelper.setComponentModule(moduleInfo); - } - - transformHelper.setRendererModule(moduleInfo); - classEl.detach(); + + return moduleInfo; } module.exports = function handleRootNodes() { - var context = this.context; - var builder = this.builder; + let context = this.context; - var componentFiles = getComponentFiles(context.filename); + let componentFiles = getComponentFiles(context.filename); if (!componentFiles) { return; } - var dirname = context.dirname; + let componentModule; + let rendererModule; + let dirname = context.dirname; if (componentFiles.package) { context.addDependency('package: ./' + componentFiles.package); @@ -174,67 +166,78 @@ module.exports = function handleRootNodes() { requirePath: './'+file.slice(0, file.lastIndexOf('.')) }; - this.setComponentModule(moduleInfo); - this.setRendererModule(moduleInfo); + componentModule = rendererModule = moduleInfo; } if (componentFiles.browserFile) { let file = componentFiles.browserFile; - this.setComponentModule({ + + componentModule = { filename: path.join(dirname, file), requirePath: './' + file.slice( 0, file.lastIndexOf('.')) - }); + }; } - var templateRoot = this.el; + let templateRoot = this.el; - var rootNodes = []; - var hasLegacyExplicitBind = false; - var hasIdCount = 0; - var nodeWithAssignedId; - var assignedId; - var transformHelper = this; + let rootNodes = []; + let hasIdCount = 0; + let nodeWithAssignedId; + let assignedId; + let transformHelper = this; let walker = context.createWalker({ enter(node) { let tagName = node.tagName && node.tagName.toLowerCase(); - let tag = node.tagName && context.taglibLookup.getTag(node.tagName); if (node.type === 'TemplateRoot' || !node.type) { - // Don't worry about the TemplateRoot or a Container node - // But continue into the node to look at its children for root elements - } else if (tag && tag.noOutput) { - walker.skip(); + // Don't worry about the TemplateRoot or an Container node } else if (node.type === 'HtmlElement') { - if (node.hasAttribute('w-bind')) { - transformHelper.setHasBoundComponentForTemplate(); - hasLegacyExplicitBind = true; - } else { - if (node.hasAttribute('id')) { - hasIdCount++; - nodeWithAssignedId = node; - assignedId = node.getAttributeValue('id'); - } + if (node.hasAttribute('id')) { + hasIdCount++; + nodeWithAssignedId = node; + assignedId = node.getAttributeValue('id'); + } - if (tagName === 'style') { - handleStyleElement(node, transformHelper); - } + if (tagName === 'style') { + handleStyleElement(node, transformHelper); + } - if (!node.isFlagSet(FLAG_COMPONENT_STYLE)) { - rootNodes.push(node); - } + if (!node.isFlagSet(FLAG_COMPONENT_STYLE)) { + rootNodes.push(node); + } + walker.skip(); + + return; + } else if (node.type === 'CustomTag') { + let tag = context.taglibLookup.getTag(node.tagName); + + if (!tag.noOutput) { + rootNodes.push(node); } walker.skip(); return; - } else if (node.type === 'CustomTag') { - rootNodes.push(node); + } else if (node.type === 'Scriptlet') { walker.skip(); return; } else { if (tagName === 'class') { - handleClassDeclaration(node, transformHelper); + let classComponentModule = handleClassDeclaration(node, transformHelper); + + if (rendererModule != null) { + transformHelper.context.addError(node, 'The component has both an inline component `class` and a separate `component.js`. This is not allowed. See: https://github.com/marko-js/marko/wiki/Error:-Component-inline-and-external'); + return; + } + + if (componentModule == null) { + componentModule = classComponentModule; + } + + rendererModule = classComponentModule; + } else if (!node.noOutput) { + rootNodes.push(node); } walker.skip(); @@ -245,43 +248,29 @@ module.exports = function handleRootNodes() { walker.walk(templateRoot); - if (hasLegacyExplicitBind) { - //There is an explicit bind so nothing to do + if (!componentModule) { return; } - if (!this.hasBoundComponentForTemplate()) { - return; + if (context.isFlagSet('hasWidgetTypes')) { + context.addError('The tag is no longer supported. See: https://github.com/marko-js/marko/issues/514'); } + templateRoot._normalizeChildTextNodes(context, true); + + // After normalizing the text nodes to remove whitespace we may have detached + // some of the root text nodes so remove those from our list + rootNodes = rootNodes.filter((rootNode) => { + return rootNode.isDetached() !== true; + }); + if (rootNodes.length === 0) { return; } - if (rootNodes.length > 1 && hasIdCount > 0) { - // We can only bind a component to multiple top-level elements if we can assign - // all of the IDs - return; - } - - transformHelper.setHasBoundComponentForTemplate(); - - var nextKey = 0; - - rootNodes.forEach((curNode, i) => { - let id = curNode.getAttributeValue('id'); - - if (id && id.type !== 'Literal') { - context.addError('Root HTML element should not have a dynamic `id` attribute. See: https://github.com/marko-js/marko/wiki/Error:-Dynamic-root-HTML-element-id-attribute'); - return; - } - - curNode.setFlag('hasComponentBind'); - - if (!curNode.hasAttribute('key') && !curNode.hasAttribute('ref')) { - if (curNode.type === 'CustomTag' || rootNodes.length > 1) { - curNode.setAttributeValue('key', builder.literal('_r' + (nextKey++))); - } - } + this.convertToComponent({ + rootNodes, + componentModule, + rendererModule }); }; diff --git a/src/components/taglib/TransformHelper/handleScopedAttrs.js b/src/components/taglib/TransformHelper/handleScopedAttrs.js new file mode 100644 index 000000000..ae58d5a17 --- /dev/null +++ b/src/components/taglib/TransformHelper/handleScopedAttrs.js @@ -0,0 +1,75 @@ +'use strict'; + +const deprecatedKeySuffix = ':key'; +const scopedSuffix = ':scoped'; +const deprecatedAttrs = { + 'for-ref': true, + 'for-key': true, + 'w-for': true +}; + +module.exports = function handleComponentKeyAttrs() { + let el = this.el; + let context = this.context; + let builder = this.builder; + const filePosition = el.pos ? context.getPosInfo(el.pos) : context.filename; + + var attrs = el.attributes.concat([]); + + attrs.forEach(attribute => { + const attributeName = attribute.name; + if (!attributeName) { + return; + } + + let fixedAttributeName = attributeName; + + // BEGIN support for deprecated for attributes + if (deprecatedAttrs[attributeName]) { + context.deprecate(`The "${attributeName}" attribute is deprecated. Please use "for:key" instead.`); + + let incompatibleAttributes = ['for', 'for:key'] + .concat(Object.keys(deprecatedAttrs).filter(a => a != attributeName)) + .filter(a => el.hasAttribute(a)); + + if (incompatibleAttributes.length) { + this.addError(`The "${attributeName}" attribute cannot be used in conjunction with "${incompatibleAttributes.join('" or "')}". (${filePosition})`); + return; + } else { + fixedAttributeName = 'for:scoped'; + } + } else if (attributeName !== deprecatedKeySuffix && attributeName.endsWith(deprecatedKeySuffix)) { + context.deprecate(`The "${attributeName}" attribute is deprecated. Please use "for:scoped" instead.`); + fixedAttributeName = attributeName.slice(0, 0-deprecatedKeySuffix.length) + ':scoped'; + } + // END support for deprecated for attributes + + if (fixedAttributeName !== scopedSuffix && fixedAttributeName.endsWith(scopedSuffix)) { + el.removeAttribute(attributeName); + + let finalAttributeName = fixedAttributeName.slice(0, 0-scopedSuffix.length); + + if (el.hasAttribute(finalAttributeName)) { + this.addError(`The "${attributeName}" attribute cannot be used in conjunction with the "${finalAttributeName}" attribute. (${filePosition})`); + return; + } + + let uniqueElId = this.nextUniqueId(); + let idVarName = 'marko_' + finalAttributeName + '_key' + uniqueElId; + + + let varNode = builder.var(idVarName, attribute.value); + + el.insertSiblingBefore(varNode); + let varIdNode = builder.identifier(idVarName); + + el.setAttributeValue(finalAttributeName, this.buildComponentElIdFunctionCall(varIdNode)); + + if (!el.hasAttribute('key') && !el.hasAttribute('w-id') && !el.hasAttribute('ref')) { + // The scoped attribute should be suitable for a key + el.setAttributeValue('key', varIdNode); + el.data.userAssignedKey = false; + } + } + }); +}; diff --git a/src/components/taglib/TransformHelper/index.js b/src/components/taglib/TransformHelper/index.js index c699acd87..6167048da 100644 --- a/src/components/taglib/TransformHelper/index.js +++ b/src/components/taglib/TransformHelper/index.js @@ -24,25 +24,11 @@ class TransformHelper { } setHasBoundComponentForTemplate() { + this.context.isComponent = true; + this.context.data[HAS_COMPONENT_KEY] = true; } - setComponentModule(value) { - this.context.data.componentModule = value; - } - - getComponentModule() { - return this.context.data.componentModule; - } - - setRendererModule(value) { - this.context.data.rendererModule = value; - } - - getRendererModule() { - return this.context.data.rendererModule; - } - getTemplateModule() { return { requirePath:this.context.getRequirePath(this.filename) @@ -55,15 +41,6 @@ class TransformHelper { this.context.data[WIDGET_PROPS_KEY] != null; } - getComponentProps() { - var componentProps = this.context.data[WIDGET_PROPS_KEY]; - if (!componentProps) { - this.firstBind = true; - componentProps = this.context.data[WIDGET_PROPS_KEY] = {}; - } - return componentProps; - } - addError(message, code) { this.context.addError(this.el, message, code); } @@ -81,11 +58,6 @@ class TransformHelper { return (this.context.data.componentNextElId++); } - getNestedIdExpression() { - this.assignComponentId(); - return this.getComponentIdInfo().nestedIdExpression; - } - getIdExpression() { this.assignComponentId(); return this.getComponentIdInfo().idExpression; @@ -129,11 +101,19 @@ class TransformHelper { buildComponentElIdFunctionCall(id) { var builder = this.builder; - var componentElId = builder.memberExpression( - builder.identifier('__component'), - builder.identifier('elId')); + if (id.type === 'Literal' && id.value === '') { + let componentElId = builder.memberExpression( + builder.identifier('__component'), + builder.identifier('id')); - return builder.functionCall(componentElId, arguments.length === 0 ? [] : [ id ]); + return componentElId; + } else { + let componentElId = builder.memberExpression( + builder.identifier('__component'), + builder.identifier('elId')); + + return builder.functionCall(componentElId, arguments.length === 0 ? [] : [ id ]); + } } getTransformHelper(el) { @@ -142,12 +122,12 @@ class TransformHelper { } TransformHelper.prototype.assignComponentId = require('./assignComponentId'); +TransformHelper.prototype.convertToComponent = require('./convertToComponent'); TransformHelper.prototype.handleRootNodes = require('./handleRootNodes'); -TransformHelper.prototype.handleIncludeNode = require('./handleIncludeNode'); TransformHelper.prototype.handleComponentEvents = require('./handleComponentEvents'); TransformHelper.prototype.handleComponentPreserve = require('./handleComponentPreserve'); TransformHelper.prototype.handleComponentPreserveAttrs = require('./handleComponentPreserveAttrs'); -TransformHelper.prototype.handleComponentBind = require('./handleComponentBind'); -TransformHelper.prototype.handleComponentKeyAttrs = require('./handleComponentKeyAttrs'); +TransformHelper.prototype.handleScopedAttrs = require('./handleScopedAttrs'); +TransformHelper.prototype.handleLegacyBind = require('./handleLegacyBind'); module.exports = TransformHelper; diff --git a/src/components/taglib/components-transformer.js b/src/components/taglib/components-transformer.js index 7df27ecb8..07996cd2e 100644 --- a/src/components/taglib/components-transformer.js +++ b/src/components/taglib/components-transformer.js @@ -23,10 +23,15 @@ module.exports = function transform(el, context) { } if (el.hasAttribute('w-body')) { + // This is a legacy code block and should be removed in Marko v5 context.deprecate('The "w-body" attribute is deprecated. Please use "": { + "<_preserve>": { "renderer": "./preserve-tag.js", - "@id": "string", - "@if": "expression", - "@body-only": "expression", - "autocomplete": [], - "deprecated": true + "@key": "string", + "@cid": "string", + "@if": "boolean", + "@body-only": "boolean", + "autocomplete": [] }, "": { "renderer": "./preserve-tag.js", diff --git a/src/components/taglib/preserve-tag-browser.js b/src/components/taglib/preserve-tag-browser.js index 99d8631e4..c90d79fce 100644 --- a/src/components/taglib/preserve-tag-browser.js +++ b/src/components/taglib/preserve-tag-browser.js @@ -1,34 +1,46 @@ -var getElementById = require('../util').___getElementById; +var componentsUtil = require('../util'); +var componentLookup = componentsUtil.___componentLookup; module.exports = function render(input, out) { - var globalComponentsContext = out.global.___components; - - if (globalComponentsContext && globalComponentsContext.___isRerenderInBrowser !== true && globalComponentsContext.___rerenderComponent !== undefined) { - var id = input.id; + var componentsContext = out.___components; + if (componentsContext) { // See if the DOM node with the given ID already exists. // If so, then reuse the existing DOM node instead of re-rendering // the children. We have to put a placeholder node that will get // replaced out if we find that the DOM node has already been rendered if (!('if' in input) || input['if']) { - var existingEl = getElementById(out.___document, id); - if (existingEl) { - var bodyOnly = input.bodyOnly === true; - // Don't actually render anything since the element is already in the DOM, - // but keep track that the node is being preserved so that we can ignore - // it while transforming the old DOM + var component = componentsContext.___componentDef.___component; + var globalComponentsContext = componentsContext.___globalContext; + var key = input.key; + var componentId; - if (!bodyOnly) { - var tagName = existingEl.tagName; - // If we are preserving the entire DOM node (not just the body) - // then that means that we have need to render a placeholder to - // mark the target location. We can then replace the placeholder - // node with the existing DOM node - out.element(tagName, { id: id }); + if (key) { + if (component.___keyedElements[key]) { + var bodyOnly = input.bodyOnly === true; + // Don't actually render anything since the element is already in the DOM, + // but keep track that the node is being preserved so that we can ignore + // it while transforming the old DOM + if (bodyOnly) { + globalComponentsContext.___preservedElBodies[key] = true; + } else { + // If we are preserving the entire DOM node (not just the body) + // then that means that we have need to render a placeholder to + // mark the target location. We can then replace the placeholder + // node with the existing DOM node + out.element('', null, key, null, 0, 8 /* FLAG_PRESERVE */); + globalComponentsContext.___preservedEls[key] = true; + } + + return; + } + } else if ((componentId = input.cid)) { + var existingComponent = componentLookup[componentId]; + if (existingComponent) { + out.___preserveComponent(existingComponent); + globalComponentsContext.___renderedComponentsById[componentId] = true; + return; } - - globalComponentsContext.___preserveDOMNode(id, bodyOnly); - return; } } } diff --git a/src/components/util-browser.js b/src/components/util-browser.js index d4dd6417f..65c921130 100644 --- a/src/components/util-browser.js +++ b/src/components/util-browser.js @@ -1,12 +1,6 @@ -var extend = require('raptor-util/extend'); -var markoGlobal = extend(window.$MG, { - uid: 0 -}); - -window.$MG = markoGlobal; - -var runtimeId = markoGlobal.uid++; +var markoUID = window.$MUID || (window.$MUID = { i: 0 }); +var runtimeId = markoUID.i++; var componentLookup = {}; @@ -17,18 +11,7 @@ function getComponentForEl(el, doc) { if (el) { var node = typeof el == 'string' ? (doc || defaultDocument).getElementById(el) : el; if (node) { - var component = node._w; - - while(component) { - var rootFor = component.___rootFor; - if (rootFor) { - component = rootFor; - } else { - break; - } - } - - return component; + return node.___markoComponent; } } } @@ -69,26 +52,26 @@ function emitLifecycleEvent(component, eventType, eventArg1, eventArg2) { component.emit(eventType, eventArg1, eventArg2); } -function destroyComponentForEl(el) { - var componentToDestroy = el._w; +function destroyComponentForNode(node) { + var componentToDestroy = node.___markoComponent; if (componentToDestroy) { componentToDestroy.___destroyShallow(); - el._w = null; - - while ((componentToDestroy = componentToDestroy.___rootFor)) { - componentToDestroy.___rootFor = null; - componentToDestroy.___destroyShallow(); - } } } -function destroyElRecursive(el) { - var curChild = el.firstChild; - while(curChild) { - if (curChild.nodeType === 1) { - destroyComponentForEl(curChild); - destroyElRecursive(curChild); +function destroyNodeRecursive(node, component) { + if (node.nodeType === 1) { + var key; + + if (component && (key = node.___markoKey)) { + delete component.___keyedElements[key]; + } + + var curChild = node.firstChild; + while(curChild) { + destroyComponentForNode(curChild); + destroyNodeRecursive(curChild, component); + curChild = curChild.nextSibling; } - curChild = curChild.nextSibling; } } @@ -97,52 +80,36 @@ function nextComponentId() { // marko runtimes. This allows multiple instances of marko to be // loaded in the same window and they should all place nice // together - return 'b' + ((markoGlobal.uid)++); + return 'b' + (markoUID.i++); } -function nextComponentIdProvider(out) { +function nextComponentIdProvider() { return nextComponentId; } -function getElementById(doc, id) { - return doc.getElementById(id); -} - function attachBubblingEvent(componentDef, handlerMethodName, extraArgs) { if (handlerMethodName) { - var id = componentDef.id; + var componentId = componentDef.id; if (extraArgs) { - var isRerenderInBrowser = componentDef.___globalComponentsContext.___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 - var component = componentDef.___component; - - var bubblingDomEvents = component.___bubblingDomEvents || - ( component.___bubblingDomEvents = [] ); - - bubblingDomEvents.push(extraArgs); - - return; - } else { - return [handlerMethodName, id, extraArgs]; - } + return [handlerMethodName, componentId, extraArgs]; } else { - return [handlerMethodName, id]; + return [handlerMethodName, componentId]; } } } function getMarkoPropsFromEl(el) { - var virtualProps = el._vprops; - if (virtualProps === undefined) { - virtualProps = el.getAttribute('data-marko'); - if (virtualProps) { - virtualProps = JSON.parse(virtualProps); + var vElement = el.___markoVElement; + var virtualProps; + + if (vElement) { + virtualProps = vElement.___properties; + } else { + virtualProps = el.___markoVProps; + if (!virtualProps) { + virtualProps = el.getAttribute('data-marko'); + el.___markoVProps = virtualProps = virtualProps ? JSON.parse(virtualProps) : EMPTY_OBJECT; } - el._vprops = virtualProps = virtualProps || EMPTY_OBJECT; } return virtualProps; @@ -152,9 +119,8 @@ exports.___runtimeId = runtimeId; exports.___componentLookup = componentLookup; exports.___getComponentForEl = getComponentForEl; exports.___emitLifecycleEvent = emitLifecycleEvent; -exports.___destroyComponentForEl = destroyComponentForEl; -exports.___destroyElRecursive = destroyElRecursive; +exports.___destroyComponentForNode = destroyComponentForNode; +exports.___destroyNodeRecursive = destroyNodeRecursive; exports.___nextComponentIdProvider = nextComponentIdProvider; -exports.___getElementById = getElementById; exports.___attachBubblingEvent = attachBubblingEvent; exports.___getMarkoPropsFromEl = getMarkoPropsFromEl; diff --git a/src/components/util.js b/src/components/util.js index 401ec4096..532904bf4 100644 --- a/src/components/util.js +++ b/src/components/util.js @@ -1,3 +1,7 @@ +var FLAG_WILL_RERENDER_IN_BROWSER = 1; +// var FLAG_HAS_BODY_EL = 2; +// var FLAG_HAS_HEAD_EL = 4; + function nextComponentIdProvider(out) { var prefix = out.global.componentIdPrefix || 's'; // "s" is for server (we use "b" for the browser) var nextId = 0; @@ -21,7 +25,7 @@ function attachBubblingEvent(componentDef, handlerMethodName, extraArgs) { // where the extra args will be found when the UI component is // rerendered in the browser - if (componentDef.___willRerenderInBrowser === false) { + if (componentDef.___flags & FLAG_WILL_RERENDER_IN_BROWSER) { if (eventIndex === 0) { component.___bubblingDomEvents = [extraArgs]; } else { @@ -40,3 +44,5 @@ function attachBubblingEvent(componentDef, handlerMethodName, extraArgs) { exports.___nextComponentIdProvider = nextComponentIdProvider; exports.___isServer = true; exports.___attachBubblingEvent = attachBubblingEvent; +exports.___destroyComponentForNode = function noop() {}; +exports.___destroyNodeRecursive = function noop() {}; diff --git a/src/morphdom/index.js b/src/morphdom/index.js index 3758701c9..952b74371 100644 --- a/src/morphdom/index.js +++ b/src/morphdom/index.js @@ -1,325 +1,539 @@ 'use strict'; -var defaultDoc = typeof document == 'undefined' ? undefined : document; var specialElHandlers = require('./specialElHandlers'); - -var morphAttrs = require('../runtime/vdom/VElement').___morphAttrs; +var componentsUtil = require('../components/util'); +var existingComponentLookup = componentsUtil.___componentLookup; +var destroyComponentForNode = componentsUtil.___destroyComponentForNode; +var destroyNodeRecursive = componentsUtil.___destroyNodeRecursive; +var VElement = require('../runtime/vdom/vdom').___VElement; +var virtualizeElement = VElement.___virtualize; +var morphAttrs = VElement.___morphAttrs; +var eventDelegation = require('../components/event-delegation'); var ELEMENT_NODE = 1; var TEXT_NODE = 3; var COMMENT_NODE = 8; +var COMPONENT_NODE = 2; + +// var FLAG_IS_SVG = 1; +// var FLAG_IS_TEXTAREA = 2; +// var FLAG_SIMPLE_ATTRS = 4; +var FLAG_PRESERVE = 8; function compareNodeNames(fromEl, toEl) { - return fromEl.nodeName === toEl.___nodeName; + return fromEl.___nodeName === toEl.___nodeName; } +function onBeforeNodeDiscarded(node) { + return eventDelegation.___handleNodeDetach(node); +} -function getElementById(doc, id) { - return doc.getElementById(id); +function onNodeAdded(node, componentsContext) { + if (node.nodeType === 1) { + eventDelegation.___handleNodeAttach(node, componentsContext); + } +} + +function insertBefore(node, referenceNode, parentNode) { + return parentNode.insertBefore(node, referenceNode); +} + +function insertAfter(node, referenceNode, parentNode) { + return parentNode.insertBefore(node, referenceNode && referenceNode.nextSibling); } function morphdom( - fromNode, + parentNode, + startNode, + endNode, toNode, - context, - onNodeAdded, - onBeforeElUpdated, - onBeforeNodeDiscarded, - onNodeDiscarded, - onBeforeElChildrenUpdated + doc, + componentsContext ) { + var globalComponentsContext; + var isRerenderInBrowser = false; - var doc = fromNode.ownerDocument || defaultDoc; - - // This object is used as a lookup to quickly find all keyed elements in the original DOM tree. - var removalList = []; - var foundKeys = {}; - - function walkDiscardedChildNodes(node) { - onNodeDiscarded(node); - var curChild = node.firstChild; - - while (curChild) { - walkDiscardedChildNodes(curChild); - curChild = curChild.nextSibling; - } + if (componentsContext) { + globalComponentsContext = componentsContext.___globalContext; + isRerenderInBrowser = globalComponentsContext.___isRerenderInBrowser; } + function createMarkerComment(referenceNode, parentNode) { + return doc.createComment('$marko'); + } - function addVirtualNode(vEl, parentEl) { - var realEl = vEl.___actualize(doc); + function insertVirtualNodeBefore(vNode, key, referenceEl, parentEl, component, keySequence) { + var realNode = vNode.___actualize(doc); + insertBefore(realNode, referenceEl, parentEl); - if (parentEl) { - parentEl.appendChild(realEl); - } - - onNodeAdded(realEl, context); - - var vCurChild = vEl.___firstChild; - while (vCurChild) { - var realCurChild = null; - - var key = vCurChild.id; + if (vNode.___nodeType === ELEMENT_NODE) { if (key) { - var unmatchedFromEl = getElementById(doc, key); - if (unmatchedFromEl && compareNodeNames(vCurChild, unmatchedFromEl)) { - morphEl(unmatchedFromEl, vCurChild, false); - realEl.appendChild(realCurChild = unmatchedFromEl); - } + realNode.___markoKey = key; + (component = vNode.___component || component).___keyedElements[key] = realNode; } - if (!realCurChild) { - addVirtualNode(vCurChild, realEl); - } - - vCurChild = vCurChild.___nextSibling; + morphChildren(realNode, null, null, vNode, component, keySequence); } - if (vEl.___nodeType === 1) { - var elHandler = specialElHandlers[vEl.nodeName]; - if (elHandler !== undefined) { - elHandler(realEl, vEl); - } - } - - return realEl; + onNodeAdded(realNode, componentsContext); } - function morphEl(fromEl, toEl, childrenOnly) { - var toElKey = toEl.id; - var nodeName = toEl.___nodeName; + function insertVirtualComponentBefore(vComponent, referenceNode, referenceNodeParentEl) { + var component = vComponent.___component; + component.___startNode = component.___endNode = insertBefore(createMarkerComment(), referenceNode, referenceNodeParentEl); + morphComponent(referenceNodeParentEl, component, vComponent); + } - if (childrenOnly === false) { - if (toElKey) { - // If an element with an ID is being morphed then it is will be in the final - // DOM so clear it out of the saved elements collection - foundKeys[toElKey] = true; + function resolveComponentEndNode(startNode, vChild, parentNode) { + var endNode = startNode; + + // We track text nodes because multiple adjacent VText nodes should + // be treated as a single VText node for purposes of pairing with HTML + // that was rendered on the server since browsers will only see + // a single text node + var isPrevText = vChild.___nodeType === TEXT_NODE; + + while((vChild = vChild.___nextSibling)) { + var nextRealNode = endNode.nextSibling; + + // We stop when there are no more corresponding real nodes or when + // we reach the end boundary for our UI component + if (!nextRealNode || nextRealNode.___endNode) { + break; } + var isText = vChild.___nodeType === TEXT_NODE; + if (isText && isPrevText) { + // Pretend like we didn't see this VText node since it + // the previous vnode was also a VText node + continue; + } + endNode = nextRealNode; + isPrevText = isText; + } - var constId = toEl.___constId; - if (constId !== undefined) { - var otherProps = fromEl._vprops; - if (otherProps !== undefined && constId === otherProps.c) { - return; + return endNode; + } + + function morphComponent(parentFromNode, component, vComponent) { + // We create a key sequence to generate unique keys since a key + // can be repeated + var keySequence = globalComponentsContext.___createKeySequence(); + + var startNode = component.___startNode; + var endNode = component.___endNode; + startNode.___markoComponent = undefined; + endNode.___endNode = undefined; + + var beforeChild = startNode.previousSibling; + var afterChild = endNode.nextSibling; + + morphChildren(parentFromNode, startNode, afterChild, vComponent, component, keySequence); + + endNode = undefined; + + if (beforeChild) { + startNode = beforeChild.nextSibling; + if (!startNode || startNode === afterChild) { + startNode = endNode = insertAfter(createMarkerComment(), beforeChild, parentFromNode); + } + } else { + startNode = parentFromNode.firstChild; + if (!startNode) { + startNode = endNode = insertAfter(createMarkerComment(), beforeChild, parentFromNode); + } + } + + if (!endNode) { + if (afterChild) { + endNode = afterChild.previousSibling; + } else { + endNode = parentFromNode.lastChild; + } + } + + // Make sure we don't use a detached node as the component boundary and + // we can't use a node that is already the boundary node for another component + if (startNode.___markoDetached !== undefined || startNode.___markoComponent) { + startNode = insertBefore(createMarkerComment(), startNode, parentFromNode); + } + + if (endNode.___markoDetached !== undefined || endNode.___endNode) { + endNode = insertAfter(createMarkerComment(), endNode, parentFromNode); + } + + startNode.___markoComponent = component; + endNode.___endNode = true; + + component.___startNode = startNode; + component.___endNode = endNode; + + return afterChild; + } + + var detachedNodes = []; + + function detachNode(node, parentNode, component) { + if (node.nodeType === ELEMENT_NODE) { + detachedNodes.push(node); + node.___markoDetached = component || true; + } else { + destroyNodeRecursive(node); + parentNode.removeChild(node); + } + } + + function destroyComponent(component) { + component.destroy(onBeforeNodeDiscarded); + } + + function morphChildren(parentFromNode, startNode, endNode, toNode, component, keySequence) { + var curFromNodeChild = startNode; + var curToNodeChild = toNode.___firstChild; + + var curToNodeKey; + var curFromNodeKey; + var curToNodeType; + + var fromNextSibling; + var toNextSibling; + var matchingFromEl; + var matchingFromComponent; + var toComponent; + var curVFromNodeChild; + var fromComponent; + + outer: while (curToNodeChild) { + toNextSibling = curToNodeChild.___nextSibling; + curToNodeType = curToNodeChild.___nodeType; + + if (curToNodeType === COMPONENT_NODE) { + toComponent = curToNodeChild.___component; + + if ((matchingFromComponent = existingComponentLookup[toComponent.id]) === undefined) { + if (isRerenderInBrowser === true) { + var firstVChild = curToNodeChild.___firstChild; + if (firstVChild) { + if (!curFromNodeChild) { + curFromNodeChild = insertBefore(createMarkerComment(), null, parentFromNode); + } + + toComponent.___startNode = curFromNodeChild; + toComponent.___endNode = resolveComponentEndNode(curFromNodeChild, firstVChild, parentFromNode); + + } else { + toComponent.___startNode = toComponent.___endNode = insertBefore(createMarkerComment(), curFromNodeChild, parentFromNode); + } + + curFromNodeChild = morphComponent(parentFromNode, toComponent, curToNodeChild); + } else { + insertVirtualComponentBefore(curToNodeChild, curFromNodeChild, parentFromNode); + } + } else { + if (matchingFromComponent.___startNode !== curFromNodeChild) { + if (curFromNodeChild && + (fromComponent = curFromNodeChild.___markoComponent) && + globalComponentsContext.___renderedComponentsById[fromComponent.id] === undefined) { + + // The component associated with the current real DOM node was not rendered + // so we should just remove it out of the real DOM by destroying it + curFromNodeChild = fromComponent.___endNode.nextSibling; + destroyComponent(fromComponent); + continue; + } + + // We need to move the existing component into + // the correct location + insertBefore(matchingFromComponent.___detach(), curFromNodeChild, parentFromNode); + } + + if (curToNodeChild.___preserve) { + curFromNodeChild = matchingFromComponent.___endNode.nextSibling; + } else { + curFromNodeChild = morphComponent(parentFromNode, toComponent, curToNodeChild); + } } - } - if (onBeforeElUpdated(fromEl, toElKey, context) === true) { - return; - } + curToNodeChild = toNextSibling; + continue; + } else if ((curToNodeKey = curToNodeChild.___key)) { + curVFromNodeChild = undefined; + curFromNodeKey = undefined; - morphAttrs(fromEl, toEl); - } + // We have a keyed element. This is the fast path for matching + // up elements + curToNodeKey = keySequence.___nextKey(curToNodeKey); - if (onBeforeElChildrenUpdated(fromEl, toElKey, context) === true) { - return; - } + if (curFromNodeChild) { + if (curFromNodeChild !== endNode) { + curFromNodeKey = curFromNodeChild.___markoKey; + curVFromNodeChild = curFromNodeChild.___markoVElement; + fromNextSibling = curFromNodeChild.nextSibling; + } + } - if (nodeName !== 'TEXTAREA') { - var curToNodeChild = toEl.___firstChild; - var curFromNodeChild = fromEl.firstChild; - var curToNodeKey; - var curFromNodeKey; - - var fromNextSibling; - var toNextSibling; - var matchingFromEl; - - outer: while (curToNodeChild) { - toNextSibling = curToNodeChild.___nextSibling; - curToNodeKey = curToNodeChild.id; - - while (curFromNodeChild) { - fromNextSibling = curFromNodeChild.nextSibling; - - curFromNodeKey = curFromNodeChild.id; - - var curFromNodeType = curFromNodeChild.nodeType; - - var isCompatible = undefined; - - if (curFromNodeType === curToNodeChild.___nodeType) { - if (curFromNodeType === ELEMENT_NODE) { - // Both nodes being compared are Element nodes - - if (curToNodeKey) { - // The target node has a key so we want to match it up with the correct element - // in the original DOM tree - if (curToNodeKey !== curFromNodeKey) { - // The current element in the original DOM tree does not have a matching key so - // let's check our lookup to see if there is a matching element in the original - // DOM tree - if ((matchingFromEl = getElementById(doc, curToNodeKey))) { - if (curFromNodeChild.nextSibling === matchingFromEl) { - // Special case for single element removals. To avoid removing the original - // DOM node out of the tree (since that can break CSS transitions, etc.), - // we will instead discard the current node and wait until the next - // iteration to properly match up the keyed target element with its matching - // element in the original tree - isCompatible = false; - } else { - // We found a matching keyed element somewhere in the original DOM tree. - // Let's moving the original DOM node into the current position and morph - // it. - - // NOTE: We use insertBefore instead of replaceChild because we want to go through - // the `removeNode()` function for the node that is being discarded so that - // all lifecycle hooks are correctly invoked + if (curFromNodeKey === curToNodeKey) { + // Elements line up. Now we just have to make sure they are compatible + if ((curToNodeChild.___flags & FLAG_PRESERVE) === 0) { + // We just skip over the fromNode if it is preserved - fromEl.insertBefore(matchingFromEl, curFromNodeChild); + if (compareNodeNames(curToNodeChild, curVFromNodeChild)) { + morphEl(curFromNodeChild, curVFromNodeChild, curToNodeChild, component, keySequence); + } else { + // Remove the old node + detachNode(curFromNodeChild, parentFromNode, component); - fromNextSibling = curFromNodeChild.nextSibling; - removalList.push(curFromNodeChild); - - curFromNodeChild = matchingFromEl; - } - } else { - // The nodes are not compatible since the "to" node has a key and there - // is no matching keyed node in the source tree - isCompatible = false; - } - } - } else if (curFromNodeKey) { - // The original has a key - isCompatible = false; - } - - isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild) === true; - - if (isCompatible === true) { - // We found compatible DOM elements so transform - // the current "from" node to match the current - // target DOM node. - morphEl(curFromNodeChild, curToNodeChild, false); - } - - } else if (curFromNodeType === TEXT_NODE || curFromNodeType === COMMENT_NODE) { - // Both nodes being compared are Text or Comment nodes - isCompatible = true; - // Simply update nodeValue on the original node to - // change the text value - curFromNodeChild.nodeValue = curToNodeChild.___nodeValue; + // Incompatible nodes. Just move the target VNode into the DOM at this position + insertVirtualNodeBefore(curToNodeChild, curToNodeKey, curFromNodeChild, parentFromNode, component, keySequence); } } - - if (isCompatible === true) { - // Advance both the "to" child and the "from" child since we found a match - curToNodeChild = toNextSibling; - curFromNodeChild = fromNextSibling; - continue outer; - } - - // No compatible match so remove the old node from the DOM and continue trying to find a - // match in the original DOM. However, we only do this if the from node is not keyed - // since it is possible that a keyed node might match up with a node somewhere else in the - // target tree and we don't want to discard it just yet since it still might find a - // home in the final DOM tree. After everything is done we will remove any keyed nodes - // that didn't find a home - removalList.push(curFromNodeChild); - - curFromNodeChild = fromNextSibling; - } - - // If we got this far then we did not find a candidate match for - // our "to node" and we exhausted all of the children "from" - // nodes. Therefore, we will just append the current "to" node - // to the end - if (curToNodeKey && (matchingFromEl = getElementById(doc, curToNodeKey)) && compareNodeNames(matchingFromEl, curToNodeChild)) { - fromEl.appendChild(matchingFromEl); - morphEl(matchingFromEl, curToNodeChild, false); } else { - addVirtualNode(curToNodeChild, fromEl); + if ((matchingFromEl = component.___keyedElements[curToNodeKey]) === undefined) { + if (isRerenderInBrowser === true && curFromNodeChild && + curFromNodeChild.nodeType === ELEMENT_NODE && + curFromNodeChild.nodeName === curToNodeChild.___nodeName) { + curVFromNodeChild = virtualizeElement(curFromNodeChild); + curFromNodeChild.___markoKey = curToNodeKey; + morphEl(curFromNodeChild, curVFromNodeChild, curToNodeChild, component, keySequence); + curToNodeChild = toNextSibling; + curFromNodeChild = fromNextSibling; + continue; + } + + insertVirtualNodeBefore(curToNodeChild, curToNodeKey, curFromNodeChild, parentFromNode, component, keySequence); + fromNextSibling = curFromNodeChild; + } else { + if (matchingFromEl.___markoDetached !== undefined) { + matchingFromEl.___markoDetached = undefined; + } + curVFromNodeChild = matchingFromEl.___markoVElement; + + if (compareNodeNames(curVFromNodeChild, curToNodeChild)) { + if (fromNextSibling === matchingFromEl) { + // Single element removal: + // A <-> A + // B <-> C <-- We are here + // C D + // D + // + // Single element swap: + // A <-> A + // B <-> C <-- We are here + // C B + + if (toNextSibling && toNextSibling.___key === curFromNodeKey) { + // Single element swap + + // We want to stay on the current real DOM node + fromNextSibling = curFromNodeChild; + + // But move the matching element into place + insertBefore(matchingFromEl, curFromNodeChild, parentFromNode); + } else { + // Single element removal + + // We need to remove the current real DOM node + // and the matching real DOM node will fall into + // place. We will continue diffing with next sibling + // after the real DOM node that just fell into place + fromNextSibling = fromNextSibling.nextSibling; + + if (curFromNodeChild) { + detachNode(curFromNodeChild, parentFromNode, component); + } + } + + } else { + // A <-> A + // B <-> D <-- We are here + // C + // D + + // We need to move the matching node into place + insertAfter(matchingFromEl, curFromNodeChild, parentFromNode); + + if (curFromNodeChild) { + detachNode(curFromNodeChild, parentFromNode, component); + } + } + + if ((curToNodeChild.___flags & FLAG_PRESERVE) === 0) { + morphEl(matchingFromEl, curVFromNodeChild, curToNodeChild, component, keySequence); + } + + + } else { + insertVirtualNodeBefore(curToNodeChild, curToNodeKey, curFromNodeChild, parentFromNode, component, keySequence); + detachNode(matchingFromEl, parentFromNode, component); + } + } } curToNodeChild = toNextSibling; curFromNodeChild = fromNextSibling; + continue; } - // We have processed all of the "to nodes". If curFromNodeChild is - // non-null then we still have some from nodes left over that need - // to be removed - while (curFromNodeChild) { - removalList.push(curFromNodeChild); - curFromNodeChild = curFromNodeChild.nextSibling; + // The know the target node is not a VComponent node and we know + // it is also not a preserve node. Let's now match up the HTML + // element, text node, comment, etc. + while (curFromNodeChild && curFromNodeChild !== endNode) { + if ((fromComponent = curFromNodeChild.___markoComponent) && fromComponent !== component) { + // The current "to" element is not associated with a component, + // but the current "from" element is associated with a component + + // Even if we destroy the current component in the original + // DOM or not, we still need to skip over it since it is + // not compatible with the current "to" node + curFromNodeChild = fromComponent.___endNode.nextSibling; + + if (!globalComponentsContext.___renderedComponentsById[fromComponent.id]) { + destroyComponent(fromComponent); + } + + continue; // Move to the next "from" node + } + + fromNextSibling = curFromNodeChild.nextSibling; + + var curFromNodeType = curFromNodeChild.nodeType; + + var isCompatible = undefined; + + if (curFromNodeType === curToNodeType) { + if (curFromNodeType === ELEMENT_NODE) { + // Both nodes being compared are Element nodes + curVFromNodeChild = curFromNodeChild.___markoVElement; + if (curVFromNodeChild === undefined) { + if (isRerenderInBrowser === true) { + curVFromNodeChild = virtualizeElement(curFromNodeChild); + } else { + // Skip over nodes that don't look like ours... + curFromNodeChild = fromNextSibling; + continue; + } + } else if ((curFromNodeKey = curVFromNodeChild.___key)) { + // We have a keyed element here but our target VDOM node + // is not keyed so this not doesn't belong + isCompatible = false; + } + + isCompatible = isCompatible !== false && compareNodeNames(curVFromNodeChild, curToNodeChild) === true; + + if (isCompatible === true) { + // We found compatible DOM elements so transform + // the current "from" node to match the current + // target DOM node. + morphEl(curFromNodeChild, curVFromNodeChild, curToNodeChild, component, keySequence); + } + + } else if (curFromNodeType === TEXT_NODE || curFromNodeType === COMMENT_NODE) { + // Both nodes being compared are Text or Comment nodes + isCompatible = true; + // Simply update nodeValue on the original node to + // change the text value + curFromNodeChild.nodeValue = curToNodeChild.___nodeValue; + } + } + + if (isCompatible === true) { + // Advance both the "to" child and the "from" child since we found a match + curToNodeChild = toNextSibling; + curFromNodeChild = fromNextSibling; + continue outer; + } + + if (curFromNodeKey) { + if (globalComponentsContext.___preservedEls[curFromNodeKey] === undefined) { + detachNode(curFromNodeChild, parentFromNode, component); + } + } else { + detachNode(curFromNodeChild, parentFromNode, component); + } + + curFromNodeChild = fromNextSibling; + } // END: while (curFromNodeChild) + + // If we got this far then we did not find a candidate match for + // our "to node" and we exhausted all of the children "from" + // nodes. Therefore, we will just append the current "to" node + // to the end + insertVirtualNodeBefore(curToNodeChild, curToNodeKey, curFromNodeChild, parentFromNode, component, keySequence); + + curToNodeChild = toNextSibling; + curFromNodeChild = fromNextSibling; + } + + // We have processed all of the "to nodes". If curFromNodeChild is + // non-null then we still have some from nodes left over that need + // to be removed + while (curFromNodeChild && (endNode === null || curFromNodeChild !== endNode)) { + fromNextSibling = curFromNodeChild.nextSibling; + + if ((fromComponent = curFromNodeChild.___markoComponent)) { + if (globalComponentsContext.___renderedComponentsById[fromComponent.id]) { + // Skip over this component since it was rendered in the target VDOM + // and will be moved into place later + curFromNodeChild = fromComponent.___endNode.nextSibling; + continue; + } } + + detachNode(curFromNodeChild, parentFromNode, component); + + curFromNodeChild = fromNextSibling; + } + } + + function morphEl(fromEl, vFromEl, toEl, component, keySequence) { + var toElKey = toEl.___key; + var nodeName = toEl.___nodeName; + + component = toEl.___component || component; + + if (isRerenderInBrowser === true && toElKey) { + component.___keyedElements[toElKey] = fromEl; + } + + var constId = toEl.___constId; + if (constId !== undefined && vFromEl.___constId === constId) { + return; + } + + morphAttrs(fromEl, vFromEl, toEl); + + if (toElKey && globalComponentsContext.___preservedElBodies[toElKey] === true) { + // Don't morph the children since they are preserved + return; + } + + if (nodeName !== 'TEXTAREA') { + morphChildren(fromEl, fromEl.firstChild, null, toEl, component, keySequence); } var specialElHandler = specialElHandlers[nodeName]; - if (specialElHandler) { + if (specialElHandler !== undefined) { specialElHandler(fromEl, toEl); } } // END: morphEl(...) - var morphedNode = fromNode; - var fromNodeType = morphedNode.nodeType; - var toNodeType = toNode.___nodeType; - var morphChildrenOnly = false; - var shouldMorphEl = true; - var newNode; + morphChildren(parentNode, startNode, endNode, toNode); - // Handle the case where we are given two DOM nodes that are not - // compatible (e.g.
--> or
--> TEXT) - if (fromNodeType == ELEMENT_NODE) { - if (toNodeType == ELEMENT_NODE) { - if (!compareNodeNames(fromNode, toNode)) { - newNode = toNode.___actualize(doc); - morphChildrenOnly = true; - removalList.push(fromNode); - } - } else { - // Going from an element node to a text or comment node - removalList.push(fromNode); - newNode = toNode.___actualize(doc); - shouldMorphEl = false; - } - } else if (fromNodeType == TEXT_NODE || fromNodeType == COMMENT_NODE) { // Text or comment node - if (toNodeType == fromNodeType) { - morphedNode.nodeValue = toNode.___nodeValue; - return morphedNode; - } else { - // Text node to something else - removalList.push(fromNode); - newNode = addVirtualNode(toNode); - shouldMorphEl = false; - } - } + detachedNodes.forEach(function(node) { + var detachedFromComponent = node.___markoDetached; - if (shouldMorphEl === true) { - morphEl(newNode || morphedNode, toNode, morphChildrenOnly); - } + if (detachedFromComponent !== undefined) { + node.___markoDetached = undefined; - if (newNode) { - if (fromNode.parentNode) { - fromNode.parentNode.replaceChild(newNode, fromNode); - } - } + destroyComponentForNode(node); + destroyNodeRecursive(node, detachedFromComponent !== true && detachedFromComponent); - // We now need to loop over any keyed nodes that might need to be - // removed. We only do the removal if we know that the keyed node - // never found a match. When a keyed node is matched up we remove - // it out of fromNodesLookup and we use fromNodesLookup to determine - // if a keyed node has been matched up or not - for (var i=0, len=removalList.length; i= 0; --i) { - var attr = oldAttributesList[i]; - - if (attr.specified !== false) { - attrName = attr.name; - if (attrName !== 'data-marko') { - var attrNamespaceURI = attr.namespaceURI; - if (attrNamespaceURI === NS_XLINK) { - oldAttrs[ATTR_XLINK_HREF] = attr.value; - } else { - oldAttrs[attrName] = attr.value; - } - } - } - } - - // We don't want preserved attributes to show up in either the old - // or new attribute map. - removePreservedAttributes(oldAttrs, props, false); } - fromEl._vattrs = attrs; - var attrValue; - var flags = toEl.___flags; - var oldFlags; + var toFlags = toEl.___flags; - if (flags & FLAG_SIMPLE_ATTRS && ((oldFlags = fromEl._vflags) & FLAG_SIMPLE_ATTRS)) { + + if (toFlags & FLAG_SIMPLE_ATTRS && fromFlags & FLAG_SIMPLE_ATTRS) { if (oldAttrs['class'] !== (attrValue = attrs['class'])) { fromEl.className = attrValue; } @@ -309,6 +331,7 @@ VElement.___morphAttrs = function(fromEl, toEl) { return; } + // In some cases we only want to set an attribute value for the first // render or we don't want certain attributes to be touched. To support // that use case we delete out all of the preserved attributes @@ -352,7 +375,7 @@ VElement.___morphAttrs = function(fromEl, toEl) { // was not a virtualized node (i.e., a node that was not rendered by a // Marko template, but rather a node that was created from an HTML // string or a real DOM node). - if (!attrs.id || props.___virtualized === true) { + if (toEl.___key === null) { for (attrName in oldAttrs) { if (!(attrName in attrs)) { if (attrName === ATTR_XLINK_HREF) { diff --git a/src/runtime/vdom/VNode.js b/src/runtime/vdom/VNode.js index 01e161a9a..937a2c706 100644 --- a/src/runtime/vdom/VNode.js +++ b/src/runtime/vdom/VNode.js @@ -1,6 +1,4 @@ /* jshint newcap:false */ -var specialElHandlers = require('../../morphdom/specialElHandlers'); - function VNode() {} VNode.prototype = { @@ -13,6 +11,8 @@ VNode.prototype = { this.___nextSiblingInternal = null; }, + ___component: null, + get ___firstChild() { var firstChild = this.___firstChildInternal; @@ -49,10 +49,10 @@ VNode.prototype = { ___appendChild: function(child) { this.___childCount++; - if (this.___isTextArea) { + if (this.___isTextArea === true) { if (child.___Text) { var childValue = child.___nodeValue; - this.___value = (this.___value || '') + childValue; + this.___valueInternal = (this.___valueInternal || '') + childValue; } else { throw TypeError(); } @@ -74,32 +74,13 @@ VNode.prototype = { }, ___finishChild: function finishChild() { - if (this.___childCount == this.___finalChildCount && this.___parentNode) { + if (this.___childCount === this.___finalChildCount && this.___parentNode) { return this.___parentNode.___finishChild(); } else { return this; } }, - actualize: function(doc) { - var actualNode = this.___actualize(doc); - - var curChild = this.___firstChild; - - while(curChild) { - actualNode.appendChild(curChild.actualize(doc)); - curChild = curChild.___nextSibling; - } - - if (this.___nodeType === 1) { - var elHandler = specialElHandlers[this.___nodeName]; - if (elHandler !== undefined) { - elHandler(actualNode, this); - } - } - - return actualNode; - } // ,toJSON: function() { // var clone = Object.assign({ diff --git a/src/runtime/vdom/helpers.js b/src/runtime/vdom/helpers.js index 5561bf765..e6ae716b3 100644 --- a/src/runtime/vdom/helpers.js +++ b/src/runtime/vdom/helpers.js @@ -10,8 +10,8 @@ var extend = require('raptor-util/extend'); var classList = commonHelpers.cl; var helpers = extend({ - e: function(tagName, attrs, childCount, flags, props) { - return new VElement(tagName, attrs, childCount, flags, props); + e: function(tagName, attrs, key, component, childCount, flags, props) { + return new VElement(tagName, attrs, key, component, childCount, flags, props); }, t: function(value) { diff --git a/src/runtime/vdom/preserve-attrs.js b/src/runtime/vdom/preserve-attrs.js index 6704b654a..314078786 100644 --- a/src/runtime/vdom/preserve-attrs.js +++ b/src/runtime/vdom/preserve-attrs.js @@ -1,11 +1,9 @@ var extend = require('raptor-util/extend'); -function removePreservedAttributes(attrs, props, clone) { +function removePreservedAttributes(attrs, props) { var preservedAttrs = props && props.noupdate; if (preservedAttrs) { - if (clone) { - attrs = extend({}, attrs); - } + attrs = extend({}, attrs); preservedAttrs.forEach(function(preservedAttrName) { delete attrs[preservedAttrName]; }); diff --git a/src/runtime/vdom/vdom.js b/src/runtime/vdom/vdom.js index e13d938ac..111e533db 100644 --- a/src/runtime/vdom/vdom.js +++ b/src/runtime/vdom/vdom.js @@ -3,12 +3,11 @@ var VComment = require('./VComment'); var VDocumentFragment = require('./VDocumentFragment'); var VElement = require('./VElement'); var VText = require('./VText'); +var VComponent = require('./VComponent'); -var FLAG_IS_TEXTAREA = 2; var defaultDocument = typeof document != 'undefined' && document; var specialHtmlRegexp = /[&<]/; -var xmlnsRegExp = /^xmlns(:|$)/; -var virtualizedProps = { ___virtualized: true }; + function virtualizeChildNodes(node, vdomParent) { var curChild = node.firstChild; @@ -18,44 +17,10 @@ function virtualizeChildNodes(node, vdomParent) { } } -function virtualize(node) { +function virtualize(node, shallow) { switch(node.nodeType) { case 1: - var attributes = node.attributes; - var attrCount = attributes.length; - - var attrs; - - if (attrCount) { - attrs = {}; - for (var i=0; i": { "code-generator": "./import-tag", + "no-output": true, "parse-options": { "relaxRequireCommas": true } @@ -135,7 +136,8 @@ { "descriptionMoreURL": "http://markojs.com/docs/marko/language-guide/#macros" } - ] + ], + "no-output": true }, "": { "code-generator": "./macro-body-tag", @@ -167,6 +169,7 @@ }, "": { "code-generator": "./static-tag", + "no-output": true, "parse-options": { "ignoreAttributes": true } diff --git a/src/taglibs/html/marko.json b/src/taglibs/html/marko.json index f1437d13a..0fbb84080 100644 --- a/src/taglibs/html/marko.json +++ b/src/taglibs/html/marko.json @@ -1127,7 +1127,8 @@ "html": true, "attribute-groups": [ "html-attributes" - ] + ], + "openTagOnly": true }, "attribute-groups": { "html-attributes": { diff --git a/test/autotests/async-render/components-await-title/expected.html b/test/autotests/async-render/components-await-title/expected.html index aeec1ed10..3b556a035 100644 --- a/test/autotests/async-render/components-await-title/expected.html +++ b/test/autotests/async-render/components-await-title/expected.html @@ -1 +1 @@ -Welcome Frank
Hello
+Welcome Frank
Hello
\ No newline at end of file diff --git a/test/autotests/compiler-browser/dynamic-tag-name/expected.js b/test/autotests/compiler-browser/dynamic-tag-name/expected.js index f4fa9a269..084c32b24 100644 --- a/test/autotests/compiler-browser/dynamic-tag-name/expected.js +++ b/test/autotests/compiler-browser/dynamic-tag-name/expected.js @@ -5,7 +5,7 @@ var marko_template = module.exports = require("marko/src/vdom").t(); function render(input, out) { var data = input; - out.ed(foo ? "foo" : "bar", null, 0); + out.ed(foo ? "foo" : "bar", null, null, null, 0); } marko_template._ = render; diff --git a/test/autotests/compiler-browser/simple/expected.js b/test/autotests/compiler-browser/simple/expected.js index 74b988d42..1728e7744 100644 --- a/test/autotests/compiler-browser/simple/expected.js +++ b/test/autotests/compiler-browser/simple/expected.js @@ -6,12 +6,12 @@ var marko_template = module.exports = require("marko/src/vdom").t(), marko_createElement = marko_helpers.e, marko_const = marko_helpers.const, marko_const_nextId = marko_const("295cea"), - marko_node0 = marko_createElement("DIV", null, 1, 0, { - c: marko_const_nextId() + marko_node0 = marko_createElement("DIV", null, null, null, 1, 0, { + i: marko_const_nextId() }) .t("No colors!"), - marko_node1 = marko_createElement("DIV", null, 1, 0, { - c: marko_const_nextId() + marko_node1 = marko_createElement("DIV", null, null, null, 1, 0, { + i: marko_const_nextId() }) .t("No colors!"); @@ -28,7 +28,7 @@ function render(input, out) { out.be("UL"); marko_forEach(input.colors, function(color) { - out.e("LI", null, 1) + out.e("LI", null, null, null, 1) .t(color); }); @@ -41,7 +41,7 @@ function render(input, out) { out.be("UL"); marko_forEach(input.colors, function(color) { - out.e("LI", null, 1) + out.e("LI", null, null, null, 1) .t(color); }); diff --git a/test/autotests/compiler-browser/svg-anchor/expected.js b/test/autotests/compiler-browser/svg-anchor/expected.js index b07a88e5a..affb7cd0f 100644 --- a/test/autotests/compiler-browser/svg-anchor/expected.js +++ b/test/autotests/compiler-browser/svg-anchor/expected.js @@ -8,13 +8,13 @@ var marko_template = module.exports = require("marko/src/vdom").t(), marko_node0 = marko_createElement("svg", { width: "140", height: "30" - }, 1, 1, { - c: marko_const_nextId() + }, null, null, 1, 1, { + i: marko_const_nextId() }) .e("a", { "xlink:href": "https://developer.mozilla.org/en-US/docs/SVG", target: "_blank" - }, 0, 1); + }, null, null, 0, 1); function render(input, out) { var data = input; diff --git a/test/autotests/compiler-browser/svg-dynamic-tag-name/expected.js b/test/autotests/compiler-browser/svg-dynamic-tag-name/expected.js index 7cb14e5c5..2ab10723f 100644 --- a/test/autotests/compiler-browser/svg-dynamic-tag-name/expected.js +++ b/test/autotests/compiler-browser/svg-dynamic-tag-name/expected.js @@ -15,8 +15,8 @@ function render(input, out) { var isCircle = true; - out.e("svg", marko_attrs0, 1, 1) - .e(isCircle ? "circle" : "square", marko_attrs1, 0, 1); + out.e("svg", marko_attrs0, null, null, 1, 1) + .e(isCircle ? "circle" : "square", marko_attrs1, null, null, 0, 1); } marko_template._ = render; diff --git a/test/autotests/compiler-browser/svg/expected.js b/test/autotests/compiler-browser/svg/expected.js index da0db4cea..8fac00093 100644 --- a/test/autotests/compiler-browser/svg/expected.js +++ b/test/autotests/compiler-browser/svg/expected.js @@ -8,14 +8,14 @@ var marko_template = module.exports = require("marko/src/vdom").t(), marko_node0 = marko_createElement("svg", { viewBox: "0 0 200 200", xmlns: "http://www.w3.org/2000/svg" - }, 1, 1, { - c: marko_const_nextId() + }, null, null, 1, 1, { + i: marko_const_nextId() }) .e("circle", { cx: "100", cy: "100", r: "100" - }, 0, 1); + }, null, null, 0, 1); function render(input, out) { var data = input; diff --git a/test/autotests/components-browser/repeated-with-label-ref/index.marko b/test/autotests/components-browser-deprecated/for-key-repeated/index.marko similarity index 90% rename from test/autotests/components-browser/repeated-with-label-ref/index.marko rename to test/autotests/components-browser-deprecated/for-key-repeated/index.marko index a87bf72d7..6bf35bc95 100644 --- a/test/autotests/components-browser/repeated-with-label-ref/index.marko +++ b/test/autotests/components-browser-deprecated/for-key-repeated/index.marko @@ -2,11 +2,11 @@ class { } -
+
-
\ No newline at end of file +
diff --git a/test/autotests/components-browser-deprecated/for-key-repeated/test.js b/test/autotests/components-browser-deprecated/for-key-repeated/test.js new file mode 100644 index 000000000..8451257d3 --- /dev/null +++ b/test/autotests/components-browser-deprecated/for-key-repeated/test.js @@ -0,0 +1,31 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var fields = [ + { + value: 'name', + label: 'Name' + }, + { + value: 'age', + label: 'Age' + } + ]; + + var component = helpers.mount(require('./index'), { + fields: fields + }); + + var inputs = component.getEl('root').querySelectorAll('input'); + var labels = component.getEl('root').querySelectorAll('label'); + + expect(inputs.length).to.equal(fields.length); + + for (var i=0; i${input.count}
diff --git a/test/autotests/components-browser/diffpatch-boundary-inner-component-only/index.marko b/test/autotests/components-browser/diffpatch-boundary-inner-component-only/index.marko new file mode 100644 index 000000000..c320bebf8 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-boundary-inner-component-only/index.marko @@ -0,0 +1,9 @@ +class { + onCreate() { + this.state = { + count: 0 + } + } +} + + diff --git a/test/autotests/components-browser/diffpatch-boundary-inner-component-only/test.js b/test/autotests/components-browser/diffpatch-boundary-inner-component-only/test.js new file mode 100644 index 000000000..f000b76e8 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-boundary-inner-component-only/test.js @@ -0,0 +1,21 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + var innerComponent = component.getComponent('inner'); + + expect(innerComponent.___startNode.className).to.equal('inner'); + expect(component.___startNode).to.not.equal(innerComponent.___startNode); + expect(component.___endNode).to.not.equal(innerComponent.___endNode); + expect(helpers.targetEl.querySelector('.inner').innerHTML).to.equal('0'); + + component.state.count++; + component.update(); + + innerComponent = component.getComponent('inner'); + + expect(innerComponent.___startNode.className).to.equal('inner'); + expect(component.___startNode).to.not.equal(innerComponent.___startNode); + expect(component.___endNode).to.not.equal(innerComponent.___endNode); + expect(helpers.targetEl.querySelector('.inner').innerHTML).to.equal('1'); +}; diff --git a/test/autotests/components-browser/diffpatch-component-mismatch-append/components/bar/index.marko b/test/autotests/components-browser/diffpatch-component-mismatch-append/components/bar/index.marko new file mode 100644 index 000000000..c991c39bb --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-mismatch-append/components/bar/index.marko @@ -0,0 +1,3 @@ +class {} + +${input.name}
diff --git a/test/autotests/components-browser/diffpatch-component-mismatch-append/components/foo/index.marko b/test/autotests/components-browser/diffpatch-component-mismatch-append/components/foo/index.marko new file mode 100644 index 000000000..ccb76c5f3 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-mismatch-append/components/foo/index.marko @@ -0,0 +1,3 @@ +class {} + +${input.name} diff --git a/test/autotests/components-browser/diffpatch-component-mismatch-append/index.marko b/test/autotests/components-browser/diffpatch-component-mismatch-append/index.marko new file mode 100644 index 000000000..9face8ab1 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-mismatch-append/index.marko @@ -0,0 +1,19 @@ +class { + onCreate() { + this.state = { + count: 0 + } + } +} + + + + + + + + + + + + diff --git a/test/autotests/components-browser/diffpatch-component-mismatch-append/test.js b/test/autotests/components-browser/diffpatch-component-mismatch-append/test.js new file mode 100644 index 000000000..bb602878f --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-mismatch-append/test.js @@ -0,0 +1,21 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + + var children; + + children = component.getEl('root').children; + expect(children.length).to.equal(2); + expect(children[0].innerHTML).to.equal('foo-a'); + expect(children[1].innerHTML).to.equal('bar-b'); + + component.state.count++; + component.update(); + + children = component.getEl('root').children; + expect(children.length).to.equal(3); + expect(children[0].innerHTML).to.equal('foo-a'); + expect(children[1].innerHTML).to.equal('foo-b'); + expect(children[2].innerHTML).to.equal('bar-c'); +}; diff --git a/test/autotests/components-browser/diffpatch-component-mismatch/components/bar/index.marko b/test/autotests/components-browser/diffpatch-component-mismatch/components/bar/index.marko new file mode 100644 index 000000000..3aeda96a5 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-mismatch/components/bar/index.marko @@ -0,0 +1,3 @@ +class {} + +bar ${component.id} diff --git a/test/autotests/components-browser/diffpatch-component-mismatch/components/foo/index.marko b/test/autotests/components-browser/diffpatch-component-mismatch/components/foo/index.marko new file mode 100644 index 000000000..f8cf2747c --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-mismatch/components/foo/index.marko @@ -0,0 +1,3 @@ +class {} + +foo ${component.id} diff --git a/test/autotests/components-browser/diffpatch-component-mismatch/index.marko b/test/autotests/components-browser/diffpatch-component-mismatch/index.marko new file mode 100644 index 000000000..8b50860b8 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-mismatch/index.marko @@ -0,0 +1,19 @@ +class { + onCreate() { + this.state = { + count: 0 + } + } +} + + + + + + + + + + + + diff --git a/test/autotests/components-browser/diffpatch-component-mismatch/test.js b/test/autotests/components-browser/diffpatch-component-mismatch/test.js new file mode 100644 index 000000000..ce46d6e7e --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-mismatch/test.js @@ -0,0 +1,16 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + + var children; + + children = component.getEl('root').children; + expect(children.length).to.equal(3); + + component.state.count++; + component.update(); + + children = component.getEl('root').children; + expect(children.length).to.equal(2); +}; diff --git a/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/components/bar/index.marko b/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/components/bar/index.marko new file mode 100644 index 000000000..0da5dadae --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/components/bar/index.marko @@ -0,0 +1,16 @@ +class { + onCreate() { + this.state = { + count: 1 + } + } + + increment() { + this.state.count++; + } +} + + + +
${i}
+ diff --git a/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/components/foo/index.marko b/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/components/foo/index.marko new file mode 100644 index 000000000..5b678b3d0 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/components/foo/index.marko @@ -0,0 +1,3 @@ +class {} + +foo ${component.id} diff --git a/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/index.marko b/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/index.marko new file mode 100644 index 000000000..583b55637 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/index.marko @@ -0,0 +1,12 @@ +class { + incrementBar() { + this.getComponent('bar').increment(); + this.getComponent('bar').update(); + } +} + + + + + + diff --git a/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/test.js b/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/test.js new file mode 100644 index 000000000..ba78313e0 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-component-toplevel-surrounded/test.js @@ -0,0 +1,10 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + + component.incrementBar(); + + var children = component.getEl('root').children; + expect(children[children.length-1].nodeName).to.equal('SPAN'); +}; diff --git a/test/autotests/components-browser/diffpatch-destroy-child/components/hello/index.marko b/test/autotests/components-browser/diffpatch-destroy-child/components/hello/index.marko new file mode 100644 index 000000000..34c5c995f --- /dev/null +++ b/test/autotests/components-browser/diffpatch-destroy-child/components/hello/index.marko @@ -0,0 +1,5 @@ +class { + +} + +Hello${input.count} diff --git a/test/autotests/components-browser/diffpatch-destroy-child/index.marko b/test/autotests/components-browser/diffpatch-destroy-child/index.marko new file mode 100644 index 000000000..0c06259d6 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-destroy-child/index.marko @@ -0,0 +1,15 @@ +class { + onCreate() { + this.state = { + count: 0, + renderHello: true + }; + } +} + + + [ROOT] + + + + diff --git a/test/autotests/components-browser/diffpatch-destroy-child/test.js b/test/autotests/components-browser/diffpatch-destroy-child/test.js new file mode 100644 index 000000000..350d682af --- /dev/null +++ b/test/autotests/components-browser/diffpatch-destroy-child/test.js @@ -0,0 +1,21 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + var rootEl = component.el; + var helloCountEl = rootEl.querySelector('span.hello-count'); + var helloComponent = component.getComponent('hello'); + + component.state.count = 1; + component.update(); + + expect(component.el).to.equal(rootEl); + expect(rootEl.querySelector('span.hello-count').innerHTML).to.equal('1'); + expect(rootEl.querySelector('span.hello-count')).to.equal(helloCountEl); + + component.state.renderHello = false; + component.update(); + + expect(helloComponent.isDestroyed()).to.equal(true); + expect(helloComponent.el == null).to.equal(true); +}; diff --git a/test/autotests/components-browser/diffpatch-insert-el-before-component/components/hello/index.marko b/test/autotests/components-browser/diffpatch-insert-el-before-component/components/hello/index.marko new file mode 100644 index 000000000..285be66ab --- /dev/null +++ b/test/autotests/components-browser/diffpatch-insert-el-before-component/components/hello/index.marko @@ -0,0 +1,5 @@ +class { + +} + +Hello: ${input.count} diff --git a/test/autotests/components-browser/diffpatch-insert-el-before-component/index.marko b/test/autotests/components-browser/diffpatch-insert-el-before-component/index.marko new file mode 100644 index 000000000..2c560f54b --- /dev/null +++ b/test/autotests/components-browser/diffpatch-insert-el-before-component/index.marko @@ -0,0 +1,21 @@ +class { + onCreate() { + this.state = { + insertEl: false, + count: 0 + }; + } +} + + + + + + + New element

+
+ +
+
+ + diff --git a/test/autotests/components-browser/diffpatch-insert-el-before-component/test.js b/test/autotests/components-browser/diffpatch-insert-el-before-component/test.js new file mode 100644 index 000000000..915f2df74 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-insert-el-before-component/test.js @@ -0,0 +1,17 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + // var rootEl = component.el; + var helloComponent = component.getComponent('hello'); + expect(component.getEl('root').querySelector('.hello') != null).to.equal(true); + // expect(helloComponent.el.parentNode).to.equal(rootEl); + + component.state.insertEl = true; + component.state.count++; + component.update(); + + expect(component.getEl('root').querySelector('.hello') != null).to.equal(true); + + expect(component.getComponent('hello')).to.equal(helloComponent); +}; diff --git a/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-component/components/hello/index.marko b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-component/components/hello/index.marko new file mode 100644 index 000000000..285be66ab --- /dev/null +++ b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-component/components/hello/index.marko @@ -0,0 +1,5 @@ +class { + +} + +Hello: ${input.count} diff --git a/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-component/index.marko b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-component/index.marko new file mode 100644 index 000000000..8f94ed243 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-component/index.marko @@ -0,0 +1,19 @@ +class { + onCreate() { + this.state = { + insertEl: false, + count: 0 + }; + } +} + + + + + + + $!{'

'} + +
+ + diff --git a/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-component/test.js b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-component/test.js new file mode 100644 index 000000000..915f2df74 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-component/test.js @@ -0,0 +1,17 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + // var rootEl = component.el; + var helloComponent = component.getComponent('hello'); + expect(component.getEl('root').querySelector('.hello') != null).to.equal(true); + // expect(helloComponent.el.parentNode).to.equal(rootEl); + + component.state.insertEl = true; + component.state.count++; + component.update(); + + expect(component.getEl('root').querySelector('.hello') != null).to.equal(true); + + expect(component.getComponent('hello')).to.equal(helloComponent); +}; diff --git a/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-preserved-component/components/hello/index.marko b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-preserved-component/components/hello/index.marko new file mode 100644 index 000000000..285be66ab --- /dev/null +++ b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-preserved-component/components/hello/index.marko @@ -0,0 +1,5 @@ +class { + +} + +Hello: ${input.count} diff --git a/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-preserved-component/index.marko b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-preserved-component/index.marko new file mode 100644 index 000000000..826e713d9 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-preserved-component/index.marko @@ -0,0 +1,19 @@ +class { + onCreate() { + this.state = { + insertEl: false, + count: 0 + }; + } +} + + + + + + + $!{'

'} + +
+ + diff --git a/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-preserved-component/test.js b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-preserved-component/test.js new file mode 100644 index 000000000..915f2df74 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-insert-unkeyed-el-before-preserved-component/test.js @@ -0,0 +1,17 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + // var rootEl = component.el; + var helloComponent = component.getComponent('hello'); + expect(component.getEl('root').querySelector('.hello') != null).to.equal(true); + // expect(helloComponent.el.parentNode).to.equal(rootEl); + + component.state.insertEl = true; + component.state.count++; + component.update(); + + expect(component.getEl('root').querySelector('.hello') != null).to.equal(true); + + expect(component.getComponent('hello')).to.equal(helloComponent); +}; diff --git a/test/autotests/components-browser/diffpatch-rearrange-keyed-components/components/hello/index.marko b/test/autotests/components-browser/diffpatch-rearrange-keyed-components/components/hello/index.marko new file mode 100644 index 000000000..aab3a0e19 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-rearrange-keyed-components/components/hello/index.marko @@ -0,0 +1,3 @@ +class {} +$ var value = input.value; +
${value}
diff --git a/test/autotests/components-browser/diffpatch-rearrange-keyed-components/index.marko b/test/autotests/components-browser/diffpatch-rearrange-keyed-components/index.marko new file mode 100644 index 000000000..e9eee07ae --- /dev/null +++ b/test/autotests/components-browser/diffpatch-rearrange-keyed-components/index.marko @@ -0,0 +1,9 @@ +class { +} + +
+

Nested components:

+ + + +
diff --git a/test/autotests/components-browser/diffpatch-rearrange-keyed-components/test.js b/test/autotests/components-browser/diffpatch-rearrange-keyed-components/test.js new file mode 100644 index 000000000..c0af89149 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-rearrange-keyed-components/test.js @@ -0,0 +1,96 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), {}); + + var previousComponents = {}; + + function checkOrder(letters) { + component.input = { letters: letters }; + component.update(); + + var divs = component.getEl('root').querySelectorAll('div'); + + expect(divs.length).to.equal(letters.length); + + var newComponents = {}; + + for(var i=0; i +
${letter}
+ diff --git a/test/autotests/components-browser/diffpatch-rearrange-keyed-els/test.js b/test/autotests/components-browser/diffpatch-rearrange-keyed-els/test.js new file mode 100644 index 000000000..ff80815e5 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-rearrange-keyed-els/test.js @@ -0,0 +1,69 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), {}); + expect(helpers.targetEl.querySelectorAll('div').length).to.equal(0); + + function checkOrder(letters) { + component.input = { letters: letters }; + component.update(); + + var divs = helpers.targetEl.querySelectorAll('div'); + + expect(divs.length).to.equal(letters.length); + + for(var i=0; i +

Header

+
Body
+ diff --git a/test/autotests/components-browser/diffpatch-remove-all-els/test.js b/test/autotests/components-browser/diffpatch-remove-all-els/test.js new file mode 100644 index 000000000..617564fc0 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-remove-all-els/test.js @@ -0,0 +1,16 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + + expect(helpers.targetEl.querySelector('h1') != null).to.equal(true); + expect(helpers.targetEl.querySelector('div') != null).to.equal(true); + + component.state.show = false; + component.update(); + + expect(helpers.targetEl.querySelector('h1') == null).to.equal(true); + expect(helpers.targetEl.querySelector('div') == null).to.equal(true); + + expect(component.isDestroyed()).to.equal(false); +}; diff --git a/test/autotests/components-browser/diffpatch-remove-end-el/index.marko b/test/autotests/components-browser/diffpatch-remove-end-el/index.marko new file mode 100644 index 000000000..c8be2bb7c --- /dev/null +++ b/test/autotests/components-browser/diffpatch-remove-end-el/index.marko @@ -0,0 +1,12 @@ +class { + onCreate() { + this.state = { + showFooter: true + }; + } +} + +
Body
+
+ Footer +
diff --git a/test/autotests/components-browser/diffpatch-remove-end-el/test.js b/test/autotests/components-browser/diffpatch-remove-end-el/test.js new file mode 100644 index 000000000..6fca56434 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-remove-end-el/test.js @@ -0,0 +1,14 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + + expect(helpers.targetEl.querySelector('footer') != null).to.equal(true); + expect(helpers.targetEl.querySelector('div') != null).to.equal(true); + + component.state.showFooter = false; + component.update(); + + expect(helpers.targetEl.querySelector('footer') == null).to.equal(true); + expect(helpers.targetEl.querySelector('div') != null).to.equal(true); +}; diff --git a/test/autotests/components-browser/diffpatch-remove-start-el/index.marko b/test/autotests/components-browser/diffpatch-remove-start-el/index.marko new file mode 100644 index 000000000..8eea05059 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-remove-start-el/index.marko @@ -0,0 +1,12 @@ +class { + onCreate() { + this.state = { + showHeader: true + }; + } +} + +

+ Header +

+
Body
diff --git a/test/autotests/components-browser/diffpatch-remove-start-el/test.js b/test/autotests/components-browser/diffpatch-remove-start-el/test.js new file mode 100644 index 000000000..a4c277797 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-remove-start-el/test.js @@ -0,0 +1,14 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + + expect(helpers.targetEl.querySelector('h1') != null).to.equal(true); + expect(helpers.targetEl.querySelector('div') != null).to.equal(true); + + component.state.showHeader = false; + component.update(); + + expect(helpers.targetEl.querySelector('h1') == null).to.equal(true); + expect(helpers.targetEl.querySelector('div') != null).to.equal(true); +}; diff --git a/test/autotests/components-browser/diffpatch-simple/index.marko b/test/autotests/components-browser/diffpatch-simple/index.marko new file mode 100644 index 000000000..44e7a2bdf --- /dev/null +++ b/test/autotests/components-browser/diffpatch-simple/index.marko @@ -0,0 +1,13 @@ +class MyComponent { + onCreate() { + this.state = { + count: 0 + }; + } +} + + + + ${state.count} + + diff --git a/test/autotests/components-browser/diffpatch-simple/test.js b/test/autotests/components-browser/diffpatch-simple/test.js new file mode 100644 index 000000000..a6951610b --- /dev/null +++ b/test/autotests/components-browser/diffpatch-simple/test.js @@ -0,0 +1,14 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + var rootEl = component.el; + var spanEl = rootEl.querySelector('span'); + + component.state.count = 1; + component.update(); + + expect(component.el).to.equal(rootEl); + expect(rootEl.querySelector('span').innerHTML).to.equal('1'); + expect(rootEl.querySelector('span')).to.equal(spanEl); +}; diff --git a/test/autotests/components-browser/diffpatch-swap-components-dynamic/components/hello/index.marko b/test/autotests/components-browser/diffpatch-swap-components-dynamic/components/hello/index.marko new file mode 100644 index 000000000..44a3156d1 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-dynamic/components/hello/index.marko @@ -0,0 +1,5 @@ +class { + +} + +${input.count} diff --git a/test/autotests/components-browser/diffpatch-swap-components-dynamic/components/world/index.marko b/test/autotests/components-browser/diffpatch-swap-components-dynamic/components/world/index.marko new file mode 100644 index 000000000..d72af3219 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-dynamic/components/world/index.marko @@ -0,0 +1,5 @@ +class { + +} + +${input.count} diff --git a/test/autotests/components-browser/diffpatch-swap-components-dynamic/index.marko b/test/autotests/components-browser/diffpatch-swap-components-dynamic/index.marko new file mode 100644 index 000000000..f444872ad --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-dynamic/index.marko @@ -0,0 +1,19 @@ +class { + onCreate() { + this.state = { + swapped: false, + count: 0 + }; + } +} + + + + + + + + + + + diff --git a/test/autotests/components-browser/diffpatch-swap-components-dynamic/test.js b/test/autotests/components-browser/diffpatch-swap-components-dynamic/test.js new file mode 100644 index 000000000..66e5151b8 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-dynamic/test.js @@ -0,0 +1,24 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + var rootEl = component.el; + + var nestedDivs = rootEl.querySelectorAll('div'); + expect(nestedDivs[0].className).to.equal('hello'); + expect(nestedDivs[1].className).to.equal('world'); + expect(nestedDivs[0].innerHTML).to.equal('0'); + expect(nestedDivs[1].innerHTML).to.equal('0'); + + component.state.swapped = true; + component.state.count = 1; + component.update(); + + var nestedDivsAfter = rootEl.querySelectorAll('div'); + expect(nestedDivsAfter[0].className).to.equal('world'); + expect(nestedDivsAfter[1].className).to.equal('hello'); + expect(nestedDivsAfter[0].innerHTML).to.equal('1'); + expect(nestedDivsAfter[1].innerHTML).to.equal('1'); + expect(nestedDivsAfter[0]).to.not.equal(nestedDivs[1]); + expect(nestedDivsAfter[1]).to.not.equal(nestedDivs[0]); +}; diff --git a/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/components/hello/index.marko b/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/components/hello/index.marko new file mode 100644 index 000000000..44a3156d1 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/components/hello/index.marko @@ -0,0 +1,5 @@ +class { + +} + +${input.count} diff --git a/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/components/world/index.marko b/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/components/world/index.marko new file mode 100644 index 000000000..d72af3219 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/components/world/index.marko @@ -0,0 +1,5 @@ +class { + +} + +${input.count} diff --git a/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/index.marko b/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/index.marko new file mode 100644 index 000000000..bb9cda28e --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/index.marko @@ -0,0 +1,19 @@ +class { + onCreate() { + this.state = { + swapped: false, + count: 0 + }; + } +} + + + + + + + + + + + diff --git a/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/test.js b/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/test.js new file mode 100644 index 000000000..0c952b174 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-keyed-dynamic/test.js @@ -0,0 +1,32 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + var rootEl = component.el; + var helloComponent = component.getComponent('hello'); + var worldComponent = component.getComponent('world'); + expect(helloComponent.el.parentNode).to.equal(rootEl); + expect(worldComponent.el.parentNode).to.equal(rootEl); + + var nestedDivs = rootEl.querySelectorAll('div'); + expect(nestedDivs[0].className).to.equal('hello'); + expect(nestedDivs[1].className).to.equal('world'); + expect(nestedDivs[0].innerHTML).to.equal('0'); + expect(nestedDivs[1].innerHTML).to.equal('0'); + + component.state.swapped = true; + component.state.count = 1; + component.update(); + + expect(component.getComponent('hello')).to.equal(helloComponent); + expect(component.getComponent('world')).to.equal(worldComponent); + + var nestedDivsAfter = rootEl.querySelectorAll('div'); + expect(nestedDivsAfter[0].className).to.equal('world'); + expect(nestedDivsAfter[1].className).to.equal('hello'); + expect(nestedDivs[0].innerHTML).to.equal('1'); + expect(nestedDivs[1].innerHTML).to.equal('1'); + + expect(nestedDivsAfter[0]).to.equal(nestedDivs[1]); + expect(nestedDivsAfter[1]).to.equal(nestedDivs[0]); +}; diff --git a/test/autotests/components-browser/diffpatch-swap-components-keyed/components/hello/index.marko b/test/autotests/components-browser/diffpatch-swap-components-keyed/components/hello/index.marko new file mode 100644 index 000000000..8d6867d77 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-keyed/components/hello/index.marko @@ -0,0 +1,5 @@ +class { + +} + +Hello: ${input.count} diff --git a/test/autotests/components-browser/diffpatch-swap-components-keyed/components/world/index.marko b/test/autotests/components-browser/diffpatch-swap-components-keyed/components/world/index.marko new file mode 100644 index 000000000..556f14608 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-keyed/components/world/index.marko @@ -0,0 +1,5 @@ +class { + +} + +World: ${input.count} diff --git a/test/autotests/components-browser/diffpatch-swap-components-keyed/index.marko b/test/autotests/components-browser/diffpatch-swap-components-keyed/index.marko new file mode 100644 index 000000000..5f75fff2e --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-keyed/index.marko @@ -0,0 +1,18 @@ +class { + onCreate() { + this.state = { + swapped: false + }; + } +} + + + + + + + + + + + diff --git a/test/autotests/components-browser/diffpatch-swap-components-keyed/test.js b/test/autotests/components-browser/diffpatch-swap-components-keyed/test.js new file mode 100644 index 000000000..c22e4e10c --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-components-keyed/test.js @@ -0,0 +1,27 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + var rootEl = component.el; + var helloComponent = component.getComponent('hello'); + var worldComponent = component.getComponent('world'); + expect(helloComponent.el.parentNode).to.equal(rootEl); + expect(worldComponent.el.parentNode).to.equal(rootEl); + + var nestedDivs = rootEl.querySelectorAll('div'); + expect(nestedDivs[0].className).to.equal('hello'); + expect(nestedDivs[1].className).to.equal('world'); + + component.state.swapped = true; + component.update(); + + expect(component.getComponent('hello')).to.equal(helloComponent); + expect(component.getComponent('world')).to.equal(worldComponent); + + var nestedDivsAfter = rootEl.querySelectorAll('div'); + expect(nestedDivsAfter[0].className).to.equal('world'); + expect(nestedDivsAfter[1].className).to.equal('hello'); + + expect(nestedDivsAfter[0]).to.equal(nestedDivs[1]); + expect(nestedDivsAfter[1]).to.equal(nestedDivs[0]); +}; diff --git a/test/autotests/components-browser/diffpatch-swap-keyed-el/index.marko b/test/autotests/components-browser/diffpatch-swap-keyed-el/index.marko new file mode 100644 index 000000000..fe6606330 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-keyed-el/index.marko @@ -0,0 +1,18 @@ +class { + onCreate() { + this.state = { + swapped: false + } + } +} + + + + bar + foo + + + foo + bar + + diff --git a/test/autotests/components-browser/diffpatch-swap-keyed-el/test.js b/test/autotests/components-browser/diffpatch-swap-keyed-el/test.js new file mode 100644 index 000000000..82f943243 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-keyed-el/test.js @@ -0,0 +1,18 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + + var fooEl = component.getEl('foo'); + var barEl = component.getEl('bar'); + + expect(fooEl.nextSibling).to.equal(barEl); + + component.state.swapped = true; + component.update(); + + expect(component.getEl('foo')).to.equal(fooEl); + expect(component.getEl('bar')).to.equal(barEl); + + expect(barEl.nextSibling).to.equal(fooEl); +}; diff --git a/test/autotests/components-browser/diffpatch-swap-unkeyed-el/index.marko b/test/autotests/components-browser/diffpatch-swap-unkeyed-el/index.marko new file mode 100644 index 000000000..e89dd1feb --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-unkeyed-el/index.marko @@ -0,0 +1,18 @@ +class { + onCreate() { + this.state = { + swapped: false + } + } +} + + + +
bar
+
foo
+ + +
foo
+
bar
+
+ diff --git a/test/autotests/components-browser/diffpatch-swap-unkeyed-el/test.js b/test/autotests/components-browser/diffpatch-swap-unkeyed-el/test.js new file mode 100644 index 000000000..7b6916948 --- /dev/null +++ b/test/autotests/components-browser/diffpatch-swap-unkeyed-el/test.js @@ -0,0 +1,26 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + var children = component.getEl('root').children; + expect(children.length).to.equal(2); + + expect(children[0].dataset.foo).to.equal('true'); + expect(children[0].dataset.bar).to.equal(undefined); + + expect(children[1].dataset.foo).to.equal(undefined); + expect(children[1].dataset.bar).to.equal('true'); + + component.state.swapped = true; + component.update(); + + children = component.getEl('root').children; + + expect(children.length).to.equal(2); + + expect(children[0].dataset.foo).to.equal(undefined); + expect(children[0].dataset.bar).to.equal('true'); + + expect(children[1].dataset.foo).to.equal('true'); + expect(children[1].dataset.bar).to.equal(undefined); +}; diff --git a/test/autotests/components-browser/event-attach-el/test.js b/test/autotests/components-browser/event-attach-el/test.js index 665f8ce57..25d46323a 100644 --- a/test/autotests/components-browser/event-attach-el/test.js +++ b/test/autotests/components-browser/event-attach-el/test.js @@ -5,7 +5,11 @@ module.exports = function(helpers) { colors: ['red'] }); - expect(component.events.length).to.equal(0); + expect(component.events.length).to.equal(1); + + + expect(component.events[0].color).to.equal('red'); + expect(component.events[0].node).to.equal(component.el.querySelectorAll('li')[0]); component.input = { @@ -14,9 +18,9 @@ module.exports = function(helpers) { component.update(); - expect(component.events.length).to.equal(1); - expect(component.events[0].color).to.equal('blue'); - expect(component.events[0].node).to.equal(component.el.querySelectorAll('li')[1]); + expect(component.events.length).to.equal(2); + expect(component.events[1].color).to.equal('blue'); + expect(component.events[1].node).to.equal(component.el.querySelectorAll('li')[1]); component.input = { colors: ['red', 'green', 'blue'] @@ -24,7 +28,7 @@ module.exports = function(helpers) { component.update(); - expect(component.events.length).to.equal(2); - expect(component.events[1].color).to.equal('green'); - expect(component.events[1].node).to.equal(component.el.querySelectorAll('li')[1]); -}; \ No newline at end of file + expect(component.events.length).to.equal(3); + expect(component.events[2].color).to.equal('green'); + expect(component.events[2].node).to.equal(component.el.querySelectorAll('li')[1]); +}; diff --git a/test/autotests/components-browser/extend-component/test.js b/test/autotests/components-browser/extend-component/test.js index 87fac4731..53c2e9c65 100644 --- a/test/autotests/components-browser/extend-component/test.js +++ b/test/autotests/components-browser/extend-component/test.js @@ -1,17 +1,15 @@ var expect = require('chai').expect; -var markoComponents = require('marko/components'); module.exports = function(helpers) { - var checkboxComponent = helpers.mount(require('./components/app-checkbox'), { + helpers.mount(require('./components/app-checkbox'), { checked: true, 'class': 'my-checkbox', data: 123 }); + expect(helpers.targetEl.children.length).to.equal(1); + expect(helpers.targetEl.children[0].nodeName).to.equal('BUTTON'); + var el = helpers.targetEl.querySelector('.my-checkbox'); expect(el != null).to.equal(true); - - var componentForEl = markoComponents.getComponentForEl(el); - - expect(componentForEl).to.equal(checkboxComponent); -}; \ No newline at end of file +}; diff --git a/test/autotests/components-browser/forceUpdate/index.marko b/test/autotests/components-browser/forceUpdate/index.marko index fc8fce307..cbef375a3 100644 --- a/test/autotests/components-browser/forceUpdate/index.marko +++ b/test/autotests/components-browser/forceUpdate/index.marko @@ -17,4 +17,4 @@ class { } } -
${counter++}
\ No newline at end of file +
${counter++}
diff --git a/test/autotests/components-browser/include-root/index.marko b/test/autotests/components-browser/include-root/index.marko new file mode 100644 index 000000000..1ef76f2e6 --- /dev/null +++ b/test/autotests/components-browser/include-root/index.marko @@ -0,0 +1,13 @@ +class { + onClick() { + this.clicked = true; + } +} + + + <@body> +
  • + +
  • + + diff --git a/test/autotests/components-browser/include-root/modal.marko b/test/autotests/components-browser/include-root/modal.marko new file mode 100644 index 000000000..380096be1 --- /dev/null +++ b/test/autotests/components-browser/include-root/modal.marko @@ -0,0 +1,9 @@ +class { + +} + + diff --git a/test/autotests/components-browser/include-root/test.js b/test/autotests/components-browser/include-root/test.js new file mode 100644 index 000000000..7afdb7e3b --- /dev/null +++ b/test/autotests/components-browser/include-root/test.js @@ -0,0 +1,7 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var component = helpers.mount(require('./index'), { }); + helpers.triggerMouseEvent(component.getEl('button'), 'click'); + expect(component.clicked).to.equal(true); +}; diff --git a/test/autotests/components-browser/label-for-scoped-repeated/index.marko b/test/autotests/components-browser/label-for-scoped-repeated/index.marko new file mode 100644 index 000000000..608aa5f10 --- /dev/null +++ b/test/autotests/components-browser/label-for-scoped-repeated/index.marko @@ -0,0 +1,12 @@ +class { + +} + +
    + +
    + + +
    + +
    diff --git a/test/autotests/components-browser/label-for-scoped-repeated/test.js b/test/autotests/components-browser/label-for-scoped-repeated/test.js new file mode 100644 index 000000000..aca3601b6 --- /dev/null +++ b/test/autotests/components-browser/label-for-scoped-repeated/test.js @@ -0,0 +1,32 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var fields = [ + { + value: 'name', + label: 'Name' + }, + { + value: 'age', + label: 'Age' + } + ]; + + var component = helpers.mount(require('./index'), { + fields: fields + }); + + var inputs = component.getEl('root').querySelectorAll('input'); + var labels = component.getEl('root').querySelectorAll('label'); + + expect(inputs.length).to.equal(fields.length); + + for (var i=0; i + Hello ${input.name}! diff --git a/test/autotests/components-browser/lifecyle-hooks-destroy/index.marko b/test/autotests/components-browser/lifecyle-hooks-destroy/index.marko index d735e05cf..a2076e1e3 100644 --- a/test/autotests/components-browser/lifecyle-hooks-destroy/index.marko +++ b/test/autotests/components-browser/lifecyle-hooks-destroy/index.marko @@ -3,11 +3,13 @@ import { expect } from 'chai'; class { onDestroy(){ - expect(document.getElementById(this.id)).to.equal(this.el); + // The nodes should still be attached + var rootNode = this.getEl('root'); + expect(rootNode.parentNode != null).to.equal(true); hooks.record('root:destroy'); } } -
    +
    diff --git a/test/autotests/components-browser/morphdom-node-added-nested-keyed/test.js b/test/autotests/components-browser/morphdom-node-added-nested-keyed/test.js index 1681d86f1..5b0db4845 100644 --- a/test/autotests/components-browser/morphdom-node-added-nested-keyed/test.js +++ b/test/autotests/components-browser/morphdom-node-added-nested-keyed/test.js @@ -2,13 +2,12 @@ var expect = require('chai').expect; module.exports = function(helpers) { var component = helpers.mount(require('./index'), { }); - var nameInput = component.getEl('nameInput'); + + expect(component.getEl('nameInput').parentNode.nodeName).to.equal('DIV'); component.state.renderCount++; - component.update(); - expect(component.getEl('nameInput')).to.equal(nameInput); - expect(component.getEl('nameInput').value).to.equal('2'); expect(component.getEl('nameInput').parentNode.nodeName).to.equal('P'); + expect(component.getEl('nameInput').value).to.equal('2'); }; diff --git a/test/autotests/components-browser/repeated-with-label-ref/test.js b/test/autotests/components-browser/repeated-with-label-ref/test.js deleted file mode 100644 index 3d524eecb..000000000 --- a/test/autotests/components-browser/repeated-with-label-ref/test.js +++ /dev/null @@ -1,20 +0,0 @@ -var expect = require('chai').expect; - -module.exports = function(helpers) { - var component = helpers.mount(require('./index'), { - fields: [ - { - value: 'name', - label: 'Name' - }, - { - value: 'age', - label: 'Age' - } - ] - }); - - var inputs = component.getEls('field'); - expect(inputs.length).to.equal(2); - expect(inputs[0].value).to.equal('name'); -}; \ No newline at end of file diff --git a/test/autotests/components-browser/rerender-multiple-roots/index.marko b/test/autotests/components-browser/rerender-multiple-roots/index.marko index d11f27edc..cf03f9871 100644 --- a/test/autotests/components-browser/rerender-multiple-roots/index.marko +++ b/test/autotests/components-browser/rerender-multiple-roots/index.marko @@ -4,5 +4,5 @@ class { } } -
    --- in that case - i have error +
    ${state.count}
    +-- [${state.count}] diff --git a/test/autotests/components-browser/rerender-multiple-roots/test.js b/test/autotests/components-browser/rerender-multiple-roots/test.js index a40a16937..bda02db5f 100644 --- a/test/autotests/components-browser/rerender-multiple-roots/test.js +++ b/test/autotests/components-browser/rerender-multiple-roots/test.js @@ -1,5 +1,3 @@ -var expect = require('chai').expect; - // Test for issues #749 #690. Using multiple root nodes or style tag at the root would // cause an infinite loop on rerender. This code does not perform any assertions // but it will get caught in an infinite loop without the changes in PR #751 diff --git a/test/autotests/components-browser/rerender-same-id/index.marko b/test/autotests/components-browser/rerender-same-id/index.marko deleted file mode 100644 index aae6c994d..000000000 --- a/test/autotests/components-browser/rerender-same-id/index.marko +++ /dev/null @@ -1,3 +0,0 @@ -
    - ${input.label} -
    \ No newline at end of file diff --git a/test/autotests/components-browser/rerender-same-id/component.js b/test/autotests/components-browser/rerender-same-root/component.js similarity index 100% rename from test/autotests/components-browser/rerender-same-id/component.js rename to test/autotests/components-browser/rerender-same-root/component.js diff --git a/test/autotests/components-browser/rerender-same-root/index.marko b/test/autotests/components-browser/rerender-same-root/index.marko new file mode 100644 index 000000000..bec7fe120 --- /dev/null +++ b/test/autotests/components-browser/rerender-same-root/index.marko @@ -0,0 +1,3 @@ +
    + ${input.label} +
    diff --git a/test/autotests/components-browser/rerender-same-id/test.js b/test/autotests/components-browser/rerender-same-root/test.js similarity index 70% rename from test/autotests/components-browser/rerender-same-id/test.js rename to test/autotests/components-browser/rerender-same-root/test.js index 8d2c9b598..29c666d6a 100644 --- a/test/autotests/components-browser/rerender-same-id/test.js +++ b/test/autotests/components-browser/rerender-same-root/test.js @@ -5,12 +5,12 @@ module.exports = function(helpers) { label: 'Foo' }); - var oldId = component.id; + var rootEl = component.getEl('root'); component.input = { label: 'Bar' }; component.update(); - expect(component.el.id).to.equal(oldId); -}; \ No newline at end of file + expect(component.getEl('root')).to.equal(rootEl); +}; diff --git a/test/autotests/components-browser/transclusion-include-from-state/components/app-button/index.marko b/test/autotests/components-browser/transclusion-include-from-state/components/app-button/index.marko deleted file mode 100644 index 7c90ae6e2..000000000 --- a/test/autotests/components-browser/transclusion-include-from-state/components/app-button/index.marko +++ /dev/null @@ -1,29 +0,0 @@ -class { - onInput(input) { - this.state = { - size: input.size || 'normal', - variant: input.variant || 'primary', - body: input.label || input.renderBody - }; - } - - // Add any other methods here - setVariant(variant) { - this.state.variant = variant; - } - - setSize(size) { - this.state.size = size; - } - - setLabel(label) { - this.state.label = label; - } -} - -$ var variantClassName=(state.variant !== 'primary' && 'app-button-' + state.variant) -$ var sizeClassName=(state.size !== 'normal' && 'app-button-' + state.size) - - \ No newline at end of file diff --git a/test/autotests/components-browser/transclusion-include-from-state/index.marko b/test/autotests/components-browser/transclusion-include-from-state/index.marko deleted file mode 100644 index 23def10ab..000000000 --- a/test/autotests/components-browser/transclusion-include-from-state/index.marko +++ /dev/null @@ -1,9 +0,0 @@ -class { - -} - -
    - - ${input.name} - -
    \ No newline at end of file diff --git a/test/autotests/components-browser/transclusion-include-from-state/test.js b/test/autotests/components-browser/transclusion-include-from-state/test.js deleted file mode 100644 index bcc5ce2ad..000000000 --- a/test/autotests/components-browser/transclusion-include-from-state/test.js +++ /dev/null @@ -1,31 +0,0 @@ -var expect = require('chai').expect; - -module.exports = function(helpers) { - var component = helpers.mount(require('./index'), { - name: 'Frank' - }); - - var buttonComponent = component.getComponent('button'); - expect(buttonComponent.el.innerHTML).to.contain('Frank'); - expect(buttonComponent.el.className).to.equal('app-button app-button-small'); - - component.input = { name: 'John '}; - component.update(); - - expect(buttonComponent.el.innerHTML).to.contain('John'); - - buttonComponent.setSize('large'); - buttonComponent.update(); - expect(buttonComponent.el.innerHTML).to.contain('John'); - expect(buttonComponent.el.className).to.equal('app-button app-button-large'); - - buttonComponent.input = { - size: 'small', - variant: 'secondary' - // NOTE: We aren't including renderBody() but we expect that content to be preserved - }; - buttonComponent.update(); - - expect(buttonComponent.el.innerHTML).to.contain('John'); - expect(buttonComponent.el.className).to.equal('app-button app-button-secondary app-button-small'); -}; \ No newline at end of file diff --git a/test/autotests/components-browser/widget-include-ref/index.marko b/test/autotests/components-browser/widget-include-ref/index.marko index f31c7b095..a0d8cfbdc 100644 --- a/test/autotests/components-browser/widget-include-ref/index.marko +++ b/test/autotests/components-browser/widget-include-ref/index.marko @@ -2,4 +2,5 @@ import barComponent from './components/app-bar';
    -
    \ No newline at end of file + +
    diff --git a/test/autotests/components-browser/widget-jQuery-proxy/test.js b/test/autotests/components-browser/widget-jQuery-proxy/test.js index cfdf1fe4c..af0665ce7 100644 --- a/test/autotests/components-browser/widget-jQuery-proxy/test.js +++ b/test/autotests/components-browser/widget-jQuery-proxy/test.js @@ -6,7 +6,6 @@ module.exports = function(helpers, done) { try { var component = helpers.mount(require('./index'), {}); - expect(component.$().attr('id')).to.equal(component.id); expect(component.$().attr('class')).to.equal('app-jquery-proxy'); expect(component.$('#foo').html()).to.equal('foo'); expect(component.$('#fooText').html()).to.equal('fooText'); diff --git a/test/autotests/components-browser/widget-rerender-init-order/test.js b/test/autotests/components-browser/widget-rerender-init-order/test.js index 5cc96ec70..eef53d019 100644 --- a/test/autotests/components-browser/widget-rerender-init-order/test.js +++ b/test/autotests/components-browser/widget-rerender-init-order/test.js @@ -7,7 +7,7 @@ module.exports = function(helpers) { version: 0 }); - expect(window.rerenderInitOrder).to.deep.equal(['childA', 'childB', 'parent']); + expect(window.rerenderInitOrder).to.deep.equal(['childB', 'childA', 'parent']); window.rerenderInitOrder = []; @@ -15,7 +15,7 @@ module.exports = function(helpers) { component.update(); // console.log('ACTUAL ORDER: ', window.rerenderInitOrder); - expect(window.rerenderInitOrder).to.deep.equal(['childA', 'childB', 'parent']); + expect(window.rerenderInitOrder).to.deep.equal(['childB', 'childA', 'parent']); delete window.rerenderInitOrder; -}; \ No newline at end of file +}; diff --git a/test/autotests/components-browser/widget-rerender-reuse-stateful/component.js b/test/autotests/components-browser/widget-rerender-reuse-stateful/component.js deleted file mode 100644 index b8e3e8e4e..000000000 --- a/test/autotests/components-browser/widget-rerender-reuse-stateful/component.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - onInput: function(input) { - this.state = { - buttonSize: input.buttonSize || 'normal' - }; - }, - - setButtonSize: function(size) { - this.setState('buttonSize', size); - } -}; \ No newline at end of file diff --git a/test/autotests/components-browser/widget-rerender-reuse-stateful/components/app-stateful-button/component.js b/test/autotests/components-browser/widget-rerender-reuse-stateful/components/app-stateful-button/component.js deleted file mode 100644 index dac980872..000000000 --- a/test/autotests/components-browser/widget-rerender-reuse-stateful/components/app-stateful-button/component.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - onInput: function(input) { - this.state = { - size: input.size || 'normal', - label: input.label || '(no label)' - }; - }, - - setSize: function(newSize) { - this.state.size = newSize; - }, - - setLabel: function(newLabel) { - this.state.label = newLabel; - } -}; \ No newline at end of file diff --git a/test/autotests/components-browser/widget-rerender-reuse-stateful/components/app-stateful-button/index.marko b/test/autotests/components-browser/widget-rerender-reuse-stateful/components/app-stateful-button/index.marko deleted file mode 100644 index f81857540..000000000 --- a/test/autotests/components-browser/widget-rerender-reuse-stateful/components/app-stateful-button/index.marko +++ /dev/null @@ -1,4 +0,0 @@ -
    - ${__filename} - ${state.label} -
    \ No newline at end of file diff --git a/test/autotests/components-browser/widget-rerender-reuse-stateful/components/app-stateful-button/marko-tag.json b/test/autotests/components-browser/widget-rerender-reuse-stateful/components/app-stateful-button/marko-tag.json deleted file mode 100644 index 1937298d5..000000000 --- a/test/autotests/components-browser/widget-rerender-reuse-stateful/components/app-stateful-button/marko-tag.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "attributes": { - "label": "string", - "href": "string", - "variant": { - "type": "string", - "description": "primary | secondary" - }, - "size": { - "type": "string", - "description": "small | normal | large" - }, - "class": { - "type": "string", - "description": "Additional CSS class names" - }, - "*": "string" - } -} \ No newline at end of file diff --git a/test/autotests/components-browser/widget-rerender-reuse-stateful/components/hello/index.marko b/test/autotests/components-browser/widget-rerender-reuse-stateful/components/hello/index.marko new file mode 100644 index 000000000..5482964d8 --- /dev/null +++ b/test/autotests/components-browser/widget-rerender-reuse-stateful/components/hello/index.marko @@ -0,0 +1,13 @@ +class { + onCreate() { + window.helloInstances.push(this); + } + + onInput(input) { + this.state = { + name: input.name + } + } +} + +Hello ${state.name} diff --git a/test/autotests/components-browser/widget-rerender-reuse-stateful/index.marko b/test/autotests/components-browser/widget-rerender-reuse-stateful/index.marko index f9d168d61..582b566a8 100644 --- a/test/autotests/components-browser/widget-rerender-reuse-stateful/index.marko +++ b/test/autotests/components-browser/widget-rerender-reuse-stateful/index.marko @@ -1,4 +1,12 @@ -
    - ${state.buttonSize} - button2 -
    \ No newline at end of file +class { + onCreate() { + this.state = { + count: 0 + }; + } +} + +
    + + +
    diff --git a/test/autotests/components-browser/widget-rerender-reuse-stateful/test.js b/test/autotests/components-browser/widget-rerender-reuse-stateful/test.js index 6ccdf55b2..6a7dcf839 100644 --- a/test/autotests/components-browser/widget-rerender-reuse-stateful/test.js +++ b/test/autotests/components-browser/widget-rerender-reuse-stateful/test.js @@ -1,38 +1,35 @@ var expect = require('chai').expect; module.exports = function(helpers) { - + window.helloInstances = []; var component = helpers.mount(require('./index'), {}); - var oldButton1Component = component.getComponent('button1'); - var oldButton2Component = component.getEl('button2').__component; - var oldButton1El = oldButton1Component.el; - var oldButton2El = component.getEl('button2'); + expect(window.helloInstances.length).to.equal(2); - expect(component.getComponent('button1').el.className).to.contain('normal'); + var helloEls = component.getEl('root').querySelectorAll('.hello'); + expect(helloEls[0].innerHTML).to.equal('Hello Jane'); + expect(helloEls[1].innerHTML).to.equal('Hello John0'); - var self = component; + var hello1 = component.getComponent('hello1'); + var hello2 = component.getComponent('hello2'); - self.setButtonSize('small'); - self.update(); + component.state.count++; + component.update(); - var newButton1El = component.getComponent('button1').el; - var newButton2El = component.getEl('button2'); + // Make sure no more instances of the nested components were created + expect(window.helloInstances.length).to.equal(2); - // // Both button components should be reused - expect(component.getComponent('button1')).to.equal(oldButton1Component); - expect(component.getEl('button2').__component).to.equal(oldButton2Component); + // Make sure the UI components received the new state as part of onInput() + expect(hello1.state.name).to.equal('Jane'); + expect(hello2.state.name).to.equal('John1'); - expect(component.getComponent('button1').el.className).to.contain('small'); + // Make sure the HTML elements were reused + var helloElsAfter = component.getEl('root').querySelectorAll('.hello'); + expect(helloElsAfter[0]).to.equal(helloEls[0]); + expect(helloElsAfter[1]).to.equal(helloEls[1]); - - // // State changed for button1 so it should have a new el - // // since it re-renders to update its view - // console.log('newButton1El: ', newButton1El); - expect(newButton1El === oldButton1El).to.equal(true); - - // - // // State didn't change for button2 so it should be the same el - expect(newButton2El).to.equal(oldButton2El); -}; \ No newline at end of file + // Make sure the DOM was updated + expect(helloElsAfter[0].innerHTML).to.equal('Hello Jane'); + expect(helloElsAfter[1].innerHTML).to.equal('Hello John1'); +}; diff --git a/test/autotests/components-browser/widget-stateful-reuse-widgets/component.js b/test/autotests/components-browser/widget-stateful-reuse-widgets/component.js deleted file mode 100644 index 8d60154ca..000000000 --- a/test/autotests/components-browser/widget-stateful-reuse-widgets/component.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - onInput: function(input) { - this.state = { - buttonSize: input.buttonSize || 'normal' - }; - }, - - setButtonSize: function(size) { - this.setState('buttonSize', size); - }, - onMount: function() { - } -}; \ No newline at end of file diff --git a/test/autotests/components-browser/widget-stateful-reuse-widgets/components/app-stateful-button/component.js b/test/autotests/components-browser/widget-stateful-reuse-widgets/components/app-stateful-button/component.js deleted file mode 100644 index 42ca16331..000000000 --- a/test/autotests/components-browser/widget-stateful-reuse-widgets/components/app-stateful-button/component.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - onInput: function(input) { - this.state = { - size: input.size || 'normal', - label: input.label || '(no label)' - }; - } -}; \ No newline at end of file diff --git a/test/autotests/components-browser/widget-stateful-reuse-widgets/components/app-stateful-button/index.marko b/test/autotests/components-browser/widget-stateful-reuse-widgets/components/app-stateful-button/index.marko deleted file mode 100644 index f81857540..000000000 --- a/test/autotests/components-browser/widget-stateful-reuse-widgets/components/app-stateful-button/index.marko +++ /dev/null @@ -1,4 +0,0 @@ -
    - ${__filename} - ${state.label} -
    \ No newline at end of file diff --git a/test/autotests/components-browser/widget-stateful-reuse-widgets/components/app-stateful-button/marko-tag.json b/test/autotests/components-browser/widget-stateful-reuse-widgets/components/app-stateful-button/marko-tag.json deleted file mode 100644 index 1937298d5..000000000 --- a/test/autotests/components-browser/widget-stateful-reuse-widgets/components/app-stateful-button/marko-tag.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "attributes": { - "label": "string", - "href": "string", - "variant": { - "type": "string", - "description": "primary | secondary" - }, - "size": { - "type": "string", - "description": "small | normal | large" - }, - "class": { - "type": "string", - "description": "Additional CSS class names" - }, - "*": "string" - } -} \ No newline at end of file diff --git a/test/autotests/components-browser/widget-stateful-reuse-widgets/index.marko b/test/autotests/components-browser/widget-stateful-reuse-widgets/index.marko deleted file mode 100644 index f9d168d61..000000000 --- a/test/autotests/components-browser/widget-stateful-reuse-widgets/index.marko +++ /dev/null @@ -1,4 +0,0 @@ -
    - ${state.buttonSize} - button2 -
    \ No newline at end of file diff --git a/test/autotests/components-browser/widget-stateful-reuse-widgets/test.js b/test/autotests/components-browser/widget-stateful-reuse-widgets/test.js deleted file mode 100644 index e3c464e45..000000000 --- a/test/autotests/components-browser/widget-stateful-reuse-widgets/test.js +++ /dev/null @@ -1,36 +0,0 @@ -var expect = require('chai').expect; - -module.exports = function(helpers) { - var component = helpers.mount(require('./index'), {}); - - var oldButton1Component = component.getComponent('button1'); - var oldButton2Component = component.getEl('button2').__component; - var oldButton1El = oldButton1Component.el; - var oldButton2El = component.getEl('button2'); - - expect(component.getComponent('button1').el.className).to.contain('normal'); - - var self = component; - - self.setButtonSize('small'); - self.update(); - - var newButton1El = component.getComponent('button1').el; - var newButton2El = component.getEl('button2'); - - // // Both button components should be reused - expect(component.getComponent('button1')).to.equal(oldButton1Component); - expect(component.getEl('button2').__component).to.equal(oldButton2Component); - - expect(component.getComponent('button1').el.className).to.contain('small'); - - - // // State changed for button1 so it should have a new el - // // since it re-renders to update its view - // console.log('newButton1El: ', newButton1El); - expect(newButton1El === oldButton1El).to.equal(true); - - // - // // State didn't change for button2 so it should be the same el - expect(newButton2El).to.equal(oldButton2El); -}; \ No newline at end of file diff --git a/test/autotests/components-compilation-deprecated/bind-component/expected.js b/test/autotests/components-compilation-deprecated/bind-component/expected.js index 8c28af17b..1dc5efce5 100644 --- a/test/autotests/components-compilation-deprecated/bind-component/expected.js +++ b/test/autotests/components-compilation-deprecated/bind-component/expected.js @@ -8,16 +8,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-deprecated/bind-component/index", function() { return marko_defineWidget_legacy(require("./")); }), - marko_rendererLegacy = legacy_helpers.r, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_rendererLegacy = legacy_helpers.r; -function render(input, out, __component, widget) { +function render(input, out, __component, widget, component) { var data = input; - out.w(""); + out.w("
    "); } marko_template._ = marko_rendererLegacy(render, { diff --git a/test/autotests/components-compilation-deprecated/bind-widget/expected.js b/test/autotests/components-compilation-deprecated/bind-widget/expected.js index 0add5bad9..16fee9562 100644 --- a/test/autotests/components-compilation-deprecated/bind-widget/expected.js +++ b/test/autotests/components-compilation-deprecated/bind-widget/expected.js @@ -8,16 +8,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-deprecated/bind-widget/widget", function() { return marko_defineWidget_legacy(require("./widget")); }), - marko_rendererLegacy = legacy_helpers.r, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_rendererLegacy = legacy_helpers.r; -function render(input, out, __component, widget) { +function render(input, out, __component, widget, component) { var data = input; - out.w(""); + out.w("
    "); } marko_template._ = marko_rendererLegacy(render, { diff --git a/test/autotests/components-compilation-deprecated/component-include-attr/expected.js b/test/autotests/components-compilation-deprecated/component-include-attr/expected.js index 1a11c21fb..be8699cca 100644 --- a/test/autotests/components-compilation-deprecated/component-include-attr/expected.js +++ b/test/autotests/components-compilation-deprecated/component-include-attr/expected.js @@ -9,23 +9,30 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), return marko_defineWidget_legacy(require("./")); }), marko_rendererLegacy = legacy_helpers.r, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), marko_helpers = require("marko/src/runtime/html/helpers"), marko_loadTag = marko_helpers.t, - include_tag = marko_loadTag(require("marko/src/components/taglib/include-tag")), - marko_attr = marko_helpers.a; + include_tag = marko_loadTag(require("marko/src/taglibs/core/include-tag")), + _preserve_tag = marko_loadTag(require("marko/src/components/taglib/preserve-tag")); -function render(input, out, __component, widget) { +function render(input, out, __component, widget, component) { var data = input; - out.w("

    Header

    "); + out.w("

    Header

    "); - include_tag({ - _target: __component.b, - _elId: __component.elId(0) + var __key3 = __component.___nextKey("2"); + + out.w("
    "); + + _preserve_tag({ + bodyOnly: true, + if: !__component.b, + key: __key3, + renderBody: function renderBody(out) { + marko_renderComponent(include_tag, { + _target: __component.b + }, out, "4"); + } }, out); out.w("
    "); @@ -33,8 +40,7 @@ function render(input, out, __component, widget) { marko_template._ = marko_rendererLegacy(render, { split: true, - type: marko_componentType, - body: 0 + type: marko_componentType }); marko_template.meta = { @@ -49,6 +55,7 @@ marko_template.meta = { } ], tags: [ - "marko/src/components/taglib/include-tag" + "marko/src/taglibs/core/include-tag", + "marko/src/components/taglib/preserve-tag" ] }; diff --git a/test/autotests/components-compilation-deprecated/component-template-entry/expected.js b/test/autotests/components-compilation-deprecated/component-template-entry/expected.js index f407a1a04..e83cfb82c 100644 --- a/test/autotests/components-compilation-deprecated/component-template-entry/expected.js +++ b/test/autotests/components-compilation-deprecated/component-template-entry/expected.js @@ -3,31 +3,36 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), components_helpers = require("marko/src/components/helpers"), marko_registerComponent = components_helpers.rc, - legacy_helpers = require("marko/src/components/legacy/helpers"), - marko_defineWidget_legacy = legacy_helpers.w, - marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-deprecated/component-template-entry/component", function() { - return marko_defineWidget_legacy(require("./component")); + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-deprecated/component-template-entry/index.marko", function() { + return module.exports; }), marko_component = require("./component"), - marko_rendererLegacy = legacy_helpers.r, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + legacy_helpers = require("marko/src/components/legacy/helpers"), + marko_defineWidget_legacy = legacy_helpers.w, + marko_componentType2 = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-deprecated/component-template-entry/component", function() { + return marko_defineWidget_legacy(require("./component")); + }), + marko_rendererLegacy = legacy_helpers.r; -function render(input, out, __component, widget) { +function render(input, out, __component, component, state, __component, widget, component) { var data = input; - out.w(""); + out.w("
    "); } marko_template._ = marko_rendererLegacy(render, { split: true, - type: marko_componentType - }, marko_component); + type: marko_componentType2 + }); marko_template.meta = { deps: [ + { + type: "require", + path: "./" + }, { type: "require", path: "./component" diff --git a/test/autotests/components-compilation-deprecated/widget-types/expected.js b/test/autotests/components-compilation-deprecated/widget-types/expected.js index df1ce7369..526558488 100644 --- a/test/autotests/components-compilation-deprecated/widget-types/expected.js +++ b/test/autotests/components-compilation-deprecated/widget-types/expected.js @@ -13,18 +13,14 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), mobile: marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-deprecated/widget-types/component-mobile", function() { return marko_defineWidget_legacy(require("./component-mobile")); }) - }, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + }; -function render(input, out, __component, widget) { +function render(input, out, __component, widget, component) { var data = input; __component.t(marko_componentTypes[data.isMobile ? "default" : "mobile"]); - out.w(""); + out.w("
    "); } marko_template._ = marko_rendererLegacy(render, {}); diff --git a/test/autotests/components-compilation-vdom/boundary-el-if-el/components/my-component/index.marko b/test/autotests/components-compilation-vdom/boundary-el-if-el/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation-vdom/boundary-el-if-el/expected.js b/test/autotests/components-compilation-vdom/boundary-el-if-el/expected.js new file mode 100644 index 000000000..69ba27647 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-el-if-el/expected.js @@ -0,0 +1,51 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-el-if-el/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("441cd5"), + marko_node0 = marko_createElement("H1", null, "0", null, 0, 0, { + i: marko_const_nextId() + }), + marko_node1 = marko_createElement("DIV", null, "2", null, 0, 0, { + i: marko_const_nextId() + }), + marko_node2 = marko_createElement("SPAN", null, "1", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + out.n(marko_node0, component); + + if (input.someCondition) { + out.n(marko_node2, component); + } + + out.n(marko_node1, component); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-el-if-el/index.marko b/test/autotests/components-compilation-vdom/boundary-el-if-el/index.marko new file mode 100644 index 000000000..2cbc93319 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-el-if-el/index.marko @@ -0,0 +1,7 @@ +class {} + +

    + + + +
    diff --git a/test/autotests/components-compilation-vdom/boundary-el-if/expected.js b/test/autotests/components-compilation-vdom/boundary-el-if/expected.js new file mode 100644 index 000000000..ca09539ef --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-el-if/expected.js @@ -0,0 +1,46 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-el-if/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("ee4c02"), + marko_node0 = marko_createElement("H1", null, "0", null, 0, 0, { + i: marko_const_nextId() + }), + marko_node1 = marko_createElement("SPAN", null, "1", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + out.n(marko_node0, component); + + if (input.someCondition) { + out.n(marko_node1, component); + } +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-el-if/index.marko b/test/autotests/components-compilation-vdom/boundary-el-if/index.marko new file mode 100644 index 000000000..cd6729875 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-el-if/index.marko @@ -0,0 +1,6 @@ +class {} + +

    + + + diff --git a/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/components/test-no-output/marko-tag.json b/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/components/test-no-output/marko-tag.json new file mode 100644 index 000000000..1dc5f764d --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/components/test-no-output/marko-tag.json @@ -0,0 +1,4 @@ +{ + "renderer": "./renderer", + "noOutput": true +} \ No newline at end of file diff --git a/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/components/test-no-output/renderer.js b/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/components/test-no-output/renderer.js new file mode 100644 index 000000000..2d87648d8 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/components/test-no-output/renderer.js @@ -0,0 +1,3 @@ +module.exports = function(input, out) { + +}; \ No newline at end of file diff --git a/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/expected.js b/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/expected.js new file mode 100644 index 000000000..7b806c3a3 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/expected.js @@ -0,0 +1,46 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-el-no-output-tag/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_loadTag = marko_helpers.t, + test_no_output_tag = marko_loadTag(require("./components/test-no-output/renderer")), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("4529ef"), + marko_node0 = marko_createElement("DIV", null, "0", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + out.n(marko_node0, component); + + test_no_output_tag({}, out); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/test-no-output/renderer" + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/index.marko b/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/index.marko new file mode 100644 index 000000000..2dee9522a --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-el-no-output-tag/index.marko @@ -0,0 +1,4 @@ +class {} + +
    + diff --git a/test/autotests/components-compilation-vdom/boundary-html-tag/expected.js b/test/autotests/components-compilation-vdom/boundary-html-tag/expected.js new file mode 100644 index 000000000..2251795e8 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-html-tag/expected.js @@ -0,0 +1,71 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-html-tag/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_loadTag = marko_helpers.t, + component_globals_tag = marko_loadTag(require("marko/src/components/taglib/component-globals-tag")), + init_components_tag = marko_loadTag(require("marko/src/components/taglib/init-components-tag")), + await_reorderer_tag = marko_loadTag(require("marko/src/taglibs/async/await-reorderer-tag")), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("5b1bc3"), + marko_node0 = marko_createElement("HEAD", null, "1", null, 1, 0, { + i: marko_const_nextId() + }) + .e("TITLE", null, "2", null, 1) + .t("Hello"), + marko_node1 = marko_createElement("H1", null, "4", null, 1, 0, { + i: marko_const_nextId() + }) + .t("Hello"); + +function render(input, out, __component, component, state) { + var data = input; + + out.be("HTML", null, "0", component); + + out.n(marko_node0, component); + + out.be("BODY", null, "3", component); + + component_globals_tag({}, out); + + out.n(marko_node1, component); + + init_components_tag({}, out); + + marko_renderComponent(await_reorderer_tag, {}, out, "5"); + + out.ee(); + + out.ee(); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "marko/src/components/taglib/component-globals-tag", + "marko/src/components/taglib/init-components-tag", + "marko/src/taglibs/async/await-reorderer-tag" + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-html-tag/index.marko b/test/autotests/components-compilation-vdom/boundary-html-tag/index.marko new file mode 100644 index 000000000..f2353b0c6 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-html-tag/index.marko @@ -0,0 +1,9 @@ +class {} + + + Hello + + +

    Hello

    + + diff --git a/test/autotests/components-compilation-vdom/boundary-if-el/expected.js b/test/autotests/components-compilation-vdom/boundary-if-el/expected.js new file mode 100644 index 000000000..0ff64302f --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-if-el/expected.js @@ -0,0 +1,46 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-if-el/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("5854ef"), + marko_node0 = marko_createElement("H1", null, "1", null, 0, 0, { + i: marko_const_nextId() + }), + marko_node1 = marko_createElement("SPAN", null, "0", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + if (input.someCondition) { + out.n(marko_node1, component); + } + + out.n(marko_node0, component); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-if-el/index.marko b/test/autotests/components-compilation-vdom/boundary-if-el/index.marko new file mode 100644 index 000000000..a47f7c3e9 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-if-el/index.marko @@ -0,0 +1,6 @@ +class {} + + + + +

    diff --git a/test/autotests/components-compilation-vdom/boundary-if-root/components/my-component/index.marko b/test/autotests/components-compilation-vdom/boundary-if-root/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation-vdom/boundary-if-root/expected.js b/test/autotests/components-compilation-vdom/boundary-if-root/expected.js new file mode 100644 index 000000000..ab8c6ed96 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-if-root/expected.js @@ -0,0 +1,41 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-if-root/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("0ec49e"), + marko_node0 = marko_createElement("DIV", null, "0", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + if (input.someCondition) { + out.n(marko_node0, component); + } +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-if-root/index.marko b/test/autotests/components-compilation-vdom/boundary-if-root/index.marko new file mode 100644 index 000000000..1f11313dc --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-if-root/index.marko @@ -0,0 +1,5 @@ +class {} + + +
    + diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-custom-tag-no-key/components/my-component/index.marko b/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-custom-tag-no-key/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-custom-tag-no-key/expected.js b/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-custom-tag-no-key/expected.js new file mode 100644 index 000000000..7afe5ff3e --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-custom-tag-no-key/expected.js @@ -0,0 +1,46 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-multi-root-html-el-custom-tag-no-key/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"), + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), + my_component_template = marko_loadTemplate(require.resolve("./components/my-component")), + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_loadTag = marko_helpers.t, + my_component_tag = marko_loadTag(my_component_template); + +function render(input, out, __component, component, state) { + var data = input; + + out.e("H1", { + "data-marko-key": marko_keyAttr(input.myStartKey, __component) + }, input.myStartKey, component, 0); + + marko_renderComponent(my_component_tag, {}, out, "0"); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/my-component" + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-custom-tag-no-key/index.marko b/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-custom-tag-no-key/index.marko new file mode 100644 index 000000000..76eda8c84 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-custom-tag-no-key/index.marko @@ -0,0 +1,3 @@ +class {} +

    + diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-id-custom-tag-key/components/my-component/index.marko b/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-id-custom-tag-key/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-id-custom-tag-key/expected.js b/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-id-custom-tag-key/expected.js new file mode 100644 index 000000000..9c6525237 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-id-custom-tag-key/expected.js @@ -0,0 +1,51 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-multi-root-html-el-id-custom-tag-key/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), + my_component_template = marko_loadTemplate(require.resolve("./components/my-component")), + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_loadTag = marko_helpers.t, + my_component_tag = marko_loadTag(my_component_template), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("0a6612"), + marko_node0 = marko_createElement("H1", { + id: "myStart" + }, "0", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + out.n(marko_node0, component); + + marko_renderComponent(my_component_tag, {}, out, "myEnd"); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/my-component" + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-id-custom-tag-key/index.marko b/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-id-custom-tag-key/index.marko new file mode 100644 index 000000000..561428614 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-el-id-custom-tag-key/index.marko @@ -0,0 +1,3 @@ +class {} +

    + diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-dynamic/expected.js b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-dynamic/expected.js new file mode 100644 index 000000000..fa9938877 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-dynamic/expected.js @@ -0,0 +1,38 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-dynamic/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c; + +function render(input, out, __component, component, state) { + var data = input; + + out.e("H1", { + id: input.myStart + }, "0", component, 0, 4); + + out.e("DIV", { + id: input.myEnd + }, "1", component, 0, 4); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-dynamic/index.marko b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-dynamic/index.marko new file mode 100644 index 000000000..b74e6c740 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-dynamic/index.marko @@ -0,0 +1,3 @@ +class {} +

    +
    diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-static/expected.js b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-static/expected.js new file mode 100644 index 000000000..f2ba087b8 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-static/expected.js @@ -0,0 +1,48 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-static/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("522184"), + marko_node0 = marko_createElement("H1", { + id: "myStart" + }, "0", null, 0, 0, { + i: marko_const_nextId() + }), + marko_node1 = marko_createElement("DIV", { + id: "myEnd" + }, "1", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + out.n(marko_node0, component); + + out.n(marko_node1, component); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-static/index.marko b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-static/index.marko new file mode 100644 index 000000000..367ef9bf1 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-ids-static/index.marko @@ -0,0 +1,3 @@ +class {} +

    +
    diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys-dynamic/expected.js b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys-dynamic/expected.js new file mode 100644 index 000000000..d2d99283e --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys-dynamic/expected.js @@ -0,0 +1,39 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys-dynamic/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"); + +function render(input, out, __component, component, state) { + var data = input; + + out.e("H1", { + "data-marko-key": marko_keyAttr(input.myStartKey, __component) + }, input.myStartKey, component, 0); + + out.e("DIV", { + "data-marko-key": marko_keyAttr(input.myEndKey, __component) + }, input.myEndKey, component, 0); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys-dynamic/index.marko b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys-dynamic/index.marko new file mode 100644 index 000000000..f8cbf1aa4 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys-dynamic/index.marko @@ -0,0 +1,3 @@ +class {} +

    +
    diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys/expected.js b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys/expected.js new file mode 100644 index 000000000..ef64c3c0b --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys/expected.js @@ -0,0 +1,39 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"); + +function render(input, out, __component, component, state) { + var data = input; + + out.e("H1", { + "data-marko-key": marko_keyAttr("myStart", __component) + }, "myStart", component, 0); + + out.e("DIV", { + "data-marko-key": marko_keyAttr("myEnd", __component) + }, "myEnd", component, 0); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys/index.marko b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys/index.marko new file mode 100644 index 000000000..5d0ef6f89 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els-keys/index.marko @@ -0,0 +1,3 @@ +class {} +

    +
    diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-els/expected.js b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els/expected.js new file mode 100644 index 000000000..308b01291 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els/expected.js @@ -0,0 +1,44 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-multi-root-html-els/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("75995e"), + marko_node0 = marko_createElement("H1", null, "0", null, 0, 0, { + i: marko_const_nextId() + }), + marko_node1 = marko_createElement("DIV", null, "1", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + out.n(marko_node0, component); + + out.n(marko_node1, component); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-multi-root-html-els/index.marko b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els/index.marko new file mode 100644 index 000000000..f5c4381dc --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-multi-root-html-els/index.marko @@ -0,0 +1,3 @@ +class {} +

    +
    diff --git a/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/components/test-no-output/marko-tag.json b/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/components/test-no-output/marko-tag.json new file mode 100644 index 000000000..1dc5f764d --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/components/test-no-output/marko-tag.json @@ -0,0 +1,4 @@ +{ + "renderer": "./renderer", + "noOutput": true +} \ No newline at end of file diff --git a/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/components/test-no-output/renderer.js b/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/components/test-no-output/renderer.js new file mode 100644 index 000000000..2d87648d8 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/components/test-no-output/renderer.js @@ -0,0 +1,3 @@ +module.exports = function(input, out) { + +}; \ No newline at end of file diff --git a/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/expected.js b/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/expected.js new file mode 100644 index 000000000..c7b5f335d --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/expected.js @@ -0,0 +1,46 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-no-output-tag-el/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_loadTag = marko_helpers.t, + test_no_output_tag = marko_loadTag(require("./components/test-no-output/renderer")), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("de2191"), + marko_node0 = marko_createElement("DIV", null, "0", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + test_no_output_tag({}, out); + + out.n(marko_node0, component); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/test-no-output/renderer" + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/index.marko b/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/index.marko new file mode 100644 index 000000000..8422ced40 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-no-output-tag-el/index.marko @@ -0,0 +1,4 @@ +class {} + + +
    diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-key/components/my-component/index.marko b/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-key/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-key/expected.js b/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-key/expected.js new file mode 100644 index 000000000..47ddb198d --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-key/expected.js @@ -0,0 +1,41 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-single-root-custom-tag-key/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), + my_component_template = marko_loadTemplate(require.resolve("./components/my-component")), + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_loadTag = marko_helpers.t, + my_component_tag = marko_loadTag(my_component_template); + +function render(input, out, __component, component, state) { + var data = input; + + marko_renderComponent(my_component_tag, {}, out, "myComponent"); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/my-component" + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-key/index.marko b/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-key/index.marko new file mode 100644 index 000000000..f1039c183 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-key/index.marko @@ -0,0 +1,2 @@ +class {} + diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-no-key/components/my-component/index.marko b/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-no-key/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-no-key/expected.js b/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-no-key/expected.js new file mode 100644 index 000000000..41db618ea --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-no-key/expected.js @@ -0,0 +1,41 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-single-root-custom-tag-no-key/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), + my_component_template = marko_loadTemplate(require.resolve("./components/my-component")), + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_loadTag = marko_helpers.t, + my_component_tag = marko_loadTag(my_component_template); + +function render(input, out, __component, component, state) { + var data = input; + + marko_renderComponent(my_component_tag, {}, out, "0"); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/my-component" + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-no-key/index.marko b/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-no-key/index.marko new file mode 100644 index 000000000..390b9d091 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-single-root-custom-tag-no-key/index.marko @@ -0,0 +1,2 @@ +class {} + diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-html-el-dynamic-id/expected.js b/test/autotests/components-compilation-vdom/boundary-single-root-html-el-dynamic-id/expected.js new file mode 100644 index 000000000..a34902edd --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-single-root-html-el-dynamic-id/expected.js @@ -0,0 +1,34 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-single-root-html-el-dynamic-id/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c; + +function render(input, out, __component, component, state) { + var data = input; + + out.e("DIV", { + id: input.id + }, "0", component, 0, 4); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-html-el-dynamic-id/index.marko b/test/autotests/components-compilation-vdom/boundary-single-root-html-el-dynamic-id/index.marko new file mode 100644 index 000000000..2afd29d56 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-single-root-html-el-dynamic-id/index.marko @@ -0,0 +1,2 @@ +class {} +
    diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-html-el-static-id/expected.js b/test/autotests/components-compilation-vdom/boundary-single-root-html-el-static-id/expected.js new file mode 100644 index 000000000..251cdb462 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-single-root-html-el-static-id/expected.js @@ -0,0 +1,41 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-single-root-html-el-static-id/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("f2c765"), + marko_node0 = marko_createElement("DIV", { + id: "foo" + }, "0", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + out.n(marko_node0, component); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-html-el-static-id/index.marko b/test/autotests/components-compilation-vdom/boundary-single-root-html-el-static-id/index.marko new file mode 100644 index 000000000..2ac73e3b6 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-single-root-html-el-static-id/index.marko @@ -0,0 +1,2 @@ +class {} +
    diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-html-el/expected.js b/test/autotests/components-compilation-vdom/boundary-single-root-html-el/expected.js new file mode 100644 index 000000000..e796f9bf8 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-single-root-html-el/expected.js @@ -0,0 +1,39 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/boundary-single-root-html-el/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/vdom/helpers"), + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("d3d7a8"), + marko_node0 = marko_createElement("DIV", null, "0", null, 0, 0, { + i: marko_const_nextId() + }); + +function render(input, out, __component, component, state) { + var data = input; + + out.n(marko_node0, component); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/boundary-single-root-html-el/index.marko b/test/autotests/components-compilation-vdom/boundary-single-root-html-el/index.marko new file mode 100644 index 000000000..f1b4025c0 --- /dev/null +++ b/test/autotests/components-compilation-vdom/boundary-single-root-html-el/index.marko @@ -0,0 +1,2 @@ +class {} +
    diff --git a/test/autotests/components-compilation-vdom/component-with-import-static/expected.js b/test/autotests/components-compilation-vdom/component-with-import-static/expected.js new file mode 100644 index 000000000..bd097a31a --- /dev/null +++ b/test/autotests/components-compilation-vdom/component-with-import-static/expected.js @@ -0,0 +1,38 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/vdom").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation-vdom/component-with-import-static/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + module_chai_module = require("chai"), + chai_module = module_chai_module.default || module_chai_module, + expect = module_chai_module.expect; + +var counter = 0; + +function render(input, out, __component, component, state) { + var data = input; + + out.e("DIV", null, "0", component, 1) + .t(counter++); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation-vdom/component-with-import-static/index.marko b/test/autotests/components-compilation-vdom/component-with-import-static/index.marko new file mode 100644 index 000000000..9f17c2513 --- /dev/null +++ b/test/autotests/components-compilation-vdom/component-with-import-static/index.marko @@ -0,0 +1,8 @@ +import { expect } from 'chai'; + +static var counter = 0; + +class { +} + +
    ${counter++}
    diff --git a/test/autotests/components-compilation/auto-key-els-renderBody/component.js b/test/autotests/components-compilation/auto-key-els-renderBody/component.js new file mode 100644 index 000000000..a09954537 --- /dev/null +++ b/test/autotests/components-compilation/auto-key-els-renderBody/component.js @@ -0,0 +1 @@ +module.exports = {}; \ No newline at end of file diff --git a/test/autotests/components-compilation/auto-key-els-renderBody/components/another-component/index.marko b/test/autotests/components-compilation/auto-key-els-renderBody/components/another-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation/auto-key-els-renderBody/expected.js b/test/autotests/components-compilation/auto-key-els-renderBody/expected.js new file mode 100644 index 000000000..4aa8d16ee --- /dev/null +++ b/test/autotests/components-compilation/auto-key-els-renderBody/expected.js @@ -0,0 +1,53 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/auto-key-els-renderBody/index.marko", function() { + return module.exports; + }), + marko_component = require("./component"), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"), + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_attr = marko_helpers.a, + marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), + another_component_template = marko_loadTemplate(require.resolve("./components/another-component")), + marko_loadTag = marko_helpers.t, + another_component_tag = marko_loadTag(another_component_template); + +function render(input, out, __component, component, state) { + var data = input; + + out.w("
    A"); + + marko_renderComponent(another_component_tag, { + renderBody: function renderBody(out) { + out.w("
    This is static
    "); + } + }, out, "1"); + + out.w("
    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/another-component" + ] + }; diff --git a/test/autotests/components-compilation/auto-key-els-renderBody/index.marko b/test/autotests/components-compilation/auto-key-els-renderBody/index.marko new file mode 100644 index 000000000..88e7b646b --- /dev/null +++ b/test/autotests/components-compilation/auto-key-els-renderBody/index.marko @@ -0,0 +1,9 @@ +
    + A + + +
    + This is static +
    +
    +
    diff --git a/test/autotests/components-compilation/auto-key-els/component.js b/test/autotests/components-compilation/auto-key-els/component.js new file mode 100644 index 000000000..a09954537 --- /dev/null +++ b/test/autotests/components-compilation/auto-key-els/component.js @@ -0,0 +1 @@ +module.exports = {}; \ No newline at end of file diff --git a/test/autotests/components-compilation/auto-key-els/expected.js b/test/autotests/components-compilation/auto-key-els/expected.js new file mode 100644 index 000000000..fbd808eac --- /dev/null +++ b/test/autotests/components-compilation/auto-key-els/expected.js @@ -0,0 +1,78 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/auto-key-els/index.marko", function() { + return module.exports; + }), + marko_component = require("./component"), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"), + marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), + foo_template = marko_loadTemplate(require.resolve("./foo.marko")), + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_attr = marko_helpers.a, + marko_forEach = marko_helpers.f, + marko_escapeXml = marko_helpers.x, + marko_loadTag = marko_helpers.t, + _preserve_tag = marko_loadTag(require("marko/src/components/taglib/preserve-tag")), + include_tag = marko_loadTag(require("marko/src/taglibs/core/include-tag")); + +function render(input, out, __component, component, state) { + var data = input; + + out.w("
    A
      "); + + marko_forEach(colors, function(color) { + out.w("
    • " + + marko_escapeXml(color) + + "
    • "); + }); + + out.w("
    "); + + var __key3 = __component.___nextKey("preservedP"); + + out.w(""); + + _preserve_tag({ + bodyOnly: true, + key: __key3, + renderBody: function renderBody(out) { + out.w(marko_escapeXml(Date.now())); + } + }, out); + + out.w("

    B"); + + marko_renderComponent(include_tag, { + _target: foo_template + }, out, "5"); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./foo.marko", + "marko/src/components/taglib/preserve-tag", + "marko/src/taglibs/core/include-tag" + ] + }; diff --git a/test/autotests/components-compilation/auto-key-els/foo.marko b/test/autotests/components-compilation/auto-key-els/foo.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation/auto-key-els/index.marko b/test/autotests/components-compilation/auto-key-els/index.marko new file mode 100644 index 000000000..c929933b1 --- /dev/null +++ b/test/autotests/components-compilation/auto-key-els/index.marko @@ -0,0 +1,11 @@ +
    + A +
      + +
    • ${color}
    • + +
    +

    ${Date.now()}

    +
    +B + diff --git a/test/autotests/components-compilation/bind-component/expected.js b/test/autotests/components-compilation/bind-component/expected.js index ad32939ce..7c5dc9c7b 100644 --- a/test/autotests/components-compilation/bind-component/expected.js +++ b/test/autotests/components-compilation/bind-component/expected.js @@ -8,16 +8,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), }), marko_component = require("./component"), marko_renderer = components_helpers.r, - marko_defineComponent = components_helpers.c, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_defineComponent = components_helpers.c; function render(input, out, __component, component, state) { var data = input; - out.w("
    "); + out.w("
    "); } marko_template._ = marko_renderer(render, { diff --git a/test/autotests/components-compilation/bind-widget/expected.js b/test/autotests/components-compilation/bind-widget/expected.js index a5bcc8b24..19f16a51e 100644 --- a/test/autotests/components-compilation/bind-widget/expected.js +++ b/test/autotests/components-compilation/bind-widget/expected.js @@ -8,16 +8,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), }), marko_component = require("./component"), marko_renderer = components_helpers.r, - marko_defineComponent = components_helpers.c, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_defineComponent = components_helpers.c; function render(input, out, __component, component, state) { var data = input; - out.w("
    "); + out.w("
    "); } marko_template._ = marko_renderer(render, { diff --git a/test/autotests/components-compilation/boundary-el-if-el/components/my-component/index.marko b/test/autotests/components-compilation/boundary-el-if-el/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation/boundary-el-if-el/expected.js b/test/autotests/components-compilation/boundary-el-if-el/expected.js new file mode 100644 index 000000000..5af227c50 --- /dev/null +++ b/test/autotests/components-compilation/boundary-el-if-el/expected.js @@ -0,0 +1,38 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-el-if-el/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c; + +function render(input, out, __component, component, state) { + var data = input; + + out.w("

    "); + + if (input.someCondition) { + out.w(""); + } + + out.w("
    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-el-if-el/index.marko b/test/autotests/components-compilation/boundary-el-if-el/index.marko new file mode 100644 index 000000000..2cbc93319 --- /dev/null +++ b/test/autotests/components-compilation/boundary-el-if-el/index.marko @@ -0,0 +1,7 @@ +class {} + +

    + + + +
    diff --git a/test/autotests/components-compilation/boundary-el-if/components/my-component/index.marko b/test/autotests/components-compilation/boundary-el-if/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation/boundary-el-if/expected.js b/test/autotests/components-compilation/boundary-el-if/expected.js new file mode 100644 index 000000000..cf7e1703f --- /dev/null +++ b/test/autotests/components-compilation/boundary-el-if/expected.js @@ -0,0 +1,36 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-el-if/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c; + +function render(input, out, __component, component, state) { + var data = input; + + out.w("

    "); + + if (input.someCondition) { + out.w(""); + } +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-el-if/index.marko b/test/autotests/components-compilation/boundary-el-if/index.marko new file mode 100644 index 000000000..cd6729875 --- /dev/null +++ b/test/autotests/components-compilation/boundary-el-if/index.marko @@ -0,0 +1,6 @@ +class {} + +

    + + + diff --git a/test/autotests/components-compilation/boundary-el-no-output-tag/components/test-no-output/marko-tag.json b/test/autotests/components-compilation/boundary-el-no-output-tag/components/test-no-output/marko-tag.json new file mode 100644 index 000000000..1dc5f764d --- /dev/null +++ b/test/autotests/components-compilation/boundary-el-no-output-tag/components/test-no-output/marko-tag.json @@ -0,0 +1,4 @@ +{ + "renderer": "./renderer", + "noOutput": true +} \ No newline at end of file diff --git a/test/autotests/components-compilation/boundary-el-no-output-tag/components/test-no-output/renderer.js b/test/autotests/components-compilation/boundary-el-no-output-tag/components/test-no-output/renderer.js new file mode 100644 index 000000000..2d87648d8 --- /dev/null +++ b/test/autotests/components-compilation/boundary-el-no-output-tag/components/test-no-output/renderer.js @@ -0,0 +1,3 @@ +module.exports = function(input, out) { + +}; \ No newline at end of file diff --git a/test/autotests/components-compilation/boundary-el-no-output-tag/expected.js b/test/autotests/components-compilation/boundary-el-no-output-tag/expected.js new file mode 100644 index 000000000..4427b1114 --- /dev/null +++ b/test/autotests/components-compilation/boundary-el-no-output-tag/expected.js @@ -0,0 +1,40 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-el-no-output-tag/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_loadTag = marko_helpers.t, + test_no_output_tag = marko_loadTag(require("./components/test-no-output/renderer")); + +function render(input, out, __component, component, state) { + var data = input; + + out.w("
    "); + + test_no_output_tag({}, out); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/test-no-output/renderer" + ] + }; diff --git a/test/autotests/components-compilation/boundary-el-no-output-tag/index.marko b/test/autotests/components-compilation/boundary-el-no-output-tag/index.marko new file mode 100644 index 000000000..2dee9522a --- /dev/null +++ b/test/autotests/components-compilation/boundary-el-no-output-tag/index.marko @@ -0,0 +1,4 @@ +class {} + +
    + diff --git a/test/autotests/components-compilation/boundary-if-root/components/my-component/index.marko b/test/autotests/components-compilation/boundary-if-root/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation/boundary-if-root/expected.js b/test/autotests/components-compilation/boundary-if-root/expected.js new file mode 100644 index 000000000..46ed7fd99 --- /dev/null +++ b/test/autotests/components-compilation/boundary-if-root/expected.js @@ -0,0 +1,34 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-if-root/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c; + +function render(input, out, __component, component, state) { + var data = input; + + if (input.someCondition) { + out.w("
    "); + } +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-if-root/index.marko b/test/autotests/components-compilation/boundary-if-root/index.marko new file mode 100644 index 000000000..1f11313dc --- /dev/null +++ b/test/autotests/components-compilation/boundary-if-root/index.marko @@ -0,0 +1,5 @@ +class {} + + +
    + diff --git a/test/autotests/components-compilation/boundary-multi-root-html-el-custom-tag-no-key/components/my-component/index.marko b/test/autotests/components-compilation/boundary-multi-root-html-el-custom-tag-no-key/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation/boundary-multi-root-html-el-custom-tag-no-key/expected.js b/test/autotests/components-compilation/boundary-multi-root-html-el-custom-tag-no-key/expected.js new file mode 100644 index 000000000..4ce9df59d --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-el-custom-tag-no-key/expected.js @@ -0,0 +1,47 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-multi-root-html-el-custom-tag-no-key/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"), + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_attr = marko_helpers.a, + marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), + my_component_template = marko_loadTemplate(require.resolve("./components/my-component")), + marko_loadTag = marko_helpers.t, + my_component_tag = marko_loadTag(my_component_template); + +function render(input, out, __component, component, state) { + var data = input; + + out.w("

    "); + + marko_renderComponent(my_component_tag, {}, out, "0"); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/my-component" + ] + }; diff --git a/test/autotests/components-compilation/boundary-multi-root-html-el-custom-tag-no-key/index.marko b/test/autotests/components-compilation/boundary-multi-root-html-el-custom-tag-no-key/index.marko new file mode 100644 index 000000000..76eda8c84 --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-el-custom-tag-no-key/index.marko @@ -0,0 +1,3 @@ +class {} +

    + diff --git a/test/autotests/components-compilation/boundary-multi-root-html-el-id-custom-tag-key/components/my-component/index.marko b/test/autotests/components-compilation/boundary-multi-root-html-el-id-custom-tag-key/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation/boundary-multi-root-html-el-id-custom-tag-key/expected.js b/test/autotests/components-compilation/boundary-multi-root-html-el-id-custom-tag-key/expected.js new file mode 100644 index 000000000..ece96c6ba --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-el-id-custom-tag-key/expected.js @@ -0,0 +1,43 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-multi-root-html-el-id-custom-tag-key/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), + my_component_template = marko_loadTemplate(require.resolve("./components/my-component")), + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_loadTag = marko_helpers.t, + my_component_tag = marko_loadTag(my_component_template); + +function render(input, out, __component, component, state) { + var data = input; + + out.w("

    "); + + marko_renderComponent(my_component_tag, {}, out, "myEnd"); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/my-component" + ] + }; diff --git a/test/autotests/components-compilation/boundary-multi-root-html-el-id-custom-tag-key/index.marko b/test/autotests/components-compilation/boundary-multi-root-html-el-id-custom-tag-key/index.marko new file mode 100644 index 000000000..561428614 --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-el-id-custom-tag-key/index.marko @@ -0,0 +1,3 @@ +class {} +

    + diff --git a/test/autotests/components-compilation/boundary-multi-root-html-els-ids-dynamic/expected.js b/test/autotests/components-compilation/boundary-multi-root-html-els-ids-dynamic/expected.js new file mode 100644 index 000000000..5e3e92350 --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-els-ids-dynamic/expected.js @@ -0,0 +1,38 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-multi-root-html-els-ids-dynamic/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_attr = marko_helpers.a; + +function render(input, out, __component, component, state) { + var data = input; + + out.w("

    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-multi-root-html-els-ids-dynamic/index.marko b/test/autotests/components-compilation/boundary-multi-root-html-els-ids-dynamic/index.marko new file mode 100644 index 000000000..b74e6c740 --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-els-ids-dynamic/index.marko @@ -0,0 +1,3 @@ +class {} +

    +
    diff --git a/test/autotests/components-compilation/boundary-multi-root-html-els-ids-static/expected.js b/test/autotests/components-compilation/boundary-multi-root-html-els-ids-static/expected.js new file mode 100644 index 000000000..a4861a5d9 --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-els-ids-static/expected.js @@ -0,0 +1,32 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-multi-root-html-els-ids-static/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c; + +function render(input, out, __component, component, state) { + var data = input; + + out.w("

    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-multi-root-html-els-ids-static/index.marko b/test/autotests/components-compilation/boundary-multi-root-html-els-ids-static/index.marko new file mode 100644 index 000000000..367ef9bf1 --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-els-ids-static/index.marko @@ -0,0 +1,3 @@ +class {} +

    +
    diff --git a/test/autotests/components-compilation/boundary-multi-root-html-els-keys-dynamic/expected.js b/test/autotests/components-compilation/boundary-multi-root-html-els-keys-dynamic/expected.js new file mode 100644 index 000000000..0c59580ea --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-els-keys-dynamic/expected.js @@ -0,0 +1,39 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-multi-root-html-els-keys-dynamic/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"), + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_attr = marko_helpers.a; + +function render(input, out, __component, component, state) { + var data = input; + + out.w("

    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-multi-root-html-els-keys-dynamic/index.marko b/test/autotests/components-compilation/boundary-multi-root-html-els-keys-dynamic/index.marko new file mode 100644 index 000000000..f8cbf1aa4 --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-els-keys-dynamic/index.marko @@ -0,0 +1,3 @@ +class {} +

    +
    diff --git a/test/autotests/components-compilation/boundary-multi-root-html-els-keys/expected.js b/test/autotests/components-compilation/boundary-multi-root-html-els-keys/expected.js new file mode 100644 index 000000000..389724008 --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-els-keys/expected.js @@ -0,0 +1,39 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-multi-root-html-els-keys/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"), + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_attr = marko_helpers.a; + +function render(input, out, __component, component, state) { + var data = input; + + out.w("

    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-multi-root-html-els-keys/index.marko b/test/autotests/components-compilation/boundary-multi-root-html-els-keys/index.marko new file mode 100644 index 000000000..5d0ef6f89 --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-els-keys/index.marko @@ -0,0 +1,3 @@ +class {} +

    +
    diff --git a/test/autotests/components-compilation/boundary-multi-root-html-els/expected.js b/test/autotests/components-compilation/boundary-multi-root-html-els/expected.js new file mode 100644 index 000000000..e68e4b915 --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-els/expected.js @@ -0,0 +1,32 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-multi-root-html-els/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c; + +function render(input, out, __component, component, state) { + var data = input; + + out.w("

    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-multi-root-html-els/index.marko b/test/autotests/components-compilation/boundary-multi-root-html-els/index.marko new file mode 100644 index 000000000..f5c4381dc --- /dev/null +++ b/test/autotests/components-compilation/boundary-multi-root-html-els/index.marko @@ -0,0 +1,3 @@ +class {} +

    +
    diff --git a/test/autotests/components-compilation/boundary-no-output-tag-el/components/test-no-output/marko-tag.json b/test/autotests/components-compilation/boundary-no-output-tag-el/components/test-no-output/marko-tag.json new file mode 100644 index 000000000..1dc5f764d --- /dev/null +++ b/test/autotests/components-compilation/boundary-no-output-tag-el/components/test-no-output/marko-tag.json @@ -0,0 +1,4 @@ +{ + "renderer": "./renderer", + "noOutput": true +} \ No newline at end of file diff --git a/test/autotests/components-compilation/boundary-no-output-tag-el/components/test-no-output/renderer.js b/test/autotests/components-compilation/boundary-no-output-tag-el/components/test-no-output/renderer.js new file mode 100644 index 000000000..2d87648d8 --- /dev/null +++ b/test/autotests/components-compilation/boundary-no-output-tag-el/components/test-no-output/renderer.js @@ -0,0 +1,3 @@ +module.exports = function(input, out) { + +}; \ No newline at end of file diff --git a/test/autotests/components-compilation/boundary-no-output-tag-el/expected.js b/test/autotests/components-compilation/boundary-no-output-tag-el/expected.js new file mode 100644 index 000000000..f609353de --- /dev/null +++ b/test/autotests/components-compilation/boundary-no-output-tag-el/expected.js @@ -0,0 +1,40 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-no-output-tag-el/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_loadTag = marko_helpers.t, + test_no_output_tag = marko_loadTag(require("./components/test-no-output/renderer")); + +function render(input, out, __component, component, state) { + var data = input; + + test_no_output_tag({}, out); + + out.w("
    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/test-no-output/renderer" + ] + }; diff --git a/test/autotests/components-compilation/boundary-no-output-tag-el/index.marko b/test/autotests/components-compilation/boundary-no-output-tag-el/index.marko new file mode 100644 index 000000000..8422ced40 --- /dev/null +++ b/test/autotests/components-compilation/boundary-no-output-tag-el/index.marko @@ -0,0 +1,4 @@ +class {} + + +
    diff --git a/test/autotests/components-compilation/boundary-single-root-custom-tag-key/components/my-component/index.marko b/test/autotests/components-compilation/boundary-single-root-custom-tag-key/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation/boundary-single-root-custom-tag-key/expected.js b/test/autotests/components-compilation/boundary-single-root-custom-tag-key/expected.js new file mode 100644 index 000000000..563941481 --- /dev/null +++ b/test/autotests/components-compilation/boundary-single-root-custom-tag-key/expected.js @@ -0,0 +1,41 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-single-root-custom-tag-key/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), + my_component_template = marko_loadTemplate(require.resolve("./components/my-component")), + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_loadTag = marko_helpers.t, + my_component_tag = marko_loadTag(my_component_template); + +function render(input, out, __component, component, state) { + var data = input; + + marko_renderComponent(my_component_tag, {}, out, "myComponent"); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/my-component" + ] + }; diff --git a/test/autotests/components-compilation/boundary-single-root-custom-tag-key/index.marko b/test/autotests/components-compilation/boundary-single-root-custom-tag-key/index.marko new file mode 100644 index 000000000..f1039c183 --- /dev/null +++ b/test/autotests/components-compilation/boundary-single-root-custom-tag-key/index.marko @@ -0,0 +1,2 @@ +class {} + diff --git a/test/autotests/components-compilation/boundary-single-root-custom-tag-no-key/components/my-component/index.marko b/test/autotests/components-compilation/boundary-single-root-custom-tag-no-key/components/my-component/index.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/components-compilation/boundary-single-root-custom-tag-no-key/expected.js b/test/autotests/components-compilation/boundary-single-root-custom-tag-no-key/expected.js new file mode 100644 index 000000000..381d1fb7a --- /dev/null +++ b/test/autotests/components-compilation/boundary-single-root-custom-tag-no-key/expected.js @@ -0,0 +1,41 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-single-root-custom-tag-no-key/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), + my_component_template = marko_loadTemplate(require.resolve("./components/my-component")), + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_loadTag = marko_helpers.t, + my_component_tag = marko_loadTag(my_component_template); + +function render(input, out, __component, component, state) { + var data = input; + + marko_renderComponent(my_component_tag, {}, out, "0"); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ], + tags: [ + "./components/my-component" + ] + }; diff --git a/test/autotests/components-compilation/boundary-single-root-custom-tag-no-key/index.marko b/test/autotests/components-compilation/boundary-single-root-custom-tag-no-key/index.marko new file mode 100644 index 000000000..390b9d091 --- /dev/null +++ b/test/autotests/components-compilation/boundary-single-root-custom-tag-no-key/index.marko @@ -0,0 +1,2 @@ +class {} + diff --git a/test/autotests/components-compilation/boundary-single-root-html-el-dynamic-id/expected.js b/test/autotests/components-compilation/boundary-single-root-html-el-dynamic-id/expected.js new file mode 100644 index 000000000..f0a43eebb --- /dev/null +++ b/test/autotests/components-compilation/boundary-single-root-html-el-dynamic-id/expected.js @@ -0,0 +1,36 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-single-root-html-el-dynamic-id/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_attr = marko_helpers.a; + +function render(input, out, __component, component, state) { + var data = input; + + out.w("
    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-single-root-html-el-dynamic-id/index.marko b/test/autotests/components-compilation/boundary-single-root-html-el-dynamic-id/index.marko new file mode 100644 index 000000000..2afd29d56 --- /dev/null +++ b/test/autotests/components-compilation/boundary-single-root-html-el-dynamic-id/index.marko @@ -0,0 +1,2 @@ +class {} +
    diff --git a/test/autotests/components-compilation/boundary-single-root-html-el-static-id/expected.js b/test/autotests/components-compilation/boundary-single-root-html-el-static-id/expected.js new file mode 100644 index 000000000..104dd1e27 --- /dev/null +++ b/test/autotests/components-compilation/boundary-single-root-html-el-static-id/expected.js @@ -0,0 +1,32 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-single-root-html-el-static-id/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c; + +function render(input, out, __component, component, state) { + var data = input; + + out.w("
    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-single-root-html-el-static-id/index.marko b/test/autotests/components-compilation/boundary-single-root-html-el-static-id/index.marko new file mode 100644 index 000000000..2ac73e3b6 --- /dev/null +++ b/test/autotests/components-compilation/boundary-single-root-html-el-static-id/index.marko @@ -0,0 +1,2 @@ +class {} +
    diff --git a/test/autotests/components-compilation/boundary-single-root-html-el/expected.js b/test/autotests/components-compilation/boundary-single-root-html-el/expected.js new file mode 100644 index 000000000..0105925f7 --- /dev/null +++ b/test/autotests/components-compilation/boundary-single-root-html-el/expected.js @@ -0,0 +1,32 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/boundary-single-root-html-el/index.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c; + +function render(input, out, __component, component, state) { + var data = input; + + out.w("
    "); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./" + } + ] + }; diff --git a/test/autotests/components-compilation/boundary-single-root-html-el/index.marko b/test/autotests/components-compilation/boundary-single-root-html-el/index.marko new file mode 100644 index 000000000..f1b4025c0 --- /dev/null +++ b/test/autotests/components-compilation/boundary-single-root-html-el/index.marko @@ -0,0 +1,2 @@ +class {} +
    diff --git a/test/autotests/components-compilation/child-tag-no-output-multiple-roots/expected.js b/test/autotests/components-compilation/child-tag-no-output-multiple-roots/expected.js index 9cc4bbd96..787aed713 100644 --- a/test/autotests/components-compilation/child-tag-no-output-multiple-roots/expected.js +++ b/test/autotests/components-compilation/child-tag-no-output-multiple-roots/expected.js @@ -12,31 +12,22 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), marko_helpers = require("marko/src/runtime/html/helpers"), marko_loadTag = marko_helpers.t, test_no_output_tag = marko_loadTag(require("./components/test-no-output/renderer")), - marko_escapeXml = marko_helpers.x, - marko_attr = marko_helpers.a; + marko_escapeXml = marko_helpers.x; function render(input, out, __component, component, state) { var data = input; test_no_output_tag({}, out); - out.w("" + + out.w("
    " + marko_escapeXml(input.name) + - "
    " + + "
    " + marko_escapeXml(input.address) + "
    "); } marko_template._ = marko_renderer(render, { - type: marko_componentType, - roots: [ - "_r0", - "_r1" - ] + type: marko_componentType }, marko_component); marko_template.Component = marko_defineComponent(marko_component, marko_template._); diff --git a/test/autotests/components-compilation/child-tag-no-output/expected.js b/test/autotests/components-compilation/child-tag-no-output/expected.js index 0bdb133f1..050993339 100644 --- a/test/autotests/components-compilation/child-tag-no-output/expected.js +++ b/test/autotests/components-compilation/child-tag-no-output/expected.js @@ -12,17 +12,14 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), marko_helpers = require("marko/src/runtime/html/helpers"), marko_loadTag = marko_helpers.t, test_no_output_tag = marko_loadTag(require("./components/test-no-output/renderer")), - marko_escapeXml = marko_helpers.x, - marko_attr = marko_helpers.a; + marko_escapeXml = marko_helpers.x; function render(input, out, __component, component, state) { var data = input; test_no_output_tag({}, out); - out.w("" + + out.w("
    " + marko_escapeXml(input.name) + "
    "); } diff --git a/test/autotests/components-compilation/class-method-empty-return/expected.js b/test/autotests/components-compilation/class-method-empty-return/expected.js index d8c444a6c..1d53553f8 100644 --- a/test/autotests/components-compilation/class-method-empty-return/expected.js +++ b/test/autotests/components-compilation/class-method-empty-return/expected.js @@ -12,16 +12,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), return module.exports; }), marko_renderer = components_helpers.r, - marko_defineComponent = components_helpers.c, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_defineComponent = components_helpers.c; function render(input, out, __component, component, state) { var data = input; - out.w("
    "); + out.w("
    "); } marko_template._ = marko_renderer(render, { diff --git a/test/autotests/components-compilation/component-include-attr/expected.js b/test/autotests/components-compilation/component-include-attr/expected.js index 10192650c..d853d0acc 100644 --- a/test/autotests/components-compilation/component-include-attr/expected.js +++ b/test/autotests/components-compilation/component-include-attr/expected.js @@ -9,28 +9,19 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), marko_component = require("./component"), marko_renderer = components_helpers.r, marko_defineComponent = components_helpers.c, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), marko_helpers = require("marko/src/runtime/html/helpers"), marko_loadTag = marko_helpers.t, - include_tag = marko_loadTag(require("marko/src/components/taglib/include-tag")), - marko_attr = marko_helpers.a; + include_tag = marko_loadTag(require("marko/src/taglibs/core/include-tag")); function render(input, out, __component, component, state) { var data = input; - out.w("

    Header

    "); + out.w("

    Header

    "); - var __componentId1 = __component.elId("0[]"); - - out.w(""); - - include_tag({ - _target: data.renderBody, - _elId: __componentId1 - }, out); + marko_renderComponent(include_tag, { + _target: data.renderBody + }, out, "3"); out.w("
    "); } @@ -49,6 +40,6 @@ marko_template.meta = { } ], tags: [ - "marko/src/components/taglib/include-tag" + "marko/src/taglibs/core/include-tag" ] }; diff --git a/test/autotests/components-compilation/component-inline-class/expected.js b/test/autotests/components-compilation/component-inline-class/expected.js index aff285842..93ba60146 100644 --- a/test/autotests/components-compilation/component-inline-class/expected.js +++ b/test/autotests/components-compilation/component-inline-class/expected.js @@ -11,16 +11,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), return module.exports; }), marko_renderer = components_helpers.r, - marko_defineComponent = components_helpers.c, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_defineComponent = components_helpers.c; function render(input, out, __component, component, state) { var data = input; - out.w("
    "); + out.w("
    "); } marko_template._ = marko_renderer(render, { diff --git a/test/autotests/components-compilation/component-inline-multiple-roots/expected.js b/test/autotests/components-compilation/component-inline-multiple-roots/expected.js index bd8508338..632074a3a 100644 --- a/test/autotests/components-compilation/component-inline-multiple-roots/expected.js +++ b/test/autotests/components-compilation/component-inline-multiple-roots/expected.js @@ -8,26 +8,16 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), return module.exports; }), marko_renderer = components_helpers.r, - marko_defineComponent = components_helpers.c, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_defineComponent = components_helpers.c; function render(input, out, __component, component, state) { var data = input; - out.w("A
    B"); + out.w("
    A
    B"); } marko_template._ = marko_renderer(render, { - type: marko_componentType, - roots: [ - "_r0", - "_r1" - ] + type: marko_componentType }, marko_component); marko_template.Component = marko_defineComponent(marko_component, marko_template._); diff --git a/test/autotests/components-compilation/component-template-entry-split/expected.js b/test/autotests/components-compilation/component-template-entry-split/expected.js index c69d786ae..2e25164fb 100644 --- a/test/autotests/components-compilation/component-template-entry-split/expected.js +++ b/test/autotests/components-compilation/component-template-entry-split/expected.js @@ -7,16 +7,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), return require("./component-browser"); }), marko_component = require("./component"), - marko_renderer = components_helpers.r, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_renderer = components_helpers.r; function render(input, out, __component, component, state) { var data = input; - out.w("
    "); + out.w("
    "); } marko_template._ = marko_renderer(render, { diff --git a/test/autotests/components-compilation/component-template-entry/expected.js b/test/autotests/components-compilation/component-template-entry/expected.js index bc65650ae..a8a537021 100644 --- a/test/autotests/components-compilation/component-template-entry/expected.js +++ b/test/autotests/components-compilation/component-template-entry/expected.js @@ -8,16 +8,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), }), marko_component = require("./component"), marko_renderer = components_helpers.r, - marko_defineComponent = components_helpers.c, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_defineComponent = components_helpers.c; function render(input, out, __component, component, state) { var data = input; - out.w("

    "); + out.w("
    "); } marko_template._ = marko_renderer(render, { diff --git a/test/autotests/components-compilation/component-template-non-index/expected.js b/test/autotests/components-compilation/component-template-non-index/expected.js index fd694770f..7720b83ba 100644 --- a/test/autotests/components-compilation/component-template-non-index/expected.js +++ b/test/autotests/components-compilation/component-template-non-index/expected.js @@ -8,16 +8,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), }), marko_component = require("./template.component"), marko_renderer = components_helpers.r, - marko_defineComponent = components_helpers.c, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_defineComponent = components_helpers.c; function render(input, out, __component, component, state) { var data = input; - out.w("

    "); + out.w("
    "); } marko_template._ = marko_renderer(render, { diff --git a/test/autotests/components-compilation/include-input-whitespace-preserved/expected.js b/test/autotests/components-compilation/include-input-whitespace-preserved/expected.js index 9308239e0..cd91d7dc4 100644 --- a/test/autotests/components-compilation/include-input-whitespace-preserved/expected.js +++ b/test/autotests/components-compilation/include-input-whitespace-preserved/expected.js @@ -9,29 +9,24 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), }), marko_renderer = components_helpers.r, marko_defineComponent = components_helpers.c, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), marko_helpers = require("marko/src/runtime/html/helpers"), marko_loadTag = marko_helpers.t, - include_tag = marko_loadTag(require("marko/src/components/taglib/include-tag")), - marko_attr = marko_helpers.a; + include_tag = marko_loadTag(require("marko/src/taglibs/core/include-tag")); function render(input, out, __component, component, state) { var data = input; - var __componentId0 = __component.id; + out.w("
    \n "); - out.w(""); - - include_tag({ + marko_renderComponent(include_tag, { _target: data.renderBody, _arg: { test: 1 - }, - _elId: __componentId0 - }, out); + } + }, out, "1"); - out.w("
    "); + out.w("\n
    "); } marko_template._ = marko_renderer(render, { @@ -48,6 +43,6 @@ marko_template.meta = { } ], tags: [ - "marko/src/components/taglib/include-tag" + "marko/src/taglibs/core/include-tag" ] }; diff --git a/test/autotests/components-compilation/include-whitespace-preserved/expected.js b/test/autotests/components-compilation/include-whitespace-preserved/expected.js index 99b0a431b..d6745139c 100644 --- a/test/autotests/components-compilation/include-whitespace-preserved/expected.js +++ b/test/autotests/components-compilation/include-whitespace-preserved/expected.js @@ -9,26 +9,21 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), }), marko_renderer = components_helpers.r, marko_defineComponent = components_helpers.c, + marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), marko_helpers = require("marko/src/runtime/html/helpers"), marko_loadTag = marko_helpers.t, - include_tag = marko_loadTag(require("marko/src/components/taglib/include-tag")), - marko_attr = marko_helpers.a; + include_tag = marko_loadTag(require("marko/src/taglibs/core/include-tag")); function render(input, out, __component, component, state) { var data = input; - var __componentId0 = __component.id; + out.w("
    \n "); - out.w(""); + marko_renderComponent(include_tag, { + _target: data.renderBody + }, out, "1"); - include_tag({ - _target: data.renderBody, - _elId: __componentId0 - }, out); - - out.w("
    "); + out.w("\n

    "); } marko_template._ = marko_renderer(render, { @@ -45,6 +40,6 @@ marko_template.meta = { } ], tags: [ - "marko/src/components/taglib/include-tag" + "marko/src/taglibs/core/include-tag" ] }; diff --git a/test/autotests/components-compilation/index-widget-only/expected.js b/test/autotests/components-compilation/index-widget-only/expected.js index 6fc179394..13f18721b 100644 --- a/test/autotests/components-compilation/index-widget-only/expected.js +++ b/test/autotests/components-compilation/index-widget-only/expected.js @@ -6,16 +6,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/index-widget-only/component-browser", function() { return require("./component-browser"); }), - marko_renderer = components_helpers.r, - marko_helpers = require("marko/src/runtime/html/helpers"), - marko_attr = marko_helpers.a; + marko_renderer = components_helpers.r; function render(input, out, __component, component, state) { var data = input; - out.w("

    "); + out.w("
    "); } marko_template._ = marko_renderer(render, { diff --git a/test/autotests/components-compilation/key-colon-attr/expected.js b/test/autotests/components-compilation/key-colon-attr/expected.js index d604ef550..8b06d08a8 100644 --- a/test/autotests/components-compilation/key-colon-attr/expected.js +++ b/test/autotests/components-compilation/key-colon-attr/expected.js @@ -11,16 +11,16 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), }), marko_renderer = components_helpers.r, marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"), marko_helpers = require("marko/src/runtime/html/helpers"), marko_attr = marko_helpers.a; function render(input, out, __component, component, state) { var data = input; - out.w("
    "); } diff --git a/test/autotests/components-compilation/key-suffix-with-deprecated-attr-error/test.js b/test/autotests/components-compilation/key-suffix-with-deprecated-attr-error/test.js index 81c41ac7c..fe8de168d 100644 --- a/test/autotests/components-compilation/key-suffix-with-deprecated-attr-error/test.js +++ b/test/autotests/components-compilation/key-suffix-with-deprecated-attr-error/test.js @@ -1,5 +1,5 @@ const expect = require('chai').expect; exports.checkError = function(err) { - expect(err.toString()).to.contain('The "for-key" tag cannot be used with "for:key".'); + expect(err.toString()).to.contain('The "for-key" attribute cannot be used in conjunction with "for:key"'); }; diff --git a/test/autotests/components-compilation/key-suffix-with-unfixed-attr-error/test.js b/test/autotests/components-compilation/key-suffix-with-unfixed-attr-error/test.js index 1297d10b2..f04f36a65 100644 --- a/test/autotests/components-compilation/key-suffix-with-unfixed-attr-error/test.js +++ b/test/autotests/components-compilation/key-suffix-with-unfixed-attr-error/test.js @@ -1,5 +1,5 @@ const expect = require('chai').expect; exports.checkError = function(err) { - expect(err.toString()).to.contain('The "for:key" attribute cannot be used in conjuction with the "for" attribute.'); + expect(err.toString()).to.contain('The "for:key" attribute cannot be used in conjunction with the "for" attribute'); }; diff --git a/test/autotests/components-compilation/key-suffix/expected.js b/test/autotests/components-compilation/key-suffix/expected.js index 6dfea2275..b4c17f6ed 100644 --- a/test/autotests/components-compilation/key-suffix/expected.js +++ b/test/autotests/components-compilation/key-suffix/expected.js @@ -11,18 +11,23 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), }), marko_renderer = components_helpers.r, marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"), marko_helpers = require("marko/src/runtime/html/helpers"), marko_attr = marko_helpers.a; function render(input, out, __component, component, state) { var data = input; - out.w("
    "); + + var marko_for_key1 = "name"; + + out.w("Name
    "); } diff --git a/test/autotests/components-compilation/key/expected.js b/test/autotests/components-compilation/key/expected.js index d76189be5..bfe8030fd 100644 --- a/test/autotests/components-compilation/key/expected.js +++ b/test/autotests/components-compilation/key/expected.js @@ -12,6 +12,7 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), marko_renderer = components_helpers.r, marko_defineComponent = components_helpers.c, marko_renderComponent = require("marko/src/components/taglib/helpers/renderComponent"), + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"), marko_loadTemplate = require("marko/src/runtime/helper-loadTemplate"), app_foo_template = marko_loadTemplate(require.resolve("./components/app-foo")), marko_helpers = require("marko/src/runtime/html/helpers"), @@ -22,17 +23,12 @@ var marko_template = module.exports = require("marko/src/html").t(__filename), function render(input, out, __component, component, state) { var data = input; - out.w("
    "); + out.w("
    "); - marko_renderComponent(app_foo_tag, {}, out, [ - __component, - "foo" - ]); + marko_renderComponent(app_foo_tag, {}, out, "foo"); out.w("eBay
    "); } diff --git a/test/autotests/components-compilation/label-for/expected.js b/test/autotests/components-compilation/label-for/expected.js new file mode 100644 index 000000000..1995c4b9a --- /dev/null +++ b/test/autotests/components-compilation/label-for/expected.js @@ -0,0 +1,47 @@ +"use strict"; + +var marko_template = module.exports = require("marko/src/html").t(__filename), + marko_component = {}, + components_helpers = require("marko/src/components/helpers"), + marko_registerComponent = components_helpers.rc, + marko_componentType = marko_registerComponent("/marko-test$1.0.0/autotests/components-compilation/label-for/template.marko", function() { + return module.exports; + }), + marko_renderer = components_helpers.r, + marko_defineComponent = components_helpers.c, + marko_keyAttr = require("marko/src/components/taglib/helpers/markoKeyAttr"), + marko_helpers = require("marko/src/runtime/html/helpers"), + marko_attr = marko_helpers.a; + +function render(input, out, __component, component, state) { + var data = input; + + var marko_for_key0 = "submitButton"; + + out.w("Submit"); + + var marko_id_key1 = "submitButton"; + + out.w("Submit"); +} + +marko_template._ = marko_renderer(render, { + type: marko_componentType + }, marko_component); + +marko_template.Component = marko_defineComponent(marko_component, marko_template._); + +marko_template.meta = { + deps: [ + { + type: "require", + path: "./template.marko" + } + ] + }; diff --git a/test/autotests/components-compilation/label-for/template.marko b/test/autotests/components-compilation/label-for/template.marko new file mode 100644 index 000000000..b860f84d2 --- /dev/null +++ b/test/autotests/components-compilation/label-for/template.marko @@ -0,0 +1,3 @@ +class {} + + diff --git a/test/autotests/components-compilation/macro-widget/expected.js b/test/autotests/components-compilation/macro-widget/expected.js index 5b0fb7c4c..aac3add72 100644 --- a/test/autotests/components-compilation/macro-widget/expected.js +++ b/test/autotests/components-compilation/macro-widget/expected.js @@ -29,9 +29,7 @@ function render(input, out, __component, component, state) { ""); } - out.w(""); + out.w("
    "); marko_forEach([ "red", diff --git a/test/autotests/components-pages/diff-body-root/template.marko b/test/autotests/components-pages/diff-body-root/template.marko index f9f693712..a0484f3bb 100644 --- a/test/autotests/components-pages/diff-body-root/template.marko +++ b/test/autotests/components-pages/diff-body-root/template.marko @@ -6,6 +6,9 @@ class { count: 0 } } + onInput() { + this.input = {}; + } onMount () { window.app = this; } diff --git a/test/autotests/components-pages/diff-body/template.marko b/test/autotests/components-pages/diff-body/template.marko index 29d78fdfa..7e41de415 100644 --- a/test/autotests/components-pages/diff-body/template.marko +++ b/test/autotests/components-pages/diff-body/template.marko @@ -6,6 +6,9 @@ class { count: 0 } } + onInput() { + this.input = {}; + } onMount () { window.app = this; } @@ -15,7 +18,7 @@ class { } -html lang="en" +html lang="en" head meta charset="UTF-8" title -- Marko Test @@ -25,7 +28,7 @@ html lang="en" div id="test" div id="mocha" div id="testsTarget" - div key="count" -- ${state.count} + div.count key="count" -- ${state.count} lasso-body diff --git a/test/autotests/components-pages/diff-html-include-layout/layout.marko b/test/autotests/components-pages/diff-html-include-layout/layout.marko new file mode 100644 index 000000000..9be923c21 --- /dev/null +++ b/test/autotests/components-pages/diff-html-include-layout/layout.marko @@ -0,0 +1,21 @@ + +html lang="en" + head + meta charset="UTF-8" + title -- Marko Test + lasso-head + body + + div id="test" + div id="mocha" + div id="testsTarget" + + + + lasso-body + + init-components immediate + + lasso-slot name="mocha-run" + + browser-refresh diff --git a/test/autotests/components-pages/diff-html-include-layout/template.marko b/test/autotests/components-pages/diff-html-include-layout/template.marko new file mode 100644 index 000000000..263a4fe3b --- /dev/null +++ b/test/autotests/components-pages/diff-html-include-layout/template.marko @@ -0,0 +1,21 @@ +class { + onCreate () { + this.state = { + count: 0 + } + } + onMount () { + window.app = this; + } + increment () { + this.state.count++; + } +} + + + + + <@body> + ${state.count} + + diff --git a/test/autotests/components-pages/diff-html-include-layout/tests.js b/test/autotests/components-pages/diff-html-include-layout/tests.js new file mode 100644 index 000000000..27672a842 --- /dev/null +++ b/test/autotests/components-pages/diff-html-include-layout/tests.js @@ -0,0 +1,14 @@ +var path = require('path'); +var expect = require('chai').expect; + +describe(path.basename(__dirname), function() { + it('should allow diffing html', function() { + var app = window.app; + expect(document.body.querySelector('span.count').innerHTML).to.equal('0'); + + app.increment(); + app.update(); + + expect(document.body.querySelector('span.count').innerHTML).to.equal('1'); + }); +}); diff --git a/test/autotests/components-pages/getEl-no-rerender/components/hello/index.marko b/test/autotests/components-pages/getEl-no-rerender/components/hello/index.marko new file mode 100644 index 000000000..2784ed636 --- /dev/null +++ b/test/autotests/components-pages/getEl-no-rerender/components/hello/index.marko @@ -0,0 +1,10 @@ +class { + onMount() { + window.hello = this; + } +}; + + + + +
    diff --git a/test/autotests/components-browser/widget-stateful-reuse-widgets/marko.json b/test/autotests/components-pages/getEl-no-rerender/marko.json similarity index 100% rename from test/autotests/components-browser/widget-stateful-reuse-widgets/marko.json rename to test/autotests/components-pages/getEl-no-rerender/marko.json diff --git a/test/autotests/components-pages/getEl-no-rerender/template.marko b/test/autotests/components-pages/getEl-no-rerender/template.marko new file mode 100644 index 000000000..91e956f5b --- /dev/null +++ b/test/autotests/components-pages/getEl-no-rerender/template.marko @@ -0,0 +1,25 @@ +lasso-page dependencies=data.browserDependencies lasso=data.lasso + + +html lang="en" + head + meta charset="UTF-8" + title -- Marko Components Tests + lasso-head + body + + div id="test" + div id="mocha" + div id="testsTarget" + + + This will prevent the UI component from re-rendering + + + lasso-body + + init-components immediate + + lasso-slot name="mocha-run" + + browser-refresh diff --git a/test/autotests/components-pages/getEl-no-rerender/tests.js b/test/autotests/components-pages/getEl-no-rerender/tests.js new file mode 100644 index 000000000..4cbddbee9 --- /dev/null +++ b/test/autotests/components-pages/getEl-no-rerender/tests.js @@ -0,0 +1,10 @@ +var path = require('path'); +var expect = require('chai').expect; + +describe(path.basename(__dirname), function() { + it('should allow getEl() with a split component', function() { + var hello = window.hello; + expect(hello.getEl('button') != null).to.equal(true); + expect(hello.getEl('button').nodeName).to.equal('BUTTON'); + }); +}); diff --git a/test/autotests/components-pages/getEl-split/components/split-component/component-browser.js b/test/autotests/components-pages/getEl-split/components/split-component/component-browser.js new file mode 100644 index 000000000..12bd8ccd8 --- /dev/null +++ b/test/autotests/components-pages/getEl-split/components/split-component/component-browser.js @@ -0,0 +1,5 @@ +module.exports = { + onMount: function() { + window.splitComponent = this; + } +}; diff --git a/test/autotests/components-pages/getEl-split/components/split-component/index.marko b/test/autotests/components-pages/getEl-split/components/split-component/index.marko new file mode 100644 index 000000000..59ff484a2 --- /dev/null +++ b/test/autotests/components-pages/getEl-split/components/split-component/index.marko @@ -0,0 +1,3 @@ + + +
    diff --git a/test/autotests/components-pages/getEl-split/marko.json b/test/autotests/components-pages/getEl-split/marko.json new file mode 100644 index 000000000..f3410fb25 --- /dev/null +++ b/test/autotests/components-pages/getEl-split/marko.json @@ -0,0 +1,3 @@ +{ + "tags-dir": "./components" +} \ No newline at end of file diff --git a/test/autotests/components-pages/getEl-split/template.marko b/test/autotests/components-pages/getEl-split/template.marko new file mode 100644 index 000000000..892360d9d --- /dev/null +++ b/test/autotests/components-pages/getEl-split/template.marko @@ -0,0 +1,23 @@ +lasso-page dependencies=data.browserDependencies lasso=data.lasso + + +html lang="en" + head + meta charset="UTF-8" + title -- Marko Components Tests + lasso-head + body + + div id="test" + div id="mocha" + div id="testsTarget" + + + + lasso-body + + init-components immediate + + lasso-slot name="mocha-run" + + browser-refresh diff --git a/test/autotests/components-pages/getEl-split/tests.js b/test/autotests/components-pages/getEl-split/tests.js new file mode 100644 index 000000000..499182d78 --- /dev/null +++ b/test/autotests/components-pages/getEl-split/tests.js @@ -0,0 +1,10 @@ +var path = require('path'); +var expect = require('chai').expect; + +describe(path.basename(__dirname), function() { + it('should allow getEl() with a split component', function() { + var splitComponent = window.splitComponent; + expect(splitComponent.getEl('button') != null).to.equal(true); + expect(splitComponent.getEl('button').nodeName).to.equal('BUTTON'); + }); +}); diff --git a/test/autotests/components-pages/getRenderedWidgets/tests.js b/test/autotests/components-pages/getRenderedWidgets/tests.js index 1ff11de88..c56e6f962 100644 --- a/test/autotests/components-pages/getRenderedWidgets/tests.js +++ b/test/autotests/components-pages/getRenderedWidgets/tests.js @@ -17,17 +17,20 @@ describe(path.basename(__dirname), function() { expect(window.simpleComponents.length).to.equal(2); expect(window.simpleComponents[0].state.type).to.equal('component state'); - expect(window.simpleComponents[0].state.name).to.equal('Frank'); - expect(window.simpleComponents[0].state.messageCount).to.equal(20); + expect(window.simpleComponents[0].state.name).to.equal('John'); + expect(window.simpleComponents[0].state.messageCount).to.equal(10); expect(window.simpleComponents[0].componentConfig.type).to.equal('component config'); - expect(window.simpleComponents[0].componentConfig.name).to.equal('Frank'); - expect(window.simpleComponents[0].componentConfig.messageCount).to.equal(20); + expect(window.simpleComponents[0].componentConfig.name).to.equal('John'); + expect(window.simpleComponents[0].componentConfig.messageCount).to.equal(10); + expect(window.simpleComponents[1].state.type).to.equal('component state'); - expect(window.simpleComponents[1].state.name).to.equal('John'); - expect(window.simpleComponents[1].state.messageCount).to.equal(10); + expect(window.simpleComponents[1].state.name).to.equal('Frank'); + expect(window.simpleComponents[1].state.messageCount).to.equal(20); expect(window.simpleComponents[1].componentConfig.type).to.equal('component config'); - expect(window.simpleComponents[1].componentConfig.name).to.equal('John'); - expect(window.simpleComponents[1].componentConfig.messageCount).to.equal(10); + expect(window.simpleComponents[1].componentConfig.name).to.equal('Frank'); + expect(window.simpleComponents[1].componentConfig.messageCount).to.equal(20); + + }); }); diff --git a/test/autotests/components-pages/onInput/template.marko b/test/autotests/components-pages/onInput/template.marko index 78bed2709..6adb17325 100644 --- a/test/autotests/components-pages/onInput/template.marko +++ b/test/autotests/components-pages/onInput/template.marko @@ -1,5 +1,7 @@ lasso-page dependencies=data.browserDependencies lasso=data.lasso + + html lang="en" head diff --git a/test/autotests/components-pages/widget-fixed-id/tests.js b/test/autotests/components-pages/widget-fixed-id/tests.js index 6b1908f64..df1e308b0 100644 --- a/test/autotests/components-pages/widget-fixed-id/tests.js +++ b/test/autotests/components-pages/widget-fixed-id/tests.js @@ -4,8 +4,8 @@ var expect = require('chai').expect; describe(path.basename(__dirname), function() { it('should allow fixed IDs for components', function() { var component = window.appFixedId; - expect(component.id).to.equal('appFixedId'); + expect(document.getElementById('appFixedId') != null).to.equal(true); component.testGetComponent(); component.testGetEl(); }); -}); \ No newline at end of file +}); diff --git a/test/autotests/components-server/getRenderedWidgets-noBrowserRerender/test.js b/test/autotests/components-server/getRenderedWidgets-noBrowserRerender/test.js index b9eaeddfb..85232b425 100644 --- a/test/autotests/components-server/getRenderedWidgets-noBrowserRerender/test.js +++ b/test/autotests/components-server/getRenderedWidgets-noBrowserRerender/test.js @@ -18,8 +18,8 @@ module.exports = function(helpers, done) { var componentDefs = renderedComponents.w; expect(componentDefs.length).to.equal(3); - expect(componentDefs[0][0]).to.equal('s0-c0'); - expect(componentDefs[1][0]).to.equal('s0-c1'); + expect(componentDefs[0][0]).to.equal('s0-2'); + expect(componentDefs[1][0]).to.equal('s0-1'); expect(componentDefs[2][0]).to.equal('s0'); done(); }); diff --git a/test/autotests/hot-reload/component-to-template/test.js b/test/autotests/hot-reload/component-to-template/test.js index 1155a21fa..e392070d1 100644 --- a/test/autotests/hot-reload/component-to-template/test.js +++ b/test/autotests/hot-reload/component-to-template/test.js @@ -32,7 +32,7 @@ exports.check = function(marko, hotReload, expect) { copyFiles(nodePath.join(__dirname, 'a')); var component = require(tempTemplatePath); - expect(component.renderToString({ name: 'Frank' })).to.equal('
    Hello Frank
    '); + expect(component.renderToString({ name: 'Frank' })).to.contain('
    Hello Frank
    '); try { fs.unlinkSync(nodePath.join(__dirname, 'temp/component.js')); @@ -42,4 +42,4 @@ exports.check = function(marko, hotReload, expect) { copyFiles(nodePath.join(__dirname, 'b')); expect(component.renderToString({ name: 'Jane' })).to.equal('
    Hello Jane
    '); -}; \ No newline at end of file +}; diff --git a/test/autotests/hot-reload/template-export-component/test.js b/test/autotests/hot-reload/template-export-component/test.js index fe073576b..e2e99681f 100644 --- a/test/autotests/hot-reload/template-export-component/test.js +++ b/test/autotests/hot-reload/template-export-component/test.js @@ -20,10 +20,10 @@ exports.check = function(marko, hotReload, expect) { copyFiles(nodePath.join(__dirname, 'a')); var component = require(tempTemplatePath); - expect(component.renderSync().toString()).to.equal('
    Hello Frank
    '); + expect(component.renderSync().toString()).to.contain('
    Hello Frank
    '); hotReload.handleFileModified(tempTemplatePath); copyFiles(nodePath.join(__dirname, 'b')); - expect(component.renderSync().toString()).to.equal('
    Hello Frank
    '); -}; \ No newline at end of file + expect(component.renderSync().toString()).to.contain('
    Hello Frank
    '); +}; diff --git a/test/autotests/hot-reload/template-to-component/test.js b/test/autotests/hot-reload/template-to-component/test.js index 148aadd60..b4e978dba 100644 --- a/test/autotests/hot-reload/template-to-component/test.js +++ b/test/autotests/hot-reload/template-to-component/test.js @@ -37,5 +37,5 @@ exports.check = function(marko, hotReload, expect) { hotReload.handleFileModified(tempTemplatePath); copyFiles(nodePath.join(__dirname, 'b')); - expect(component.renderSync({ name: 'Jane' }).toString()).to.equal('
    Hello Jane
    '); -}; \ No newline at end of file + expect(component.renderSync({ name: 'Jane' }).toString()).to.contain('
    Hello Jane
    '); +}; diff --git a/test/autotests/morphdom/add-rearrange-incompatible-keys/expected.html b/test/autotests/morphdom/add-rearrange-incompatible-keys/expected.html index 0f8d76b7b..07b9f17fc 100644 --- a/test/autotests/morphdom/add-rearrange-incompatible-keys/expected.html +++ b/test/autotests/morphdom/add-rearrange-incompatible-keys/expected.html @@ -1,3 +1,5 @@ -
    -
    -
    + +
    +
    +
    + "\n" diff --git a/test/autotests/morphdom/add-rearrange/expected.html b/test/autotests/morphdom/add-rearrange/expected.html index 0f8d76b7b..07b9f17fc 100644 --- a/test/autotests/morphdom/add-rearrange/expected.html +++ b/test/autotests/morphdom/add-rearrange/expected.html @@ -1,3 +1,5 @@ -
    -
    -
    + +
    +
    +
    + "\n" diff --git a/test/autotests/morphdom/attr-value-empty-string/expected.html b/test/autotests/morphdom/attr-value-empty-string/expected.html index 8ea34ece4..3475630e5 100644 --- a/test/autotests/morphdom/attr-value-empty-string/expected.html +++ b/test/autotests/morphdom/attr-value-empty-string/expected.html @@ -1 +1,2 @@ - + + diff --git a/test/autotests/morphdom/change-tagname-ids/expected.html b/test/autotests/morphdom/change-tagname-ids/expected.html index fb23f2486..8582e21c4 100644 --- a/test/autotests/morphdom/change-tagname-ids/expected.html +++ b/test/autotests/morphdom/change-tagname-ids/expected.html @@ -1,5 +1,6 @@ -
    - "\n " - - "italics" - "\n" + +
    + "\n " + + "italics" + "\n" diff --git a/test/autotests/morphdom/change-tagname/expected.html b/test/autotests/morphdom/change-tagname/expected.html index 8846924cc..cbdab9107 100644 --- a/test/autotests/morphdom/change-tagname/expected.html +++ b/test/autotests/morphdom/change-tagname/expected.html @@ -1,2 +1,3 @@ - - "bold" + + + "bold" diff --git a/test/autotests/morphdom/data-table/expected.html b/test/autotests/morphdom/data-table/expected.html index 8c4be4f29..92d1c8d77 100644 --- a/test/autotests/morphdom/data-table/expected.html +++ b/test/autotests/morphdom/data-table/expected.html @@ -1,279 +1,280 @@ - - "\n " - - "\n " - - "\n " -
    - "\n " - - "\n virtual-dom\n " - - "\n morphdom\n " - "\n " + + "\n " - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " +
    - "\n FOOBAR\n " - "\n " - - "\n 888ms\n " - - "\n 999ms\n " - "\n " -
    - "\n change-tagname-ids\n " - "\n " - - "\n 0.02ms\n " - - "\n 0.01ms\n " - "\n " -
    - "\n data-table\n " - "\n " - - "\n 0.30ms\n " - - "\n 0.34ms\n " - "\n " -
    - "\n ids-nested\n " - "\n " - - "\n 0.01ms\n " - - "\n 0.01ms\n " - "\n " -
    - "\n ids-nested-2\n " - "\n " - - "\n 0.02ms\n " - - "\n 0.01ms\n " - "\n " -
    - "\n ids-nested-3\n " - "\n " - - "\n 0.16ms\n " - - "\n 0.00ms\n " - "\n " -
    - "\n ids-nested-4\n " - "\n " - - "\n 0.18ms\n " - - "\n 0.07ms\n " - "\n " -
    - "\n ids-nested-5\n " - "\n " - - "\n 0.03ms\n " - - "\n 0.01ms\n " - "\n " -
    - "\n ids-nested-6\n " - "\n " - - "\n 0.02ms\n " - - "\n 0.01ms\n " - "\n " -
    - "\n ids-prepend\n " - "\n " - - "\n 0.02ms\n " - - "\n 0.01ms\n " - "\n " -
    - "\n input-element\n " - "\n " - - "\n 0.01ms\n " - - "\n 0.01ms\n " - "\n " -
    - "\n input-element-disabled\n " - "\n " - - "\n 0.00ms\n " - - "\n 0.03ms\n " - "\n " -
    - "\n input-element-enabled\n " - "\n " - - "\n 0.01ms\n " - - "\n 0.01ms\n " - "\n " -
    - "\n large\n " - "\n " - - "\n 0.95ms\n " - - "\n 1.53ms\n " - "\n " -
    - "\n lengthen\n " - "\n " - - "\n 0.02ms\n " - - "\n 0.02ms\n " - "\n " -
    - "\n one\n " - "\n " - - "\n 0.01ms\n " - - "\n 0.00ms\n " - "\n " -
    - "\n reverse\n " - "\n " - - "\n 0.02ms\n " - - "\n 0.00ms\n " - "\n " -
    - "\n reverse-ids\n " - "\n " - - "\n 0.02ms\n " - - "\n 0.01ms\n " - "\n " -
    - "\n select-element\n " - "\n " - - "\n 0.03ms\n " - - "\n 0.03ms\n " - "\n " -
    - "\n shorten\n " - "\n " - - "\n 0.01ms\n " - - "\n 0.02ms\n " - "\n " -
    - "\n simple\n " - "\n " - - "\n 0.02ms\n " - - "\n 0.00ms\n " - "\n " -
    - "\n simple-ids\n " - "\n " - - "\n 0.03ms\n " - - "\n 0.02ms\n " - "\n " -
    - "\n simple-text-el\n " - "\n " - - "\n 0.02ms\n " - - "\n 0.00ms\n " - "\n " -
    - "\n svg\n " - "\n " - - "\n 0.01ms\n " - - "\n 0.14ms\n " - "\n " -
    - "\n todomvc\n " - "\n " - - "\n 0.23ms\n " - - "\n 0.30ms\n " - "\n " -
    - "\n two\n " - "\n " - - "\n 0.01ms\n " - - "\n 0.01ms\n " +
    + "\n " + + "\n virtual-dom\n " + + "\n morphdom\n " + "\n " + "\n " "\n " - "\n " +
    + "\n FOOBAR\n " + "\n " + + "\n 888ms\n " + + "\n 999ms\n " + "\n " +
    + "\n change-tagname-ids\n " + "\n " + + "\n 0.02ms\n " + + "\n 0.01ms\n " + "\n " +
    + "\n data-table\n " + "\n " + + "\n 0.30ms\n " + + "\n 0.34ms\n " + "\n " +
    + "\n ids-nested\n " + "\n " + + "\n 0.01ms\n " + + "\n 0.01ms\n " + "\n " +
    + "\n ids-nested-2\n " + "\n " + + "\n 0.02ms\n " + + "\n 0.01ms\n " + "\n " +
    + "\n ids-nested-3\n " + "\n " + + "\n 0.16ms\n " + + "\n 0.00ms\n " + "\n " +
    + "\n ids-nested-4\n " + "\n " + + "\n 0.18ms\n " + + "\n 0.07ms\n " + "\n " +
    + "\n ids-nested-5\n " + "\n " + + "\n 0.03ms\n " + + "\n 0.01ms\n " + "\n " +
    + "\n ids-nested-6\n " + "\n " + + "\n 0.02ms\n " + + "\n 0.01ms\n " + "\n " +
    + "\n ids-prepend\n " + "\n " + + "\n 0.02ms\n " + + "\n 0.01ms\n " + "\n " +
    + "\n input-element\n " + "\n " + + "\n 0.01ms\n " + + "\n 0.01ms\n " + "\n " +
    + "\n input-element-disabled\n " + "\n " + + "\n 0.00ms\n " + + "\n 0.03ms\n " + "\n " +
    + "\n input-element-enabled\n " + "\n " + + "\n 0.01ms\n " + + "\n 0.01ms\n " + "\n " +
    + "\n large\n " + "\n " + + "\n 0.95ms\n " + + "\n 1.53ms\n " + "\n " +
    + "\n lengthen\n " + "\n " + + "\n 0.02ms\n " + + "\n 0.02ms\n " + "\n " +
    + "\n one\n " + "\n " + + "\n 0.01ms\n " + + "\n 0.00ms\n " + "\n " +
    + "\n reverse\n " + "\n " + + "\n 0.02ms\n " + + "\n 0.00ms\n " + "\n " +
    + "\n reverse-ids\n " + "\n " + + "\n 0.02ms\n " + + "\n 0.01ms\n " + "\n " +
    + "\n select-element\n " + "\n " + + "\n 0.03ms\n " + + "\n 0.03ms\n " + "\n " +
    + "\n shorten\n " + "\n " + + "\n 0.01ms\n " + + "\n 0.02ms\n " + "\n " +
    + "\n simple\n " + "\n " + + "\n 0.02ms\n " + + "\n 0.00ms\n " + "\n " +
    + "\n simple-ids\n " + "\n " + + "\n 0.03ms\n " + + "\n 0.02ms\n " + "\n " +
    + "\n simple-text-el\n " + "\n " + + "\n 0.02ms\n " + + "\n 0.00ms\n " + "\n " +
    + "\n svg\n " + "\n " + + "\n 0.01ms\n " + + "\n 0.14ms\n " + "\n " +
    + "\n todomvc\n " + "\n " + + "\n 0.23ms\n " + + "\n 0.30ms\n " + "\n " +
    + "\n two\n " + "\n " + + "\n 0.01ms\n " + + "\n 0.01ms\n " + "\n " + "\n " + "\n " diff --git a/test/autotests/morphdom/data-table2/expected.html b/test/autotests/morphdom/data-table2/expected.html index 7ecf259fa..841fa8b3f 100644 --- a/test/autotests/morphdom/data-table2/expected.html +++ b/test/autotests/morphdom/data-table2/expected.html @@ -1,1103 +1,1104 @@ - - "\n " - - "\n " - - "\n " -
    - "Name" - "\n " - - "Position" - "\n " - - "Office" - "\n " - - "Age" - "\n " - - "Start date" - "\n " - - "Salary" - "\n " + + "\n " - "\n " - - "\n " - - "\n " - "\n " + + "\n " + - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - - "\n " - "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " +
    - "Name" - "\n " - - "Position" - "\n " - - "Office" - "\n " - - "Age" - "\n " - - "Start date" - "\n " - - "Salary" +
    + "Name" + "\n " + + "Position" + "\n " + + "Office" + "\n " + + "Age" + "\n " + + "Start date" + "\n " + + "Salary" + "\n " + "\n " "\n " - "\n " -
    - "Zorita Serrano" - "\n " - - "Software Engineer" - "\n " - - "San Francisco" - "\n " - - "56" - "\n " - - "2012/06/01" - "\n " - - "$115,000" - "\n " - "\n " -
    - "Zenaida Frank" - "\n " - - "Software Engineer" - "\n " - - "New York" - "\n " - - "63" - "\n " - - "2010/01/04" - "\n " - - "$125,250" - "\n " - "\n " -
    - "Yuri Berry" - "\n " - - "Chief Marketing Officer (CMO)" - "\n " - - "New York" - "\n " - - "40" - "\n " - - "2009/06/25" - "\n " - - "$675,000" - "\n " - "\n " -
    - "Vivian Harrell" - "\n " - - "Financial Controller" - "\n " - - "San Francisco" - "\n " - - "62" - "\n " - - "2009/02/14" - "\n " - - "$452,500" - "\n " - "\n " -
    - "Unity Butler" - "\n " - - "Marketing Designer" - "\n " - - "San Francisco" - "\n " - - "47" - "\n " - - "2009/12/09" - "\n " - - "$85,675" - "\n " - "\n " -
    - "Timothy Mooney" - "\n " - - "Office Manager" - "\n " - - "London" - "\n " - - "37" - "\n " - - "2008/12/11" - "\n " - - "$136,200" - "\n " - "\n " -
    - "Tiger Nixon" - "\n " - - "System Architect" - "\n " - - "Edinburgh" - "\n " - - "61" - "\n " - - "2011/04/25" - "\n " - - "$320,800" - "\n " - "\n " -
    - "Thor Walton" - "\n " - - "Developer" - "\n " - - "New York" - "\n " - - "61" - "\n " - - "2013/08/11" - "\n " - - "$98,540" - "\n " - "\n " -
    - "Tatyana Fitzpatrick" - "\n " - - "Regional Director" - "\n " - - "London" - "\n " - - "19" - "\n " - - "2010/03/17" - "\n " - - "$385,750" - "\n " - "\n " -
    - "Suki Burks" - "\n " - - "Developer" - "\n " - - "London" - "\n " - - "53" - "\n " - - "2009/10/22" - "\n " - - "$114,500" - "\n " - "\n " -
    - "Sonya Frost" - "\n " - - "Software Engineer" - "\n " - - "Edinburgh" - "\n " - - "23" - "\n " - - "2008/12/13" - "\n " - - "$103,600" - "\n " - "\n " -
    - "Shou Itou" - "\n " - - "Regional Marketing" - "\n " - - "Tokyo" - "\n " - - "20" - "\n " - - "2011/08/14" - "\n " - - "$163,000" - "\n " - "\n " -
    - "Shad Decker" - "\n " - - "Regional Director" - "\n " - - "Edinburgh" - "\n " - - "51" - "\n " - - "2008/11/13" - "\n " - - "$183,000" - "\n " - "\n " -
    - "Serge Baldwin" - "\n " - - "Data Coordinator" - "\n " - - "Singapore" - "\n " - - "64" - "\n " - - "2012/04/09" - "\n " - - "$138,575" - "\n " - "\n " -
    - "Sakura Yamamoto" - "\n " - - "Support Engineer" - "\n " - - "Tokyo" - "\n " - - "37" - "\n " - - "2009/08/19" - "\n " - - "$139,575" - "\n " - "\n " -
    - "Rhona Davidson" - "\n " - - "Integration Specialist" - "\n " - - "Tokyo" - "\n " - - "55" - "\n " - - "2010/10/14" - "\n " - - "$327,900" - "\n " - "\n " -
    - "Quinn Flynn" - "\n " - - "Support Lead" - "\n " - - "Edinburgh" - "\n " - - "22" - "\n " - - "2013/03/03" - "\n " - - "$342,000" - "\n " - "\n " -
    - "Prescott Bartlett" - "\n " - - "Technical Author" - "\n " - - "London" - "\n " - - "27" - "\n " - - "2011/05/07" - "\n " - - "$145,000" - "\n " - "\n " -
    - "Paul Byrd" - "\n " - - "Chief Financial Officer (CFO)" - "\n " - - "New York" - "\n " - - "64" - "\n " - - "2010/06/09" - "\n " - - "$725,000" - "\n " - "\n " -
    - "Olivia Liang" - "\n " - - "Support Engineer" - "\n " - - "Singapore" - "\n " - - "64" - "\n " - - "2011/02/03" - "\n " - - "$234,500" - "\n " - "\n " -
    - "Michelle House" - "\n " - - "Integration Specialist" - "\n " - - "Sidney" - "\n " - - "37" - "\n " - - "2011/06/02" - "\n " - - "$95,400" - "\n " - "\n " -
    - "Michael Silva" - "\n " - - "Marketing Designer" - "\n " - - "London" - "\n " - - "66" - "\n " - - "2012/11/27" - "\n " - - "$198,500" - "\n " - "\n " -
    - "Michael Bruce" - "\n " - - "Javascript Developer" - "\n " - - "Singapore" - "\n " - - "29" - "\n " - - "2011/06/27" - "\n " - - "$183,000" - "\n " - "\n " -
    - "Martena Mccray" - "\n " - - "Post-Sales support" - "\n " - - "Edinburgh" - "\n " - - "46" - "\n " - - "2011/03/09" - "\n " - - "$324,050" - "\n " - "\n " -
    - "Lael Greer" - "\n " - - "Systems Administrator" - "\n " - - "London" - "\n " - - "21" - "\n " - - "2009/02/27" - "\n " - - "$103,500" - "\n " - "\n " -
    - "Jonas Alexander" - "\n " - - "Developer" - "\n " - - "San Francisco" - "\n " - - "30" - "\n " - - "2010/07/14" - "\n " - - "$86,500" - "\n " - "\n " -
    - "Jennifer Chang" - "\n " - - "Regional Director" - "\n " - - "Singapore" - "\n " - - "28" - "\n " - - "2010/11/14" - "\n " - - "$357,650" - "\n " - "\n " -
    - "Jennifer Acosta" - "\n " - - "Junior Javascript Developer" - "\n " - - "Edinburgh" - "\n " - - "43" - "\n " - - "2013/02/01" - "\n " - - "$75,650" - "\n " - "\n " -
    - "Jenette Caldwell" - "\n " - - "Development Lead" - "\n " - - "New York" - "\n " - - "30" - "\n " - - "2011/09/03" - "\n " - - "$345,000" - "\n " - "\n " -
    - "Jena Gaines" - "\n " - - "Office Manager" - "\n " - - "London" - "\n " - - "30" - "\n " - - "2008/12/19" - "\n " - - "$90,560" - "\n " - "\n " -
    - "Jackson Bradshaw" - "\n " - - "Director" - "\n " - - "New York" - "\n " - - "65" - "\n " - - "2008/09/26" - "\n " - - "$645,750" - "\n " - "\n " -
    - "Howard Hatfield" - "\n " - - "Office Manager" - "\n " - - "San Francisco" - "\n " - - "51" - "\n " - - "2008/12/16" - "\n " - - "$164,500" - "\n " - "\n " -
    - "Hope Fuentes" - "\n " - - "Secretary" - "\n " - - "San Francisco" - "\n " - - "41" - "\n " - - "2010/02/12" - "\n " - - "$109,850" - "\n " - "\n " -
    - "Herrod Chandler" - "\n " - - "Sales Assistant" - "\n " - - "San Francisco" - "\n " - - "59" - "\n " - - "2012/08/06" - "\n " - - "$137,500" - "\n " - "\n " -
    - "Hermione Butler" - "\n " - - "Regional Director" - "\n " - - "London" - "\n " - - "47" - "\n " - - "2011/03/21" - "\n " - - "$356,250" - "\n " - "\n " -
    - "Haley Kennedy" - "\n " - - "Senior Marketing Designer" - "\n " - - "London" - "\n " - - "43" - "\n " - - "2012/12/18" - "\n " - - "$313,500" - "\n " - "\n " -
    - "Gloria Little" - "\n " - - "Systems Administrator" - "\n " - - "New York" - "\n " - - "59" - "\n " - - "2009/04/10" - "\n " - - "$237,500" - "\n " - "\n " -
    - "Gavin Joyce" - "\n " - - "Developer" - "\n " - - "Edinburgh" - "\n " - - "42" - "\n " - - "2010/12/22" - "\n " - - "$92,575" - "\n " - "\n " -
    - "Gavin Cortez" - "\n " - - "Team Leader" - "\n " - - "San Francisco" - "\n " - - "22" - "\n " - - "2008/10/26" - "\n " - - "$235,500" - "\n " - "\n " -
    - "Garrett Winters" - "\n " - - "Accountant" - "\n " - - "Tokyo" - "\n " - - "63" - "\n " - - "2011/07/25" - "\n " - - "$170,750" - "\n " - "\n " -
    - "Fiona Green" - "\n " - - "Chief Operating Officer (COO)" - "\n " - - "San Francisco" - "\n " - - "48" - "\n " - - "2010/03/11" - "\n " - - "$850,000" - "\n " - "\n " -
    - "Finn Camacho" - "\n " - - "Support Engineer" - "\n " - - "San Francisco" - "\n " - - "47" - "\n " - - "2009/07/07" - "\n " - - "$87,500" - "\n " - "\n " -
    - "Doris Wilder" - "\n " - - "Sales Assistant" - "\n " - - "Sidney" - "\n " - - "23" - "\n " - - "2010/09/20" - "\n " - - "$85,600" - "\n " - "\n " -
    - "Donna Snider" - "\n " - - "Customer Support" - "\n " - - "New York" - "\n " - - "27" - "\n " - - "2011/01/25" - "\n " - - "$112,000" - "\n " - "\n " -
    - "Dai Rios" - "\n " - - "Personnel Lead" - "\n " - - "Edinburgh" - "\n " - - "35" - "\n " - - "2012/09/26" - "\n " - - "$217,500" - "\n " - "\n " -
    - "Colleen Hurst" - "\n " - - "Javascript Developer" - "\n " - - "San Francisco" - "\n " - - "39" - "\n " - - "2009/09/15" - "\n " - - "$205,500" - "\n " - "\n " -
    - "Charde Marshall" - "\n " - - "Regional Director" - "\n " - - "San Francisco" - "\n " - - "36" - "\n " - - "2008/10/16" - "\n " - - "$470,600" - "\n " - "\n " -
    - "Cedric Kelly" - "\n " - - "Senior Javascript Developer" - "\n " - - "Edinburgh" - "\n " - - "22" - "\n " - - "2012/03/29" - "\n " - - "$433,060" - "\n " - "\n " -
    - "Cara Stevens" - "\n " - - "Sales Assistant" - "\n " - - "New York" - "\n " - - "46" - "\n " - - "2011/12/06" - "\n " - - "$145,600" - "\n " - "\n " -
    - "Caesar Vance" - "\n " - - "Pre-Sales Support" - "\n " - - "New York" - "\n " - - "21" - "\n " - - "2011/12/12" - "\n " - - "$106,450" +
    + "Name" + "\n " + + "Position" + "\n " + + "Office" + "\n " + + "Age" + "\n " + + "Start date" + "\n " + + "Salary" + "\n " + "\n " "\n " - "\n" +
    + "Zorita Serrano" + "\n " + + "Software Engineer" + "\n " + + "San Francisco" + "\n " + + "56" + "\n " + + "2012/06/01" + "\n " + + "$115,000" + "\n " + "\n " +
    + "Zenaida Frank" + "\n " + + "Software Engineer" + "\n " + + "New York" + "\n " + + "63" + "\n " + + "2010/01/04" + "\n " + + "$125,250" + "\n " + "\n " +
    + "Yuri Berry" + "\n " + + "Chief Marketing Officer (CMO)" + "\n " + + "New York" + "\n " + + "40" + "\n " + + "2009/06/25" + "\n " + + "$675,000" + "\n " + "\n " +
    + "Vivian Harrell" + "\n " + + "Financial Controller" + "\n " + + "San Francisco" + "\n " + + "62" + "\n " + + "2009/02/14" + "\n " + + "$452,500" + "\n " + "\n " +
    + "Unity Butler" + "\n " + + "Marketing Designer" + "\n " + + "San Francisco" + "\n " + + "47" + "\n " + + "2009/12/09" + "\n " + + "$85,675" + "\n " + "\n " +
    + "Timothy Mooney" + "\n " + + "Office Manager" + "\n " + + "London" + "\n " + + "37" + "\n " + + "2008/12/11" + "\n " + + "$136,200" + "\n " + "\n " +
    + "Tiger Nixon" + "\n " + + "System Architect" + "\n " + + "Edinburgh" + "\n " + + "61" + "\n " + + "2011/04/25" + "\n " + + "$320,800" + "\n " + "\n " +
    + "Thor Walton" + "\n " + + "Developer" + "\n " + + "New York" + "\n " + + "61" + "\n " + + "2013/08/11" + "\n " + + "$98,540" + "\n " + "\n " +
    + "Tatyana Fitzpatrick" + "\n " + + "Regional Director" + "\n " + + "London" + "\n " + + "19" + "\n " + + "2010/03/17" + "\n " + + "$385,750" + "\n " + "\n " +
    + "Suki Burks" + "\n " + + "Developer" + "\n " + + "London" + "\n " + + "53" + "\n " + + "2009/10/22" + "\n " + + "$114,500" + "\n " + "\n " +
    + "Sonya Frost" + "\n " + + "Software Engineer" + "\n " + + "Edinburgh" + "\n " + + "23" + "\n " + + "2008/12/13" + "\n " + + "$103,600" + "\n " + "\n " +
    + "Shou Itou" + "\n " + + "Regional Marketing" + "\n " + + "Tokyo" + "\n " + + "20" + "\n " + + "2011/08/14" + "\n " + + "$163,000" + "\n " + "\n " +
    + "Shad Decker" + "\n " + + "Regional Director" + "\n " + + "Edinburgh" + "\n " + + "51" + "\n " + + "2008/11/13" + "\n " + + "$183,000" + "\n " + "\n " +
    + "Serge Baldwin" + "\n " + + "Data Coordinator" + "\n " + + "Singapore" + "\n " + + "64" + "\n " + + "2012/04/09" + "\n " + + "$138,575" + "\n " + "\n " +
    + "Sakura Yamamoto" + "\n " + + "Support Engineer" + "\n " + + "Tokyo" + "\n " + + "37" + "\n " + + "2009/08/19" + "\n " + + "$139,575" + "\n " + "\n " +
    + "Rhona Davidson" + "\n " + + "Integration Specialist" + "\n " + + "Tokyo" + "\n " + + "55" + "\n " + + "2010/10/14" + "\n " + + "$327,900" + "\n " + "\n " +
    + "Quinn Flynn" + "\n " + + "Support Lead" + "\n " + + "Edinburgh" + "\n " + + "22" + "\n " + + "2013/03/03" + "\n " + + "$342,000" + "\n " + "\n " +
    + "Prescott Bartlett" + "\n " + + "Technical Author" + "\n " + + "London" + "\n " + + "27" + "\n " + + "2011/05/07" + "\n " + + "$145,000" + "\n " + "\n " +
    + "Paul Byrd" + "\n " + + "Chief Financial Officer (CFO)" + "\n " + + "New York" + "\n " + + "64" + "\n " + + "2010/06/09" + "\n " + + "$725,000" + "\n " + "\n " +
    + "Olivia Liang" + "\n " + + "Support Engineer" + "\n " + + "Singapore" + "\n " + + "64" + "\n " + + "2011/02/03" + "\n " + + "$234,500" + "\n " + "\n " +
    + "Michelle House" + "\n " + + "Integration Specialist" + "\n " + + "Sidney" + "\n " + + "37" + "\n " + + "2011/06/02" + "\n " + + "$95,400" + "\n " + "\n " +
    + "Michael Silva" + "\n " + + "Marketing Designer" + "\n " + + "London" + "\n " + + "66" + "\n " + + "2012/11/27" + "\n " + + "$198,500" + "\n " + "\n " +
    + "Michael Bruce" + "\n " + + "Javascript Developer" + "\n " + + "Singapore" + "\n " + + "29" + "\n " + + "2011/06/27" + "\n " + + "$183,000" + "\n " + "\n " +
    + "Martena Mccray" + "\n " + + "Post-Sales support" + "\n " + + "Edinburgh" + "\n " + + "46" + "\n " + + "2011/03/09" + "\n " + + "$324,050" + "\n " + "\n " +
    + "Lael Greer" + "\n " + + "Systems Administrator" + "\n " + + "London" + "\n " + + "21" + "\n " + + "2009/02/27" + "\n " + + "$103,500" + "\n " + "\n " +
    + "Jonas Alexander" + "\n " + + "Developer" + "\n " + + "San Francisco" + "\n " + + "30" + "\n " + + "2010/07/14" + "\n " + + "$86,500" + "\n " + "\n " +
    + "Jennifer Chang" + "\n " + + "Regional Director" + "\n " + + "Singapore" + "\n " + + "28" + "\n " + + "2010/11/14" + "\n " + + "$357,650" + "\n " + "\n " +
    + "Jennifer Acosta" + "\n " + + "Junior Javascript Developer" + "\n " + + "Edinburgh" + "\n " + + "43" + "\n " + + "2013/02/01" + "\n " + + "$75,650" + "\n " + "\n " +
    + "Jenette Caldwell" + "\n " + + "Development Lead" + "\n " + + "New York" + "\n " + + "30" + "\n " + + "2011/09/03" + "\n " + + "$345,000" + "\n " + "\n " +
    + "Jena Gaines" + "\n " + + "Office Manager" + "\n " + + "London" + "\n " + + "30" + "\n " + + "2008/12/19" + "\n " + + "$90,560" + "\n " + "\n " +
    + "Jackson Bradshaw" + "\n " + + "Director" + "\n " + + "New York" + "\n " + + "65" + "\n " + + "2008/09/26" + "\n " + + "$645,750" + "\n " + "\n " +
    + "Howard Hatfield" + "\n " + + "Office Manager" + "\n " + + "San Francisco" + "\n " + + "51" + "\n " + + "2008/12/16" + "\n " + + "$164,500" + "\n " + "\n " +
    + "Hope Fuentes" + "\n " + + "Secretary" + "\n " + + "San Francisco" + "\n " + + "41" + "\n " + + "2010/02/12" + "\n " + + "$109,850" + "\n " + "\n " +
    + "Herrod Chandler" + "\n " + + "Sales Assistant" + "\n " + + "San Francisco" + "\n " + + "59" + "\n " + + "2012/08/06" + "\n " + + "$137,500" + "\n " + "\n " +
    + "Hermione Butler" + "\n " + + "Regional Director" + "\n " + + "London" + "\n " + + "47" + "\n " + + "2011/03/21" + "\n " + + "$356,250" + "\n " + "\n " +
    + "Haley Kennedy" + "\n " + + "Senior Marketing Designer" + "\n " + + "London" + "\n " + + "43" + "\n " + + "2012/12/18" + "\n " + + "$313,500" + "\n " + "\n " +
    + "Gloria Little" + "\n " + + "Systems Administrator" + "\n " + + "New York" + "\n " + + "59" + "\n " + + "2009/04/10" + "\n " + + "$237,500" + "\n " + "\n " +
    + "Gavin Joyce" + "\n " + + "Developer" + "\n " + + "Edinburgh" + "\n " + + "42" + "\n " + + "2010/12/22" + "\n " + + "$92,575" + "\n " + "\n " +
    + "Gavin Cortez" + "\n " + + "Team Leader" + "\n " + + "San Francisco" + "\n " + + "22" + "\n " + + "2008/10/26" + "\n " + + "$235,500" + "\n " + "\n " +
    + "Garrett Winters" + "\n " + + "Accountant" + "\n " + + "Tokyo" + "\n " + + "63" + "\n " + + "2011/07/25" + "\n " + + "$170,750" + "\n " + "\n " +
    + "Fiona Green" + "\n " + + "Chief Operating Officer (COO)" + "\n " + + "San Francisco" + "\n " + + "48" + "\n " + + "2010/03/11" + "\n " + + "$850,000" + "\n " + "\n " +
    + "Finn Camacho" + "\n " + + "Support Engineer" + "\n " + + "San Francisco" + "\n " + + "47" + "\n " + + "2009/07/07" + "\n " + + "$87,500" + "\n " + "\n " +
    + "Doris Wilder" + "\n " + + "Sales Assistant" + "\n " + + "Sidney" + "\n " + + "23" + "\n " + + "2010/09/20" + "\n " + + "$85,600" + "\n " + "\n " +
    + "Donna Snider" + "\n " + + "Customer Support" + "\n " + + "New York" + "\n " + + "27" + "\n " + + "2011/01/25" + "\n " + + "$112,000" + "\n " + "\n " +
    + "Dai Rios" + "\n " + + "Personnel Lead" + "\n " + + "Edinburgh" + "\n " + + "35" + "\n " + + "2012/09/26" + "\n " + + "$217,500" + "\n " + "\n " +
    + "Colleen Hurst" + "\n " + + "Javascript Developer" + "\n " + + "San Francisco" + "\n " + + "39" + "\n " + + "2009/09/15" + "\n " + + "$205,500" + "\n " + "\n " +
    + "Charde Marshall" + "\n " + + "Regional Director" + "\n " + + "San Francisco" + "\n " + + "36" + "\n " + + "2008/10/16" + "\n " + + "$470,600" + "\n " + "\n " +
    + "Cedric Kelly" + "\n " + + "Senior Javascript Developer" + "\n " + + "Edinburgh" + "\n " + + "22" + "\n " + + "2012/03/29" + "\n " + + "$433,060" + "\n " + "\n " +
    + "Cara Stevens" + "\n " + + "Sales Assistant" + "\n " + + "New York" + "\n " + + "46" + "\n " + + "2011/12/06" + "\n " + + "$145,600" + "\n " + "\n " +
    + "Caesar Vance" + "\n " + + "Pre-Sales Support" + "\n " + + "New York" + "\n " + + "21" + "\n " + + "2011/12/12" + "\n " + + "$106,450" + "\n " + "\n " + "\n" diff --git a/test/autotests/morphdom/equal/expected.html b/test/autotests/morphdom/equal/expected.html index 2eb994f31..873725939 100644 --- a/test/autotests/morphdom/equal/expected.html +++ b/test/autotests/morphdom/equal/expected.html @@ -1,144 +1,145 @@ -
    - "\n " -
    - "\n " -