diff --git a/compiler/ast/CustomTag.js b/compiler/ast/CustomTag.js index ab29a6d17..a40436492 100644 --- a/compiler/ast/CustomTag.js +++ b/compiler/ast/CustomTag.js @@ -299,7 +299,8 @@ class CustomTag extends HtmlElement { // to the input object for the custom tag this.forEachAttribute((attr) => { var attrName = attr.name; - var attrDef = attr.def || tagDef.getAttribute(attr.name); + + var attrDef = attr.def || context.taglibLookup.getAttribute(tagName, attrName) || tagDef.getAttribute(attr.name); if (!attrDef) { var errorMessage = 'Unsupported attribute of "' + attrName + '" found on the <' + this.tagName + '> custom tag.'; diff --git a/compiler/ast/TemplateRoot.js b/compiler/ast/TemplateRoot.js index b0bd2aa98..73c18e90b 100644 --- a/compiler/ast/TemplateRoot.js +++ b/compiler/ast/TemplateRoot.js @@ -15,6 +15,16 @@ class TemplateRoot extends Node { constructor(def) { super('TemplateRoot'); this.body = this.makeContainer(def.body); + this.extraRenderParams = null; + this.generateAssignRenderCode = null; + } + + addRenderFunctionParam(id) { + if (!this.extraRenderParams) { + this.extraRenderParams = []; + } + + this.extraRenderParams.push(id); } generateCode(codegen) { @@ -24,8 +34,6 @@ class TemplateRoot extends Node { context.optimize(this); - context.emit('beforeGenerateCodeTemplateRoot', this); - var body = this.body; var builder = codegen.builder; @@ -54,48 +62,73 @@ class TemplateRoot extends Node { renderStatements) ]); } else { - var templateArgs = [ - builder.identifier('__filename') - ]; - - let templateId = builder.identifier('template'); - let body = [ - builder.var(templateId, builder.functionCall( + builder.var('marko_template', builder.functionCall( builder.memberExpression( builder.require( builder.literal(context.getModuleRuntimeTarget()) ), - builder.identifier('c') + builder.identifier('t') ), - templateArgs - )) + [ + builder.identifier('__filename') + ] + )), + builder.assignment( + builder.moduleExports(), + builder.identifier('marko_template')) ]; - var templateExports = this.generateExports(templateId, context); - - body = body.concat(templateExports); - let staticNodes = context.getStaticNodes(); if (staticNodes.length) { body = body.concat(staticNodes); } + var renderParams = [builder.identifier('data'), builder.identifierOut()]; + if (this.extraRenderParams) { + renderParams = renderParams.concat(this.extraRenderParams); + } + let renderFunction = builder.functionDeclaration( 'render', - ['data', builder.identifierOut()], + renderParams, renderStatements); body = body.concat([ renderFunction, - builder.assignment( - builder.memberExpression(builder.identifier('template'), builder.identifier('_')), - builder.identifier('render')) ]); + var assignRenderCode; + + let templateVar = builder.identifier('marko_template'); + let renderFunctionVar = builder.identifier('render'); + let templateRendererMember = builder.memberExpression( + builder.identifier('marko_template'), + builder.identifier('_')); + + if (this.generateAssignRenderCode) { + var eventArgs = { + context, + templateVar, + templateRendererMember, + renderFunctionVar + }; + + assignRenderCode = this.generateAssignRenderCode(eventArgs); + } else { + + assignRenderCode = builder.assignment( + templateRendererMember, + renderFunctionVar); + } + + if (assignRenderCode) { + body = body.concat(assignRenderCode); + } + if (context.useMeta && context.meta) { body.push(builder.assignment( - builder.memberExpression(builder.identifier('template'), builder.identifier('meta')), + builder.memberExpression(builder.identifier('marko_template'), builder.identifier('meta')), context.meta)); } @@ -103,15 +136,6 @@ class TemplateRoot extends Node { } } - generateExports(template, context) { - var builder = context.builder; - - return builder.assignment( - builder.memberExpression('module', 'exports'), - template - ); - } - toJSON(prettyPrinter) { return { type: this.type, diff --git a/hot-reload/index.js b/hot-reload/index.js index 73836498d..7d46054fb 100644 --- a/hot-reload/index.js +++ b/hot-reload/index.js @@ -12,7 +12,22 @@ var modifiedId = 1; var HOT_RELOAD_KEY = Symbol('HOT_RELOAD'); +function cleaResolvePathCache() { + var modulePathCache = require('module').Module._pathCache; + if (!modulePathCache) { + console.log('[marko/hot-reload] WARNING: Missing: require("module").Module._pathCache [' + __filename + ']'); + return; + } + + var keys = Object.keys(modulePathCache); + keys.forEach(function(key) { + delete modulePathCache[key]; + }); +} + function tryReloadTemplate(path) { + path = path.replace(/\.js$/, ''); + try { return marko.load(path); } catch(e) { @@ -32,91 +47,62 @@ exports.enable = function() { // installed in the project will have hot reload enabled. process.env.MARKO_HOT_RELOAD = 'true'; - var oldCreateTemplate = runtime.c; - - function patchMethods(obj, methodNames, reloadFunc) { - var hotReloadData = obj[HOT_RELOAD_KEY] || (obj[HOT_RELOAD_KEY] = {}); - hotReloadData._modifiedId = modifiedId; - hotReloadData._latest = obj; - - methodNames.forEach(function(methodName) { - hotReloadData[methodName] = obj[methodName]; - - obj[methodName] = function hotReloadWrapper() { - if (hotReloadData.modifiedId !== modifiedId) { - hotReloadData.modifiedId = modifiedId; - hotReloadData._latest = reloadFunc() || obj; - } - - var latest = hotReloadData._latest; - return latest[HOT_RELOAD_KEY][methodName].apply(latest, arguments); + function createHotReloadProxy(func, template, methodName) { + var hotReloadData = template[HOT_RELOAD_KEY]; + if (!hotReloadData) { + hotReloadData = template[HOT_RELOAD_KEY] = { + modifiedId: modifiedId, + latest: template, + originals: {} }; - }); + } + + hotReloadData.originals[methodName] = func; + + var templatePath = template.path; + + function hotReloadProxy() { + if (hotReloadData.modifiedId !== modifiedId) { + hotReloadData.modifiedId = modifiedId; + hotReloadData.latest = tryReloadTemplate(templatePath) || template; + + if (hotReloadData.latest !== template) { + template.meta = hotReloadData.latest.meta; + console.log('[marko/hot-reload] Template successfully reloaded: ' + templatePath); + } + } + + var latest = hotReloadData.latest; + var originals = latest[HOT_RELOAD_KEY] && latest[HOT_RELOAD_KEY].originals; + if (!originals) { + originals = latest; + } + + var targetFunc = originals._; + return targetFunc.apply(latest, arguments); + } + + return hotReloadProxy; } - runtime.c = function hotReloadCreateTemplate(path) { - var originalTemplate = oldCreateTemplate.apply(runtime, arguments); - path = path.replace(/\.js$/, ''); + var oldCreateTemplate = runtime.t; + runtime.t = function hotReloadCreateTemplate(path) { + var originalTemplate = oldCreateTemplate.apply(runtime, arguments); var actualRenderFunc; - var firstSet = true; - Object.defineProperty(originalTemplate, '_', { - configurable: true, - get: function() { return actualRenderFunc; }, set: function(renderFunc) { - actualRenderFunc = renderFunc; - if (firstSet) { - firstSet = false; - patchMethods(originalTemplate, ['_'], function reloadTemplate() { - var latestTemplate = tryReloadTemplate(path); - if (latestTemplate) { - if (latestTemplate !== originalTemplate) { - console.log('[marko/hot-reload] Reloaded template: ' + path); - originalTemplate.meta = latestTemplate.meta; - } - - if (latestTemplate.template) { - // The template might export a component that has a template property. - return latestTemplate.template; - } else { - return latestTemplate; - } - } - }); - } + actualRenderFunc = createHotReloadProxy(renderFunc, originalTemplate, '_'); } }); return originalTemplate; }; - - var oldCreateComponent = widgets.c; - - widgets.c = function hotReloadCreateComponent(componentDef, template) { - var path = template.path; - path = path.replace(/\.js$/, ''); - - var originalComponent = oldCreateComponent.apply(runtime, arguments); - - patchMethods(originalComponent, ['renderer', 'render', 'renderSync'], function reloadTemplate() { - var latestComponent = tryReloadTemplate(path); - if (latestComponent) { - if (latestComponent !== originalComponent) { - console.log('[marko/hot-reload] Reloaded template: ' + path); - } - return latestComponent; - } - - }); - - return originalComponent; - }; }; exports.handleFileModified = function(path) { @@ -131,6 +117,7 @@ exports.handleFileModified = function(path) { console.log('[marko/hot-reload] File modified: ' + path); runtime.cache = {}; compiler.clearCaches(); + cleaResolvePathCache(); modifiedId++; } diff --git a/runtime/html/index.js b/runtime/html/index.js index 587a1f1ce..2d125de66 100644 --- a/runtime/html/index.js +++ b/runtime/html/index.js @@ -8,7 +8,7 @@ var makeRenderable = require('../renderable'); * it is used to create a new Template instance. * @private */ -exports.c = function createTemplate(path) { +exports.t = function createTemplate(path) { return new Template(path); }; diff --git a/runtime/vdom/index.js b/runtime/vdom/index.js index 332d1ff9a..32d4320c6 100644 --- a/runtime/vdom/index.js +++ b/runtime/vdom/index.js @@ -10,7 +10,7 @@ var makeRenderable = require('../renderable'); * it is used to create a new Template instance. * @private */ -exports.c = function createTemplate(path) { +exports.t = function createTemplate(path) { return new Template(path); }; diff --git a/test/autotests/codegen/codegen-addStaticVar/expected.js b/test/autotests/codegen/codegen-addStaticVar/expected.js index 784bb89d6..6c4b6c93f 100644 --- a/test/autotests/codegen/codegen-addStaticVar/expected.js +++ b/test/autotests/codegen/codegen-addStaticVar/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var foo = "Hello World"; @@ -8,4 +8,4 @@ function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/codegen/codegen-addVar/expected.js b/test/autotests/codegen/codegen-addVar/expected.js index 980958d25..7bb4f085b 100644 --- a/test/autotests/codegen/codegen-addVar/expected.js +++ b/test/autotests/codegen/codegen-addVar/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { var foo = "Hello World"; @@ -8,4 +8,4 @@ function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/codegen/context-addStaticVar-dedupe/expected.js b/test/autotests/codegen/context-addStaticVar-dedupe/expected.js index 784bb89d6..6c4b6c93f 100644 --- a/test/autotests/codegen/context-addStaticVar-dedupe/expected.js +++ b/test/autotests/codegen/context-addStaticVar-dedupe/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var foo = "Hello World"; @@ -8,4 +8,4 @@ function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/codegen/context-addStaticVar/expected.js b/test/autotests/codegen/context-addStaticVar/expected.js index 784bb89d6..6c4b6c93f 100644 --- a/test/autotests/codegen/context-addStaticVar/expected.js +++ b/test/autotests/codegen/context-addStaticVar/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var foo = "Hello World"; @@ -8,4 +8,4 @@ function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/codegen/context-addVar-addStaticVar/expected.js b/test/autotests/codegen/context-addVar-addStaticVar/expected.js index 8e9f56eaf..7c4eeac52 100644 --- a/test/autotests/codegen/context-addVar-addStaticVar/expected.js +++ b/test/autotests/codegen/context-addVar-addStaticVar/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var fooStatic = "Hello Foo", barStatic = "Hello Bar"; @@ -12,4 +12,4 @@ function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/codegen/context-addVar/expected.js b/test/autotests/codegen/context-addVar/expected.js index 980958d25..7bb4f085b 100644 --- a/test/autotests/codegen/context-addVar/expected.js +++ b/test/autotests/codegen/context-addVar/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { var foo = "Hello World"; @@ -8,4 +8,4 @@ function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/codegen/forEach/expected.js b/test/autotests/codegen/forEach/expected.js index e55b94092..d6d174f18 100644 --- a/test/autotests/codegen/forEach/expected.js +++ b/test/autotests/codegen/forEach/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_forEach = marko_helpers.f, @@ -12,4 +12,4 @@ function render(data, out) { }); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/codegen/forEachProps/expected.js b/test/autotests/codegen/forEachProps/expected.js index 12d8d0bf7..e6d850023 100644 --- a/test/autotests/codegen/forEachProps/expected.js +++ b/test/autotests/codegen/forEachProps/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_forEachProp = marko_helpers.fp; @@ -11,4 +11,4 @@ function render(data, out) { }); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/codegen/generate-exports/expected.js b/test/autotests/codegen/generate-exports/expected.js deleted file mode 100644 index 68b796c3a..000000000 --- a/test/autotests/codegen/generate-exports/expected.js +++ /dev/null @@ -1,11 +0,0 @@ -var template = require("marko/html").c(__filename); - -var component = require("./component"); - -var template = template; - -module.exports = require("marko-widgets").c(component, template); - -function render(data, out) {} - -template._ = render; diff --git a/test/autotests/codegen/generate-exports/index.js b/test/autotests/codegen/generate-exports/index.js deleted file mode 100644 index 1c15814bd..000000000 --- a/test/autotests/codegen/generate-exports/index.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -module.exports = function(builder, codegen) { - var templateRoot = builder.templateRoot([]); - - codegen.context.on('beforeGenerateCode:TemplateRoot', function(root) { - root.node.generateExports = function(template) { - return [ - builder.assignment( - builder.var('component'), - builder.require( - builder.literal('./component') - ) - ), - builder.assignment( - builder.var('template'), - template - ), - builder.assignment( - builder.memberExpression( - builder.identifier('module'), - builder.identifier('exports') - ), - builder.functionCall( - builder.memberExpression( - builder.require( - builder.literal('marko-widgets') - ), - builder.identifier('c') - ), - [ - builder.identifier('component'), - builder.identifier('template') - ] - ) - ) - ]; - }; - }); - - return templateRoot; -}; \ No newline at end of file diff --git a/test/autotests/codegen/marko-template/expected.js b/test/autotests/codegen/marko-template/expected.js index 4a3afea66..eb104464e 100644 --- a/test/autotests/codegen/marko-template/expected.js +++ b/test/autotests/codegen/marko-template/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_escapeXml = marko_helpers.x; @@ -23,4 +23,4 @@ function render(data, out) { } } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/codegen/meta-dependencies/expected.js b/test/autotests/codegen/meta-dependencies/expected.js index 32bb59f96..75c7fec23 100644 --- a/test/autotests/codegen/meta-dependencies/expected.js +++ b/test/autotests/codegen/meta-dependencies/expected.js @@ -1,14 +1,14 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; -template.meta = { +marko_template.meta = { deps: [ "./foo" ] diff --git a/test/autotests/codegen/templateRoot-prependChild/expected.js b/test/autotests/codegen/templateRoot-prependChild/expected.js index 823d1ed63..2616da3da 100644 --- a/test/autotests/codegen/templateRoot-prependChild/expected.js +++ b/test/autotests/codegen/templateRoot-prependChild/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { var foo = "bar"; @@ -8,4 +8,4 @@ function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/codegen/templateRoot/expected.js b/test/autotests/codegen/templateRoot/expected.js index 958dc69e5..4e48fde35 100644 --- a/test/autotests/codegen/templateRoot/expected.js +++ b/test/autotests/codegen/templateRoot/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { var foo = "bar"; @@ -8,4 +8,4 @@ function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/addNestedVariable/expected.js b/test/autotests/compiler/addNestedVariable/expected.js index 1373631e8..f372fd9b7 100644 --- a/test/autotests/compiler/addNestedVariable/expected.js +++ b/test/autotests/compiler/addNestedVariable/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_escapeXml = marko_helpers.x, @@ -17,4 +17,4 @@ function render(data, out) { }, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/attr-escape/expected.js b/test/autotests/compiler/attr-escape/expected.js index 93ef67d42..10efedbad 100644 --- a/test/autotests/compiler/attr-escape/expected.js +++ b/test/autotests/compiler/attr-escape/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_classAttr = marko_helpers.ca, @@ -23,4 +23,4 @@ function render(data, out) { " b\">"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/attr-placeholder-escapeXml/expected.js b/test/autotests/compiler/attr-placeholder-escapeXml/expected.js index 7caf79e96..0abf47304 100644 --- a/test/autotests/compiler/attr-placeholder-escapeXml/expected.js +++ b/test/autotests/compiler/attr-placeholder-escapeXml/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_escapeXmlAttr = marko_helpers.xa; @@ -13,4 +13,4 @@ function render(data, out) { var foo = "Hello " + data.name; } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/createNodeFromEl/expected.js b/test/autotests/compiler/createNodeFromEl/expected.js index b8d063872..2bfaa0263 100644 --- a/test/autotests/compiler/createNodeFromEl/expected.js +++ b/test/autotests/compiler/createNodeFromEl/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_loadTag = marko_helpers.t, @@ -20,4 +20,4 @@ function render(data, out) { }, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/custom-tag-body-function/expected.js b/test/autotests/compiler/custom-tag-body-function/expected.js index 6834c431c..5f30aa3d7 100644 --- a/test/autotests/compiler/custom-tag-body-function/expected.js +++ b/test/autotests/compiler/custom-tag-body-function/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_loadTag = marko_helpers.t, @@ -15,4 +15,4 @@ function render(data, out) { }, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/custom-tag-data/expected.js b/test/autotests/compiler/custom-tag-data/expected.js index 25658f3b1..6393ff7bc 100644 --- a/test/autotests/compiler/custom-tag-data/expected.js +++ b/test/autotests/compiler/custom-tag-data/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_loadTag = marko_helpers.t, @@ -26,4 +26,4 @@ function render(data, out) { }), out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/custom-tag-import-var/expected.js b/test/autotests/compiler/custom-tag-import-var/expected.js index c19387baa..3bbf25a17 100644 --- a/test/autotests/compiler/custom-tag-import-var/expected.js +++ b/test/autotests/compiler/custom-tag-import-var/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_loadTag = marko_helpers.t, @@ -17,4 +17,4 @@ function render(data, out) { }, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/custom-tag-template/expected.js b/test/autotests/compiler/custom-tag-template/expected.js index 7c64de69c..c60b86a68 100644 --- a/test/autotests/compiler/custom-tag-template/expected.js +++ b/test/autotests/compiler/custom-tag-template/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_loadTemplate = marko_helpers.l, @@ -14,4 +14,4 @@ function render(data, out) { }, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/custom-tag/expected.js b/test/autotests/compiler/custom-tag/expected.js index 95e54e008..df0f58587 100644 --- a/test/autotests/compiler/custom-tag/expected.js +++ b/test/autotests/compiler/custom-tag/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_loadTag = marko_helpers.t, @@ -12,4 +12,4 @@ function render(data, out) { }, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/entities/expected.js b/test/autotests/compiler/entities/expected.js index b42b8d586..cd9e328cc 100644 --- a/test/autotests/compiler/entities/expected.js +++ b/test/autotests/compiler/entities/expected.js @@ -1,9 +1,9 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { out.w("Hello John & Suzy Invalid Entity: &b ; Valid Numeric Entity: " Valid Hexadecimal Entity: ¢"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/for-array/expected.js b/test/autotests/compiler/for-array/expected.js index 06498b47b..cc69551ed 100644 --- a/test/autotests/compiler/for-array/expected.js +++ b/test/autotests/compiler/for-array/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_escapeXml = marko_helpers.x; @@ -22,4 +22,4 @@ function render(data, out) { } } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/hello-dynamic/expected.js b/test/autotests/compiler/hello-dynamic/expected.js index 5a776a88b..d63db98fc 100644 --- a/test/autotests/compiler/hello-dynamic/expected.js +++ b/test/autotests/compiler/hello-dynamic/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_escapeXml = marko_helpers.x, @@ -16,4 +16,4 @@ function render(data, out) { "!"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/import-tag/expected.js b/test/autotests/compiler/import-tag/expected.js index ea8cdfd5d..06e64546a 100644 --- a/test/autotests/compiler/import-tag/expected.js +++ b/test/autotests/compiler/import-tag/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var bar = require("./bar"), foo = bar.f; @@ -9,4 +9,4 @@ require("./foo"); function render(data, out) {} -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/importModule/expected.js b/test/autotests/compiler/importModule/expected.js index 4a4d082ff..ec98c5572 100644 --- a/test/autotests/compiler/importModule/expected.js +++ b/test/autotests/compiler/importModule/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var foo = require("./foo"); @@ -8,4 +8,4 @@ function render(data, out) { foo(); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/include/expected.js b/test/autotests/compiler/include/expected.js index d99395d8f..ecb090c31 100644 --- a/test/autotests/compiler/include/expected.js +++ b/test/autotests/compiler/include/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_loadTemplate = marko_helpers.l, @@ -14,4 +14,4 @@ function render(data, out) { }, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/invoke-if/expected.js b/test/autotests/compiler/invoke-if/expected.js index 060f5a022..8e9804d6f 100644 --- a/test/autotests/compiler/invoke-if/expected.js +++ b/test/autotests/compiler/invoke-if/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { if (true) { @@ -8,4 +8,4 @@ function render(data, out) { } } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/invoke/expected.js b/test/autotests/compiler/invoke/expected.js index 7080883c3..af5822319 100644 --- a/test/autotests/compiler/invoke/expected.js +++ b/test/autotests/compiler/invoke/expected.js @@ -1,9 +1,9 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { data.renderBody(out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/macros/expected.js b/test/autotests/compiler/macros/expected.js index 6e3f28425..605fc1998 100644 --- a/test/autotests/compiler/macros/expected.js +++ b/test/autotests/compiler/macros/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_escapeXml = marko_helpers.x, @@ -30,4 +30,4 @@ function render(data, out) { macro_renderTree(data.node, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/marko-init/expected.js b/test/autotests/compiler/marko-init/expected.js index e3aa80701..db047da2c 100644 --- a/test/autotests/compiler/marko-init/expected.js +++ b/test/autotests/compiler/marko-init/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_escapeXml = marko_helpers.x; @@ -14,4 +14,4 @@ function render(data, out) { "!"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/nested-tag-shorthand-simple-conditional/expected.js b/test/autotests/compiler/nested-tag-shorthand-simple-conditional/expected.js index 6554d1df6..c1f959597 100644 --- a/test/autotests/compiler/nested-tag-shorthand-simple-conditional/expected.js +++ b/test/autotests/compiler/nested-tag-shorthand-simple-conditional/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_loadTemplate = marko_helpers.l, @@ -18,4 +18,4 @@ function render(data, out) { }, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/nested-tags/expected.js b/test/autotests/compiler/nested-tags/expected.js index 211b8abb2..c7484a708 100644 --- a/test/autotests/compiler/nested-tags/expected.js +++ b/test/autotests/compiler/nested-tags/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_loadTag = marko_helpers.t, @@ -24,4 +24,4 @@ function render(data, out) { }, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/replaceWith/expected.js b/test/autotests/compiler/replaceWith/expected.js index dfa5369fe..120c9477f 100644 --- a/test/autotests/compiler/replaceWith/expected.js +++ b/test/autotests/compiler/replaceWith/expected.js @@ -1,9 +1,9 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/simple/expected.js b/test/autotests/compiler/simple/expected.js index d8305c3ed..fd14e1938 100644 --- a/test/autotests/compiler/simple/expected.js +++ b/test/autotests/compiler/simple/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_escapeXml = marko_helpers.x, @@ -40,4 +40,4 @@ function render(data, out) { } } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/compiler/static/expected.js b/test/autotests/compiler/static/expected.js index e9869b7e4..33b093279 100644 --- a/test/autotests/compiler/static/expected.js +++ b/test/autotests/compiler/static/expected.js @@ -1,9 +1,9 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { out.w("Hello John"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/hot-reload/component-to-template/.gitignore b/test/autotests/hot-reload/component-to-template/.gitignore new file mode 100644 index 000000000..102d344f2 --- /dev/null +++ b/test/autotests/hot-reload/component-to-template/.gitignore @@ -0,0 +1 @@ +template.temp.marko \ No newline at end of file diff --git a/test/autotests/hot-reload/component-to-template/a/component.js b/test/autotests/hot-reload/component-to-template/a/component.js new file mode 100644 index 000000000..1e70b9676 --- /dev/null +++ b/test/autotests/hot-reload/component-to-template/a/component.js @@ -0,0 +1,7 @@ +module.exports = { + onInput(input) { + this.state = { + name: input.name + }; + } +}; \ No newline at end of file diff --git a/test/autotests/hot-reload/component-to-template/a/index.marko b/test/autotests/hot-reload/component-to-template/a/index.marko new file mode 100644 index 000000000..c5e40bf1e --- /dev/null +++ b/test/autotests/hot-reload/component-to-template/a/index.marko @@ -0,0 +1,3 @@ +
+ Hello ${state.name} +
\ No newline at end of file diff --git a/test/autotests/hot-reload/component-to-template/b/index.marko b/test/autotests/hot-reload/component-to-template/b/index.marko new file mode 100644 index 000000000..60ca8defd --- /dev/null +++ b/test/autotests/hot-reload/component-to-template/b/index.marko @@ -0,0 +1,3 @@ +
+ Hello ${data.name} +
\ No newline at end of file diff --git a/test/autotests/hot-reload/component-to-template/temp/index.marko b/test/autotests/hot-reload/component-to-template/temp/index.marko new file mode 100644 index 000000000..60ca8defd --- /dev/null +++ b/test/autotests/hot-reload/component-to-template/temp/index.marko @@ -0,0 +1,3 @@ +
+ Hello ${data.name} +
\ No newline at end of file diff --git a/test/autotests/hot-reload/component-to-template/test.js b/test/autotests/hot-reload/component-to-template/test.js new file mode 100644 index 000000000..81673ef48 --- /dev/null +++ b/test/autotests/hot-reload/component-to-template/test.js @@ -0,0 +1,45 @@ +var fs = require('fs'); +var nodePath = require('path'); + +var tempDir = nodePath.join(__dirname, 'temp'); + +function copyFiles(dir) { + var files = fs.readdirSync(dir); + files.forEach((file) => { + var src = fs.readFileSync(nodePath.join(dir, file)); + fs.writeFileSync(nodePath.join(tempDir, file), src); + }); +} + +exports.check = function(marko, hotReload, expect) { + try { + fs.mkdirSync(nodePath.join(__dirname, 'temp')); + } catch(e) {} + + try { + fs.unlinkSync(nodePath.join(__dirname, 'temp/component.js')); + } catch(e) {} + + try { + fs.unlinkSync(nodePath.join(__dirname, 'temp/index.marko')); + } catch(e) {} + + try { + fs.unlinkSync(nodePath.join(__dirname, 'temp/index.marko.js')); + } catch(e) {} + + var tempTemplatePath = nodePath.join(__dirname, 'temp/index.marko'); + + copyFiles(nodePath.join(__dirname, 'a')); + var component = require(tempTemplatePath); + expect(component.renderToString({ name: 'Frank' })).to.equal('
Hello Frank
'); + + try { + fs.unlinkSync(nodePath.join(__dirname, 'temp/component.js')); + } catch(e) {} + + hotReload.handleFileModified(tempTemplatePath); + + 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-to-component/.gitignore b/test/autotests/hot-reload/template-to-component/.gitignore new file mode 100644 index 000000000..102d344f2 --- /dev/null +++ b/test/autotests/hot-reload/template-to-component/.gitignore @@ -0,0 +1 @@ +template.temp.marko \ No newline at end of file diff --git a/test/autotests/hot-reload/template-to-component/a/index.marko b/test/autotests/hot-reload/template-to-component/a/index.marko new file mode 100644 index 000000000..55d3da1e0 --- /dev/null +++ b/test/autotests/hot-reload/template-to-component/a/index.marko @@ -0,0 +1,3 @@ +
+ Hello ${data.name} +
\ No newline at end of file diff --git a/test/autotests/hot-reload/template-to-component/b/component.js b/test/autotests/hot-reload/template-to-component/b/component.js new file mode 100644 index 000000000..1e70b9676 --- /dev/null +++ b/test/autotests/hot-reload/template-to-component/b/component.js @@ -0,0 +1,7 @@ +module.exports = { + onInput(input) { + this.state = { + name: input.name + }; + } +}; \ No newline at end of file diff --git a/test/autotests/hot-reload/template-to-component/b/index.marko b/test/autotests/hot-reload/template-to-component/b/index.marko new file mode 100644 index 000000000..701678aff --- /dev/null +++ b/test/autotests/hot-reload/template-to-component/b/index.marko @@ -0,0 +1,3 @@ +
+ Hello ${state.name} +
\ No newline at end of file diff --git a/test/autotests/hot-reload/template-to-component/temp/component.js b/test/autotests/hot-reload/template-to-component/temp/component.js new file mode 100644 index 000000000..1e70b9676 --- /dev/null +++ b/test/autotests/hot-reload/template-to-component/temp/component.js @@ -0,0 +1,7 @@ +module.exports = { + onInput(input) { + this.state = { + name: input.name + }; + } +}; \ No newline at end of file diff --git a/test/autotests/hot-reload/template-to-component/temp/index.marko b/test/autotests/hot-reload/template-to-component/temp/index.marko new file mode 100644 index 000000000..701678aff --- /dev/null +++ b/test/autotests/hot-reload/template-to-component/temp/index.marko @@ -0,0 +1,3 @@ +
+ Hello ${state.name} +
\ No newline at end of file diff --git a/test/autotests/hot-reload/template-to-component/test.js b/test/autotests/hot-reload/template-to-component/test.js new file mode 100644 index 000000000..d34ca8dfa --- /dev/null +++ b/test/autotests/hot-reload/template-to-component/test.js @@ -0,0 +1,41 @@ +var fs = require('fs'); +var nodePath = require('path'); + +var tempDir = nodePath.join(__dirname, 'temp'); + +function copyFiles(dir) { + var files = fs.readdirSync(dir); + files.forEach((file) => { + var src = fs.readFileSync(nodePath.join(dir, file)); + fs.writeFileSync(nodePath.join(tempDir, file), src); + }); +} + +exports.check = function(marko, hotReload, expect) { + try { + fs.mkdirSync(nodePath.join(__dirname, 'temp')); + } catch(e) {} + + try { + fs.unlinkSync(nodePath.join(__dirname, 'temp/component.js')); + } catch(e) {} + + try { + fs.unlinkSync(nodePath.join(__dirname, 'temp/index.marko')); + } catch(e) {} + + try { + fs.unlinkSync(nodePath.join(__dirname, 'temp/index.marko.js')); + } catch(e) {} + + var tempTemplatePath = nodePath.join(__dirname, 'temp/index.marko'); + + copyFiles(nodePath.join(__dirname, 'a')); + var component = require(tempTemplatePath); + expect(component.renderSync({ name: 'Frank' }).toString()).to.equal('
Hello Frank
'); + + hotReload.handleFileModified(tempTemplatePath); + + copyFiles(nodePath.join(__dirname, 'b')); + expect(component.renderSync({ name: 'Jane' }).toString()).to.equal('
Hello Jane
'); +}; \ No newline at end of file diff --git a/test/autotests/taglib-lookup/forEachAttribute/expected.json b/test/autotests/taglib-lookup/forEachAttribute/expected.json index 53db80169..7c55df239 100644 --- a/test/autotests/taglib-lookup/forEachAttribute/expected.json +++ b/test/autotests/taglib-lookup/forEachAttribute/expected.json @@ -10,6 +10,7 @@ "for", "include", "while", + "$w", "w-bind", "w-scope", "w-config", @@ -29,4 +30,4 @@ "w-preserve-attrs", "on*", "w-on*" -] +] \ No newline at end of file diff --git a/test/autotests/vdom-compiler/attr-class-expression/expected.js b/test/autotests/vdom-compiler/attr-class-expression/expected.js index 25b2f687c..08dc2049f 100644 --- a/test/autotests/vdom-compiler/attr-class-expression/expected.js +++ b/test/autotests/vdom-compiler/attr-class-expression/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/vdom").c(__filename); +var marko_template = require("marko/vdom").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/vdom/helpers"), marko_classList = marko_helpers.cl, @@ -18,4 +18,4 @@ function render(data, out) { .t("!"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/vdom-compiler/attrs-dynamic-object-literal/expected.js b/test/autotests/vdom-compiler/attrs-dynamic-object-literal/expected.js index c56964c16..d96e72de8 100644 --- a/test/autotests/vdom-compiler/attrs-dynamic-object-literal/expected.js +++ b/test/autotests/vdom-compiler/attrs-dynamic-object-literal/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/vdom").c(__filename); +var marko_template = require("marko/vdom").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { out.e("div", { @@ -12,4 +12,4 @@ function render(data, out) { .t("!"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/vdom-compiler/attrs-dynamic/expected.js b/test/autotests/vdom-compiler/attrs-dynamic/expected.js index 00f9a7e5b..4867ad777 100644 --- a/test/autotests/vdom-compiler/attrs-dynamic/expected.js +++ b/test/autotests/vdom-compiler/attrs-dynamic/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/vdom").c(__filename); +var marko_template = require("marko/vdom").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { var attrs = { @@ -14,4 +14,4 @@ function render(data, out) { .t("!"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/vdom-compiler/custom-tag/expected.js b/test/autotests/vdom-compiler/custom-tag/expected.js index ecfe8c17f..c6569ec18 100644 --- a/test/autotests/vdom-compiler/custom-tag/expected.js +++ b/test/autotests/vdom-compiler/custom-tag/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/vdom").c(__filename); +var marko_template = require("marko/vdom").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/vdom/helpers"), marko_loadTag = marko_helpers.t, @@ -26,4 +26,4 @@ function render(data, out) { out.ee(); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/vdom-compiler/dynamic-body-text/expected.js b/test/autotests/vdom-compiler/dynamic-body-text/expected.js index 70ee42565..b5857ce0d 100644 --- a/test/autotests/vdom-compiler/dynamic-body-text/expected.js +++ b/test/autotests/vdom-compiler/dynamic-body-text/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/vdom").c(__filename); +var marko_template = require("marko/vdom").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_attrs0 = { "class": "foo" @@ -13,4 +13,4 @@ function render(data, out) { .t("!"); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/vdom-compiler/no-escape/expected.js b/test/autotests/vdom-compiler/no-escape/expected.js index abb54f3dd..5c3cda4aa 100644 --- a/test/autotests/vdom-compiler/no-escape/expected.js +++ b/test/autotests/vdom-compiler/no-escape/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/vdom").c(__filename); +var marko_template = require("marko/vdom").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { out.t("Hello "); @@ -12,4 +12,4 @@ function render(data, out) { out.h(message); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/vdom-compiler/simple/expected.js b/test/autotests/vdom-compiler/simple/expected.js index 1fa02f3b8..70747887c 100644 --- a/test/autotests/vdom-compiler/simple/expected.js +++ b/test/autotests/vdom-compiler/simple/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/vdom").c(__filename); +var marko_template = require("marko/vdom").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/vdom/helpers"), marko_forEach = marko_helpers.f, @@ -30,4 +30,4 @@ function render(data, out) { } } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/vdom-compiler/static-element-nested/expected.js b/test/autotests/vdom-compiler/static-element-nested/expected.js index 71ba18cd3..e93890d63 100644 --- a/test/autotests/vdom-compiler/static-element-nested/expected.js +++ b/test/autotests/vdom-compiler/static-element-nested/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/vdom").c(__filename); +var marko_template = require("marko/vdom").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/vdom/helpers"), marko_createElement = marko_helpers.e, @@ -21,4 +21,4 @@ function render(data, out) { .n(marko_node0); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/vdom-compiler/static-element-root/expected.js b/test/autotests/vdom-compiler/static-element-root/expected.js index 3c85149f6..6de6fcb1f 100644 --- a/test/autotests/vdom-compiler/static-element-root/expected.js +++ b/test/autotests/vdom-compiler/static-element-root/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/vdom").c(__filename); +var marko_template = require("marko/vdom").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/vdom/helpers"), marko_createElement = marko_helpers.e, @@ -16,4 +16,4 @@ function render(data, out) { out.n(marko_node0); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/vdom-compiler/tag-body/expected.js b/test/autotests/vdom-compiler/tag-body/expected.js index eb941a6b0..198217117 100644 --- a/test/autotests/vdom-compiler/tag-body/expected.js +++ b/test/autotests/vdom-compiler/tag-body/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/vdom").c(__filename); +var marko_template = require("marko/vdom").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/vdom/helpers"), marko_loadTag = marko_helpers.t, @@ -15,4 +15,4 @@ function render(data, out) { }, out); } -template._ = render; +marko_template._ = render; diff --git a/test/autotests/widgets-browser/sanity-check-custom-event/components/app-foo/component.js b/test/autotests/widgets-browser/sanity-check-custom-event/components/app-foo/component.js new file mode 100644 index 000000000..d9143bae8 --- /dev/null +++ b/test/autotests/widgets-browser/sanity-check-custom-event/components/app-foo/component.js @@ -0,0 +1,5 @@ +module.exports = { + emitTestEvent: function() { + this.emit('test', 'abc', '123'); + } +}; \ No newline at end of file diff --git a/test/autotests/widgets-browser/sanity-check-custom-event/components/app-foo/index.marko b/test/autotests/widgets-browser/sanity-check-custom-event/components/app-foo/index.marko new file mode 100644 index 000000000..cc15524c0 --- /dev/null +++ b/test/autotests/widgets-browser/sanity-check-custom-event/components/app-foo/index.marko @@ -0,0 +1,3 @@ + + [app-foo] + \ No newline at end of file diff --git a/test/autotests/widgets-browser/sanity-check-custom-event/index.marko b/test/autotests/widgets-browser/sanity-check-custom-event/index.marko new file mode 100644 index 000000000..1c2417deb --- /dev/null +++ b/test/autotests/widgets-browser/sanity-check-custom-event/index.marko @@ -0,0 +1,16 @@ +
+ +
+ + \ No newline at end of file diff --git a/test/autotests/widgets-browser/sanity-check-custom-event/test.js b/test/autotests/widgets-browser/sanity-check-custom-event/test.js new file mode 100644 index 000000000..984ae262b --- /dev/null +++ b/test/autotests/widgets-browser/sanity-check-custom-event/test.js @@ -0,0 +1,11 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + + var widget = helpers.mount(require('./index.marko'), { name: 'Frank' }); + + expect(widget.fooEvent.length).to.equal(3); + expect(widget.fooEvent[0]).to.equal('abc'); + expect(widget.fooEvent[1]).to.equal('123'); + expect(widget.fooEvent[2]).to.equal(widget.fooWidget); +}; \ No newline at end of file diff --git a/test/autotests/widgets-browser/sanity-check-inline/index.marko b/test/autotests/widgets-browser/sanity-check-inline/index.marko index 1840ad485..a59f8bfbc 100644 --- a/test/autotests/widgets-browser/sanity-check-inline/index.marko +++ b/test/autotests/widgets-browser/sanity-check-inline/index.marko @@ -1,5 +1,5 @@
- Hello ${data.name}! + Hello ${state.name}!
+ + + \ No newline at end of file diff --git a/test/autotests/widgets-browser/sanity-check-ref/index.marko b/test/autotests/widgets-browser/sanity-check-ref/index.marko new file mode 100644 index 000000000..3784a7550 --- /dev/null +++ b/test/autotests/widgets-browser/sanity-check-ref/index.marko @@ -0,0 +1,12 @@ + + + + + eBay + \ No newline at end of file diff --git a/test/autotests/widgets-browser/sanity-check-ref/test.js b/test/autotests/widgets-browser/sanity-check-ref/test.js new file mode 100644 index 000000000..6c9a73a23 --- /dev/null +++ b/test/autotests/widgets-browser/sanity-check-ref/test.js @@ -0,0 +1,11 @@ +var expect = require('chai').expect; + +module.exports = function(helpers) { + var widget = helpers.mount(require('./index'), { }); + + var fooWidget = widget.getWidget('foo'); + expect(fooWidget.el.className).to.equal('foo'); + + var link = widget.getEl('link'); + expect(link.nodeName).to.equal('A'); +}; \ No newline at end of file diff --git a/test/autotests/widgets-browser/sanity-check-single-file-component/index.marko b/test/autotests/widgets-browser/sanity-check-single-file-component/index.marko index 29531b824..fb98792d5 100644 --- a/test/autotests/widgets-browser/sanity-check-single-file-component/index.marko +++ b/test/autotests/widgets-browser/sanity-check-single-file-component/index.marko @@ -12,5 +12,5 @@
- Hello ${data.name}! + Hello ${state.name}!
\ No newline at end of file diff --git a/test/autotests/widgets-browser/sanity-check-template-entry/component.js b/test/autotests/widgets-browser/sanity-check-template-entry/component.js index 06fac67b7..e1fa6b833 100644 --- a/test/autotests/widgets-browser/sanity-check-template-entry/component.js +++ b/test/autotests/widgets-browser/sanity-check-template-entry/component.js @@ -2,7 +2,7 @@ module.exports = { onInput: function(input) { this.state = { name: input.name - } + }; }, setName: function(newName) { this.state.name = newName; diff --git a/test/autotests/widgets-browser/sanity-check-template-entry/index.marko b/test/autotests/widgets-browser/sanity-check-template-entry/index.marko index 21ee43c6e..858c8431e 100644 --- a/test/autotests/widgets-browser/sanity-check-template-entry/index.marko +++ b/test/autotests/widgets-browser/sanity-check-template-entry/index.marko @@ -1,3 +1,3 @@
- Hello ${data.name}! + Hello ${state.name}!
diff --git a/test/autotests/widgets-compilation/bind-component/expected.js b/test/autotests/widgets-compilation/bind-component/expected.js index 8edfae176..8584b319c 100644 --- a/test/autotests/widgets-compilation/bind-component/expected.js +++ b/test/autotests/widgets-compilation/bind-component/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_widgets = require("marko/widgets"), marko_registerWidget = marko_widgets.registerWidget, @@ -8,23 +8,14 @@ var marko_widgets = require("marko/widgets"), return require("./"); }), marko_helpers = require("marko/runtime/html/helpers"), - marko_attr = marko_helpers.a, - marko_loadTag = marko_helpers.t, - _widget_tag = marko_loadTag(require("marko/widgets/taglib/widget-tag")); + marko_attr = marko_helpers.a; -function render(data, out) { - _widget_tag({ - type: marko_widgetType, - _cfg: data.widgetConfig, - _state: data.widgetState, - _props: data.widgetProps, - _body: data.widgetBody, - renderBody: function renderBody(out, widget, state) { - out.w(""); - } - }, out); +function render(data, out, widget, state) { + out.w(""); } -template._ = render; +marko_template._ = marko_widgets.r(render, { + type: marko_widgetType + }); diff --git a/test/autotests/widgets-compilation/bind-widget/expected.js b/test/autotests/widgets-compilation/bind-widget/expected.js index 16a47401d..75708b551 100644 --- a/test/autotests/widgets-compilation/bind-widget/expected.js +++ b/test/autotests/widgets-compilation/bind-widget/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_widgets = require("marko/widgets"), marko_registerWidget = marko_widgets.registerWidget, @@ -8,23 +8,14 @@ var marko_widgets = require("marko/widgets"), return require("./widget"); }), marko_helpers = require("marko/runtime/html/helpers"), - marko_attr = marko_helpers.a, - marko_loadTag = marko_helpers.t, - _widget_tag = marko_loadTag(require("marko/widgets/taglib/widget-tag")); + marko_attr = marko_helpers.a; -function render(data, out) { - _widget_tag({ - type: marko_widgetType, - _cfg: data.widgetConfig, - _state: data.widgetState, - _props: data.widgetProps, - _body: data.widgetBody, - renderBody: function renderBody(out, widget, state) { - out.w(""); - } - }, out); +function render(data, out, widget, state) { + out.w(""); } -template._ = render; +marko_template._ = marko_widgets.r(render, { + type: marko_widgetType + }); diff --git a/test/autotests/widgets-compilation/component-include-attr/expected.js b/test/autotests/widgets-compilation/component-include-attr/expected.js index 526d03da5..7e412eafb 100644 --- a/test/autotests/widgets-compilation/component-include-attr/expected.js +++ b/test/autotests/widgets-compilation/component-include-attr/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_widgets = require("marko/widgets"), marko_registerWidget = marko_widgets.registerWidget, @@ -10,33 +10,25 @@ var marko_widgets = require("marko/widgets"), marko_helpers = require("marko/runtime/html/helpers"), marko_loadTag = marko_helpers.t, include_tag = marko_loadTag(require("marko/widgets/taglib/include-tag")), - marko_attr = marko_helpers.a, - _widget_tag = marko_loadTag(require("marko/widgets/taglib/widget-tag")); + marko_attr = marko_helpers.a; -function render(data, out) { - _widget_tag({ - type: marko_widgetType, - body: 0, - _cfg: data.widgetConfig, - _state: data.widgetState, - _props: data.widgetProps, - _body: data.widgetBody, - renderBody: function renderBody(out, widget, state) { - out.w("

Header

"); +function render(data, out, widget, state) { + out.w("

Header

"); - include_tag({ - _target: data.widgetBody, - _widgetId: widget.elId(0), - _arg: widget - }, out); - - out.w(""); - } + include_tag({ + _target: widget.body, + _widgetId: widget.elId(0), + _arg: widget }, out); + + out.w(""); } -template._ = render; +marko_template._ = marko_widgets.r(render, { + type: marko_widgetType, + body: 0 + }); diff --git a/test/autotests/widgets-compilation/component-inline-multiple-roots/expected.js b/test/autotests/widgets-compilation/component-inline-multiple-roots/expected.js new file mode 100644 index 000000000..0512a6b16 --- /dev/null +++ b/test/autotests/widgets-compilation/component-inline-multiple-roots/expected.js @@ -0,0 +1,36 @@ +var marko_template = require("marko/html").t(__filename); + +module.exports = marko_template; + +var marko_component = (function() { + var marko_component; + + marko_component = {}; + + return marko_component; + })(), + marko_widgets = require("marko/widgets"), + marko_registerWidget = marko_widgets.registerWidget, + marko_widgetType = marko_registerWidget("/marko-test$1.0.0/autotests/widgets-compilation/component-inline-multiple-roots/index.marko", function() { + return module.exports; + }), + marko_helpers = require("marko/runtime/html/helpers"), + marko_attr = marko_helpers.a; + +function render(data, out, widget, state) { + out.w("AB"); +} + +marko_template._ = marko_widgets.r(render, { + type: marko_widgetType, + roots: [ + "_r0", + "_r1" + ] + }, marko_component); + +marko_template.Widget = marko_widgets.w(marko_component, marko_template._); diff --git a/test/autotests/widgets-compilation/component-inline-multiple-roots/index.marko b/test/autotests/widgets-compilation/component-inline-multiple-roots/index.marko new file mode 100644 index 000000000..dc659d16e --- /dev/null +++ b/test/autotests/widgets-compilation/component-inline-multiple-roots/index.marko @@ -0,0 +1,10 @@ + + +
+ A +
+ + B + diff --git a/test/autotests/widgets-compilation/component-inline/expected.js b/test/autotests/widgets-compilation/component-inline/expected.js index 672cae61b..ae239f1f7 100644 --- a/test/autotests/widgets-compilation/component-inline/expected.js +++ b/test/autotests/widgets-compilation/component-inline/expected.js @@ -1,39 +1,30 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -var component = (function() { - var marko_component; +module.exports = marko_template; - marko_component = {}; +var marko_component = (function() { + var marko_component; - return marko_component; -})(); + marko_component = {}; -var marko_widgets = require("marko/widgets"); - -module.exports = marko_widgets.c(component, template); - -var marko_registerWidget = marko_widgets.registerWidget, + return marko_component; + })(), + marko_widgets = require("marko/widgets"), + marko_registerWidget = marko_widgets.registerWidget, marko_widgetType = marko_registerWidget("/marko-test$1.0.0/autotests/widgets-compilation/component-inline/index.marko", function() { return module.exports; }), marko_helpers = require("marko/runtime/html/helpers"), - marko_attr = marko_helpers.a, - marko_loadTag = marko_helpers.t, - _widget_tag = marko_loadTag(require("marko/widgets/taglib/widget-tag")); + marko_attr = marko_helpers.a; -function render(data, out) { - _widget_tag({ - type: marko_widgetType, - _cfg: data.widgetConfig, - _state: data.widgetState, - _props: data.widgetProps, - _body: data.widgetBody, - renderBody: function renderBody(out, widget, state) { - out.w(""); - } - }, out); +function render(data, out, widget, state) { + out.w(""); } -template._ = render; +marko_template._ = marko_widgets.r(render, { + type: marko_widgetType + }, marko_component); + +marko_template.Widget = marko_widgets.w(marko_component, marko_template._); diff --git a/test/autotests/widgets-compilation/component-template-entry-split/expected.js b/test/autotests/widgets-compilation/component-template-entry-split/expected.js index a27dd2862..f9986b978 100644 --- a/test/autotests/widgets-compilation/component-template-entry-split/expected.js +++ b/test/autotests/widgets-compilation/component-template-entry-split/expected.js @@ -1,33 +1,22 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -var renderer = require("./renderer"); +module.exports = marko_template; -var marko_widgets = require("marko/widgets"); - -module.exports = marko_widgets.r(renderer, template); - -var marko_registerWidget = marko_widgets.registerWidget, +var marko_component = require("./renderer"), + marko_widgets = require("marko/widgets"), + marko_registerWidget = marko_widgets.registerWidget, marko_widgetType = marko_registerWidget("/marko-test$1.0.0/autotests/widgets-compilation/component-template-entry-split/widget", function() { return require("./widget"); }), marko_helpers = require("marko/runtime/html/helpers"), - marko_attr = marko_helpers.a, - marko_loadTag = marko_helpers.t, - _widget_tag = marko_loadTag(require("marko/widgets/taglib/widget-tag")); + marko_attr = marko_helpers.a; -function render(data, out) { - _widget_tag({ - type: marko_widgetType, - _cfg: data.widgetConfig, - _state: data.widgetState, - _props: data.widgetProps, - _body: data.widgetBody, - renderBody: function renderBody(out, widget, state) { - out.w(""); - } - }, out); +function render(data, out, widget, state) { + out.w(""); } -template._ = render; +marko_template._ = marko_widgets.r(render, { + type: marko_widgetType + }, marko_component); diff --git a/test/autotests/widgets-compilation/component-template-entry/expected.js b/test/autotests/widgets-compilation/component-template-entry/expected.js index a51901446..e2b127640 100644 --- a/test/autotests/widgets-compilation/component-template-entry/expected.js +++ b/test/autotests/widgets-compilation/component-template-entry/expected.js @@ -1,33 +1,24 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -var component = require("./component"); +module.exports = marko_template; -var marko_widgets = require("marko/widgets"); - -module.exports = marko_widgets.c(component, template); - -var marko_registerWidget = marko_widgets.registerWidget, +var marko_component = require("./component"), + marko_widgets = require("marko/widgets"), + marko_registerWidget = marko_widgets.registerWidget, marko_widgetType = marko_registerWidget("/marko-test$1.0.0/autotests/widgets-compilation/component-template-entry/index.marko", function() { return module.exports; }), marko_helpers = require("marko/runtime/html/helpers"), - marko_attr = marko_helpers.a, - marko_loadTag = marko_helpers.t, - _widget_tag = marko_loadTag(require("marko/widgets/taglib/widget-tag")); + marko_attr = marko_helpers.a; -function render(data, out) { - _widget_tag({ - type: marko_widgetType, - _cfg: data.widgetConfig, - _state: data.widgetState, - _props: data.widgetProps, - _body: data.widgetBody, - renderBody: function renderBody(out, widget, state) { - out.w(""); - } - }, out); +function render(data, out, widget, state) { + out.w(""); } -template._ = render; +marko_template._ = marko_widgets.r(render, { + type: marko_widgetType + }, marko_component); + +marko_template.Widget = marko_widgets.w(marko_component, marko_template._); diff --git a/test/autotests/widgets-compilation/ref/components/app-foo/index.marko b/test/autotests/widgets-compilation/ref/components/app-foo/index.marko new file mode 100644 index 000000000..025abeca1 --- /dev/null +++ b/test/autotests/widgets-compilation/ref/components/app-foo/index.marko @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/test/autotests/widgets-compilation/ref/expected.js b/test/autotests/widgets-compilation/ref/expected.js new file mode 100644 index 000000000..5dfaa9fa1 --- /dev/null +++ b/test/autotests/widgets-compilation/ref/expected.js @@ -0,0 +1,48 @@ +var marko_template = require("marko/html").t(__filename); + +module.exports = marko_template; + +var marko_component = (function() { + var marko_component; + + marko_component = { + onMount: function () { + } + }; + + return marko_component; + })(), + marko_widgets = require("marko/widgets"), + marko_registerWidget = marko_widgets.registerWidget, + marko_widgetType = marko_registerWidget("/marko-test$1.0.0/autotests/widgets-compilation/ref/index.marko", function() { + return module.exports; + }), + marko_helpers = require("marko/runtime/html/helpers"), + marko_loadTemplate = marko_helpers.l, + app_foo_template = marko_loadTemplate(require.resolve("./components/app-foo")), + marko_loadTag = marko_helpers.t, + app_foo_tag = marko_loadTag(app_foo_template), + marko_attr = marko_helpers.a; + +function render(data, out, widget, state) { + out.w("
"); + + app_foo_tag({ + $w: [ + widget, + "foo" + ] + }, out); + + out.w("eBay
"); +} + +marko_template._ = marko_widgets.r(render, { + type: marko_widgetType + }, marko_component); + +marko_template.Widget = marko_widgets.w(marko_component, marko_template._); diff --git a/test/autotests/widgets-compilation/ref/index.marko b/test/autotests/widgets-compilation/ref/index.marko new file mode 100644 index 000000000..3784a7550 --- /dev/null +++ b/test/autotests/widgets-compilation/ref/index.marko @@ -0,0 +1,12 @@ + + + + + eBay + \ No newline at end of file diff --git a/test/autotests/widgets-compilation/style-in-directory/expected.js b/test/autotests/widgets-compilation/style-in-directory/expected.js index 4ec95ed46..2acc9b2bb 100644 --- a/test/autotests/widgets-compilation/style-in-directory/expected.js +++ b/test/autotests/widgets-compilation/style-in-directory/expected.js @@ -1,14 +1,14 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; -template.meta = { +marko_template.meta = { deps: [ "./style.css" ] diff --git a/test/autotests/widgets-compilation/top-level-inline-style/expected.js b/test/autotests/widgets-compilation/top-level-inline-style/expected.js index 26b4024da..caca27c91 100644 --- a/test/autotests/widgets-compilation/top-level-inline-style/expected.js +++ b/test/autotests/widgets-compilation/top-level-inline-style/expected.js @@ -1,14 +1,14 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; function render(data, out) { out.w("
"); } -template._ = render; +marko_template._ = render; -template.meta = { +marko_template.meta = { deps: [ { type: "css", diff --git a/test/autotests/widgets-compilation/widget-types/expected.js b/test/autotests/widgets-compilation/widget-types/expected.js index 7addc8565..1bc7f4e1a 100644 --- a/test/autotests/widgets-compilation/widget-types/expected.js +++ b/test/autotests/widgets-compilation/widget-types/expected.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_widgets = require("marko/widgets"), marko_registerWidget = marko_widgets.registerWidget, @@ -13,25 +13,14 @@ var marko_widgets = require("marko/widgets"), }) }, marko_helpers = require("marko/runtime/html/helpers"), - marko_attr = marko_helpers.a, - marko_loadTag = marko_helpers.t, - _widget_tag = marko_loadTag(require("marko/widgets/taglib/widget-tag")); + marko_attr = marko_helpers.a; -function render(data, out) { - out.w(""); +function render(data, out, widget, state) { + widget.type = marko_widgetTypes[data.isMobile ? "default" : "mobile"]; - _widget_tag({ - type: marko_widgetTypes[data.isMobile ? "default" : "mobile"], - _cfg: data.widgetConfig, - _state: data.widgetState, - _props: data.widgetProps, - _body: data.widgetBody, - renderBody: function renderBody(out, widget, state) { - out.w(""); - } - }, out); + out.w(""); } -template._ = render; +marko_template._ = marko_widgets.r(render, {}); diff --git a/test/browser-tests-runner/page-template.marko.js b/test/browser-tests-runner/page-template.marko.js index ab585d93e..184e7bac7 100644 --- a/test/browser-tests-runner/page-template.marko.js +++ b/test/browser-tests-runner/page-template.marko.js @@ -1,6 +1,6 @@ -var template = require("marko/html").c(__filename); +var marko_template = require("marko/html").t(__filename); -module.exports = template; +module.exports = marko_template; var marko_helpers = require("marko/runtime/html/helpers"), marko_loadTag = marko_helpers.t, @@ -45,4 +45,4 @@ function render(data, out) { out.w(""); } -template._ = render; +marko_template._ = render; diff --git a/widgets/WidgetDef.js b/widgets/WidgetDef.js index 17c61241f..439a5c0ad 100644 --- a/widgets/WidgetDef.js +++ b/widgets/WidgetDef.js @@ -31,11 +31,10 @@ function WidgetDef(config, endFunc, out) { this.scope = config.scope; // The ID of the widget that this widget is scoped within this.customEvents = config.customEvents; // An array containing information about custom events this.bodyElId = config.bodyElId; // The ID for the default body element (if any any) - this.hasDomEvents = config.hasDomEvents; // A flag to indicate if this widget has any - // listeners for non-bubbling DOM events this.roots = config.roots; + this.body = config.body; - this.children = []; // An array of nested WidgetDef instances + this.children = null; // An array of nested WidgetDef instances this.end = endFunc; // A function that when called will pop this widget def off the stack this.domEvents = null; // An array of DOM events that need to be added (in sets of three) this.out = out; // The AsyncWriter that this widget is associated with @@ -48,7 +47,13 @@ WidgetDef.prototype = { * so that we can instantiate nested widgets before their parents. */ addChild: function (widgetDef) { - this.children.push(widgetDef); + var children = this.children; + + if (children) { + children.push(widgetDef); + } else { + this.children = [widgetDef]; + } }, /** * This helper method generates a unique and fully qualified DOM element ID diff --git a/widgets/WidgetsContext.js b/widgets/WidgetsContext.js index d0abf0a71..c97b08543 100644 --- a/widgets/WidgetsContext.js +++ b/widgets/WidgetsContext.js @@ -32,15 +32,15 @@ WidgetsContext.prototype = { }, beginWidget: function (widgetInfo, callback) { - var _this = this; - var widgetStack = _this.widgetStack; + var self = this; + var widgetStack = self.widgetStack; var origLength = widgetStack.length; var parent = origLength ? widgetStack[origLength - 1] : null; var widgetId = widgetInfo.id; if (!widgetId) { - widgetId = _this._nextWidgetId(); + widgetId = self._nextWidgetId(); widgetInfo.id = widgetId; } @@ -58,7 +58,7 @@ WidgetsContext.prototype = { //Check if it is a top-level widget parent.addChild(widgetDef); } else { - _this.widgets.push(widgetDef); + self.widgets.push(widgetDef); } widgetStack.push(widgetDef); diff --git a/widgets/defineRenderer.js b/widgets/defineRenderer.js index 0142e9977..775360975 100644 --- a/widgets/defineRenderer.js +++ b/widgets/defineRenderer.js @@ -1,21 +1,14 @@ var marko = require('../'); -var extend = require('raptor-util/extend'); var makeRenderable = require('../runtime/renderable'); -module.exports = function defineRenderer(def) { - var renderer = def.renderer; +module.exports = function defineRenderer(renderingLogic) { + var renderer = renderingLogic.renderer; if (renderer && renderer._isRenderer) { return renderer; } - var template = def.template; - var onInput = def.onInput; - var getInitialProps = def.getInitialProps; //deprecate - var getTemplateData = def.getTemplateData; - var getInitialState = def.getInitialState; //deprecate - var getWidgetConfig = def.getWidgetConfig; //deprecate - var getInitialBody = def.getInitialBody; + var template = renderingLogic.template; if (typeof template === 'string') { template = marko.load(template); @@ -26,124 +19,14 @@ module.exports = function defineRenderer(def) { // the input properties to a view state. Also, this renderer // takes care of re-using existing widgets. renderer = function renderer(input, out) { - var global = out.global; - - var newProps = input; - - if (!newProps) { - // Make sure we always have a non-null input object - newProps = {}; - } - - var widgetState; - var widgetConfig; - - if (global.__rerenderWidget && global.__rerenderState) { - // This is a state-ful widget. If this is a rerender then the "input" - // will be the new state. If we have state then we should use the input - // as the widget state and skip the steps of converting the input - // to a widget state. - var isFirstWidget = !global.__firstWidgetFound; - - if (isFirstWidget) { - // We are the first widget and we are not being extended - // and we are not extending so use the input as the state - widgetState = input; - newProps = null; - } - } - - if (newProps && onInput) { - var lightweightWidget = Object.create(def); - lightweightWidget.onInput(newProps); - widgetState = lightweightWidget.state; - widgetConfig = lightweightWidget; - delete widgetConfig.state; - } - - if (!widgetState) { - // If we do not have state then we need to go through the process - // of converting the input to a widget state, or simply normalizing - // the input using getInitialProps - - if (getInitialProps) { - // This optional method is used to normalize input state - newProps = getInitialProps(newProps, out) || {}; - } - - if (getInitialState) { - // This optional method is used to derive the widget state - // from the input properties - widgetState = getInitialState(newProps, out); - } - } - - global.__firstWidgetFound = true; - - // Use getTemplateData(state, props, out) to get the template - // data. If that method is not provided then just use the - // the state (if provided) or the input data. - var templateData = getTemplateData ? - getTemplateData(widgetState, newProps, out) : - widgetState || newProps; - - if (templateData) { - // We are going to be modifying the template data so we need to - // make a shallow clone of the object so that we don't - // mutate user provided data. - templateData = extend({}, templateData); - } else { - // We always should have some template data - templateData = {}; - } - - if (widgetState) { - // If we have widget state then pass it to the template - // so that it is available to the widget tag - templateData.widgetState = widgetState; - } - - if (widgetConfig) { - // If we have widget config then pass it to the template - // so that it is available to the widget tag - templateData.widgetConfig = widgetConfig; - } - - if (newProps) { - // If we have widget props then pass it to the template - // so that it is available to the widget tag. The widget props - // are only needed so that we can call widget.shouldUpdate(newProps) - templateData.widgetProps = newProps; - - if (getInitialBody) { - // If we have widget a widget body then pass it to the template - // so that it is available to the widget tag and can be inserted - // at the w-body marker - templateData.widgetBody = getInitialBody(newProps, out); - } else { - // Default to using the nested content as the widget body - // getInitialBody was not implemented - templateData.widgetBody = newProps.renderBody; - } - - if (getWidgetConfig) { - // If getWidgetConfig() was implemented then use that to - // get the widget config. The widget config will be passed - // to the widget constructor. If rendered on the server the - // widget config will be serialized to a JSON-like data - // structure and stored in a "data-w-config" attribute. - templateData.widgetConfig = getWidgetConfig(newProps, out); - } - } - // Render the template associated with the component using the final template // data that we constructed - template._(templateData, out); + template._(input, out, renderingLogic); }; } renderer._isRenderer = true; - renderer.createOut = template ? template.createOut : def.createOut; + renderer.createOut = template ? template.createOut : renderingLogic.createOut; renderer.template = template; makeRenderable(renderer, renderer); diff --git a/widgets/index-browser.js b/widgets/index-browser.js index a9fe411c9..d503f57c9 100644 --- a/widgets/index-browser.js +++ b/widgets/index-browser.js @@ -65,20 +65,12 @@ var jquery = window.$; exports.$ = jquery; exports.registerWidget = require('./registry').register; -exports.defineComponent = require('./defineComponent'); -exports.defineWidget = require('./defineWidget'); -exports.defineRenderer = require('./defineRenderer'); +exports.defineComponent = require('./defineComponent'); // Deprecated +exports.defineWidget /* deprecated */ = exports.w = require('./defineWidget'); +exports.defineRenderer = require('./defineRenderer'); // Deprecated exports.makeRenderable = exports.renderable = require('../runtime/renderable'); -exports.c = function(component, template) { - component.template = template; - return exports.defineComponent(component); -}; - -exports.r = function(renderer, template) { - renderer.template = template; - return exports.defineRenderer(renderer); -}; +exports.r = require('./renderer'); exports.batchUpdate = updateManager.batchUpdate; exports.onAfterUpdate = updateManager.onAfterUpdate; diff --git a/widgets/index.js b/widgets/index.js index 385a95952..8b89364e1 100644 --- a/widgets/index.js +++ b/widgets/index.js @@ -24,10 +24,13 @@ exports.uniqueId = require('./uniqueId'); function flattenHelper(widgets, flattened) { for (var i = 0, len = widgets.length; i < len; i++) { var widgetDef = widgets[i]; + if (!widgetDef.type) { + continue; + } var children = widgetDef.children; - if (children.length) { + if (children) { // Depth-first search (children should be initialized before parent) flattenHelper(children, flattened); } @@ -95,17 +98,8 @@ exports.defineWidget = require('./defineWidget'); exports.defineRenderer = require('./defineRenderer'); exports.makeRenderable = exports.renderable = require('../runtime/renderable'); -exports.c = function(componentDef, template) { - componentDef.template = template; - var component = exports.defineComponent(componentDef); - component.template = template; - return component; -}; - -exports.r = function(renderer, template) { - renderer.template = template; - return exports.defineRenderer(renderer); -}; +exports.r = require('./renderer'); +exports.w = function() { /* no op for defining a widget on teh server */ }; // registerWidget is a no-op on the server. // Fixes https://github.com/marko-js/marko-widgets/issues/111 diff --git a/widgets/init-widgets-browser.js b/widgets/init-widgets-browser.js index 01a02cc6b..d2fdfa238 100644 --- a/widgets/init-widgets-browser.js +++ b/widgets/init-widgets-browser.js @@ -114,8 +114,7 @@ function initWidget(widgetDef, doc) { el = els[0]; } else { - var widgetEl = doc.getElementById(id); - el = widgetEl; + el = doc.getElementById(id); el.__widget = widget; els = [el]; } @@ -228,10 +227,14 @@ function initClientRendered(widgetDefs, doc) { for (var i=0,len=widgetDefs.length; i { - event.insertCode(widgetArgsFunctionCall); - }); - - el.onAfterGenerateCode((event) => { - event.insertCode(cleanupWidgetArgsFunctionCall); - }); - } - - buildWidgetArgsFunctionCall(transformHelper) { - var context = transformHelper.context; var builder = transformHelper.builder; var id = this.id; @@ -62,33 +45,44 @@ class WidgetArgs { // widget if it is needed var shouldProvideScope = id || customEvents; - let widgetArgsVar = context.addStaticVar('marko_widgetArgs', - 'require("' + getRequirePath('marko/widgets/taglib/helpers/widgetArgs', context) + '")'); - - var functionCallArgs = [ - builder.identifier('out') - ]; + var args = []; if (shouldProvideScope) { - functionCallArgs.push(builder.memberExpression( - builder.identifier('widget'), - builder.identifier('id') - )); + args.push(builder.identifier('widget')); } else { - functionCallArgs.push(builder.literalNull()); + args.push(builder.literalNull()); } if (id != null) { - functionCallArgs.push(id); + args.push(id); } else { - functionCallArgs.push(builder.literalNull()); + args.push(builder.literalNull()); } if (customEvents) { - functionCallArgs.push(builder.literal(customEvents)); + args.push(builder.literal(customEvents)); } - return builder.functionCall(widgetArgsVar, functionCallArgs); + if (!el.tagDef || !el.tagDef.template) { + let widgetArgsVar = transformHelper.context.addStaticVar('marko_widgetArgs', + builder.require(builder.literal('marko/widgets/taglib/helpers/widgetArgs'))); + + let widgetArgsFunctionCall = builder.functionCall(widgetArgsVar, [ + builder.identifierOut(), + builder.literal(args) + ]); + let cleanupWidgetArgsFunctionCall = this.buildCleanupWidgetArgsFunctionCall(transformHelper); + + el.onBeforeGenerateCode((event) => { + event.insertCode(widgetArgsFunctionCall); + }); + + el.onAfterGenerateCode((event) => { + event.insertCode(cleanupWidgetArgsFunctionCall); + }); + } else { + el.setAttributeValue('$w', builder.literal(args)); + } } buildCleanupWidgetArgsFunctionCall(transformHelper) { diff --git a/widgets/taglib/TransformHelper/assignWidgetId.js b/widgets/taglib/TransformHelper/assignWidgetId.js index aa3631721..10e78125b 100644 --- a/widgets/taglib/TransformHelper/assignWidgetId.js +++ b/widgets/taglib/TransformHelper/assignWidgetId.js @@ -16,16 +16,16 @@ module.exports = function assignWidgetId(isRepeated) { var nestedIdExpression; var idExpression; - var containingWidgetNode = this.getContainingWidgetNode(); - if (!containingWidgetNode) { + + if (!this.hasBoundWidgetForTemplate()) { // We are assigning a widget ID to a nested widget in a template that does not have a widget. // That means we do not have access to the parent widget variable as part of a closure. We // need to look it up out of the `out.data` map if (!context.isFlagSet('hasWidgetVar')) { context.setFlag('hasWidgetVar'); - var getCurrentWidgetVar = context.importModule('__getCurrentWidget', + var getCurrentWidgetVar = context.importModule('marko_getCurrentWidget', this.getMarkoWidgetsRequirePath('marko/widgets/taglib/helpers/getCurrentWidget')); context.addVar('widget', builder.functionCall(getCurrentWidgetVar, [builder.identifierOut()])); diff --git a/widgets/taglib/TransformHelper/getContainingWidgetNode.js b/widgets/taglib/TransformHelper/getContainingWidgetNode.js deleted file mode 100644 index 94c08ddbb..000000000 --- a/widgets/taglib/TransformHelper/getContainingWidgetNode.js +++ /dev/null @@ -1,27 +0,0 @@ - -function getContainingWidgetNode() { - if (this.containingWidgetNode !== undefined) { - return this.containingWidgetNode; - } - - var curNode = this.el; - - while (true) { - if (curNode.tagName === '_widget') { - this.containingWidgetNode = curNode; - return this.containingWidgetNode; - } - - curNode = curNode.parentNode; - - if (!curNode) { - break; - } - } - - this.containingWidgetNode = null; - - return null; -} - -module.exports = getContainingWidgetNode; \ No newline at end of file diff --git a/widgets/taglib/TransformHelper/handleIncludeNode.js b/widgets/taglib/TransformHelper/handleIncludeNode.js index 3f138ed1c..009f151ef 100644 --- a/widgets/taglib/TransformHelper/handleIncludeNode.js +++ b/widgets/taglib/TransformHelper/handleIncludeNode.js @@ -6,8 +6,7 @@ module.exports = function(includeNode) { var builder = this.builder; var context = this.context; - let widgetTagNode = this.getContainingWidgetNode(); - if (!widgetTagNode) { + if (!this.hasBoundWidgetForTemplate()) { return; } @@ -28,16 +27,17 @@ module.exports = function(includeNode) { } } else { parentTransformHelper.assignWidgetId(false /* not repeated */); - widgetTagNode.setAttributeValue('body', parentTransformHelper.getNestedIdExpression()); - } - - if (!includeNode.data.includeTarget) { - includeNode.addProp('_target', builder.memberExpression(builder.identifier('data'), builder.identifier('widgetBody'))); + var widgetProps = this.getWidgetProps(); + widgetProps.body = parentTransformHelper.getNestedIdExpression(); } includeNode.setRendererPath(includeTagForWidgets); includeNode.onBeforeGenerateCode(function() { + if (!includeNode.data.includeTarget) { + includeNode.addProp('_target', builder.memberExpression(builder.identifier('widget'), builder.identifier('body'))); + } + includeNode.addProp('_widgetId', parentTransformHelper.getIdExpression()); includeNode.addProp('_arg', builder.identifier('widget')); }); diff --git a/widgets/taglib/TransformHelper/handleRootNodes.js b/widgets/taglib/TransformHelper/handleRootNodes.js index 179dd364a..e093d2b17 100644 --- a/widgets/taglib/TransformHelper/handleRootNodes.js +++ b/widgets/taglib/TransformHelper/handleRootNodes.js @@ -77,7 +77,8 @@ function handleScriptElement(scriptEl, transformHelper) { builder.returnStatement('marko_component') ]); - transformHelper.setInlineComponent(inlineComponent); + var inlineComponentVar = transformHelper.context.addStaticVar('marko_component', inlineComponent); + transformHelper.setInlineComponent(inlineComponentVar); } } @@ -179,16 +180,10 @@ module.exports = function handleRootNodes() { return; } - let widgetNode = context.createNodeForEl('_widget'); - - context.root.moveChildrenTo(widgetNode); - context.root.appendChild(widgetNode); - var nextRef = 0; rootNodes.forEach((curNode, i) => { curNode.setAttributeValue('w-bind'); - curNode.data.widgetNode = widgetNode; if (!curNode.hasAttribute('ref')) { if (curNode.type === 'CustomTag' || rootNodes.length > 1) { diff --git a/widgets/taglib/TransformHelper/handleWidgetBind.js b/widgets/taglib/TransformHelper/handleWidgetBind.js index 48bd8d62d..a69a9caad 100644 --- a/widgets/taglib/TransformHelper/handleWidgetBind.js +++ b/widgets/taglib/TransformHelper/handleWidgetBind.js @@ -34,6 +34,24 @@ function checkSplitComponent(context) { return rendererPath != null; } +function checkIsInnerBind(el) { + var curNode = el; + + while (true) { + if (curNode.data.hasBoundWidget) { + return true; + } + + curNode = curNode.parentNode; + + if (!curNode) { + break; + } + } + + return false; +} + module.exports = function handleWidgetBind() { let el = this.el; let context = this.context; @@ -44,16 +62,20 @@ module.exports = function handleWidgetBind() { return; } - // A widget is bound to the el... - // Remove the w-bind attribute since we don't want it showing up in the output DOM el.removeAttribute('w-bind'); + var isInnerBind = checkIsInnerBind(el.parentNode); + + el.data.hasBoundWidget = true; + + // A widget is bound to the el... + // Read the value for the w-bind attribute. This will be an AST node for the parsed JavaScript let bindAttrValue = bindAttr.value; let modulePath; - let widgetAttrs = {}; + var widgetProps = isInnerBind ? {} : this.getWidgetProps(); let isMain = isTemplateMainEntry(context); let transformHelper = this; @@ -87,11 +109,17 @@ module.exports = function handleWidgetBind() { return; } - widgetAttrs.type = builder.computedMemberExpression( - builder.identifier('marko_widgetTypes'), - bindAttrValue); + el.insertSiblingBefore( + builder.assignment( + builder.memberExpression(builder.identifier('widget'), builder.identifier('type')), + builder.memberExpression( + builder.identifier('marko_widgetTypes'), + bindAttrValue, + true /* computed */))); } + var renderingLogic; + if (inlineComponent) { isComponentExport = true; } else { @@ -105,20 +133,24 @@ module.exports = function handleWidgetBind() { } } - if (isComponentExport || isRendererExport) { - transformHelper.markoWidgetsVar = builder.identifier('marko_widgets'); + + if (inlineComponent) { + renderingLogic = inlineComponent; + } else if (isComponentExport) { + renderingLogic = context.addStaticVar('marko_component', builder.require(builder.literal(modulePath))); + } else if (rendererPath) { + renderingLogic = context.addStaticVar('marko_component', builder.require(builder.literal(rendererPath))); } if (modulePath) { let widgetTypeNode; - let def; - var widgetPath = modulePath; + var widgetTypeImport; if (isMain && isComponentExport) { widgetPath = './' + path.basename(context.filename); - def = builder.functionDeclaration(null, [], [ + widgetTypeImport = builder.functionDeclaration(null, [], [ builder.returnStatement(builder.memberExpression(builder.identifier('module'), builder.identifier('exports'))) ]); } @@ -126,63 +158,110 @@ module.exports = function handleWidgetBind() { context.addDependency({ type:'require', path:widgetPath }); context.addDependency({ type:'require', path:'marko/widgets' }); - widgetTypeNode = context.addStaticVar('marko_widgetType', this.buildWidgetTypeNode(widgetPath, def)); + widgetTypeNode = context.addStaticVar('marko_widgetType', this.buildWidgetTypeNode(widgetPath, widgetTypeImport)); - widgetAttrs.type = widgetTypeNode; + widgetProps.type = widgetTypeNode; + } - if (isComponentExport || isRendererExport) { - this.context.on('beforeGenerateCode:TemplateRoot', function(root) { - root.node.generateExports = function(template) { - if(inlineComponent) { - return buildComponentExport(transformHelper, inlineComponent, template); - } else if (isComponentExport) { - let component = builder.require( - builder.literal(modulePath) - ); + if (el.hasAttribute('w-config')) { + el.insertSiblingBefore( + builder.assignment( + builder.memberExpression(builder.identifier('widget'), builder.identifier('config')), + el.getAttributeValue('w-config'))); - return buildComponentExport(transformHelper, component, template); - } else { - let renderer = builder.require( - builder.literal(rendererPath) - ); - - return buildRendererExport(transformHelper, renderer, template); - } - - }; - }); - } + el.removeAttribute('w-config'); } let id = el.getAttributeValue('id'); - if (el.hasAttribute('w-config')) { - widgetAttrs.config = el.getAttributeValue('w-config'); - el.removeAttribute('w-config'); - } - if (id) { - widgetAttrs.id = id; + widgetProps.id = id; } - let widgetNode = el.data.widgetNode; + if (isInnerBind) { + // let widgetOptionsVar = context.addStaticVar( + // 'widgetOptions', + // builder.functionCall( + // builder.memberExpression(transformHelper.markoWidgetsVar, builder.identifier('r')), + // [ + // builder.renderBodyFunction([el]), + // builder.literal(widgetProps) + // ])); + // + // widgetProps._ = widgetOptionsVar; - if (widgetNode) { - widgetNode.setAttributeValues(widgetAttrs); - } else { - widgetNode = context.createNodeForEl('_widget', widgetAttrs); + el.setAttributeValue('id', + builder.memberExpression( + builder.identifier('widget'), + builder.identifier('id'))); + + // TODO Deprecation warning for inner binds + let widgetNode = context.createNodeForEl('_widget', { + props: builder.literal(widgetProps) + }); el.wrapWith(widgetNode); + return; } + if (this.firstBind) { + this.context.on('beforeGenerateCode:TemplateRoot', function(eventArgs) { + eventArgs.node.addRenderFunctionParam(builder.identifier('widget')); + 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; + + var createRendererArgs = [ + renderFunctionVar, + builder.literal(widgetProps) + ]; + + if (renderingLogic) { + createRendererArgs.push(renderingLogic); + } + + nodes.push(builder.assignment( + templateRendererMember, + builder.functionCall( + builder.memberExpression(transformHelper.markoWidgetsVar, builder.identifier('r')), + createRendererArgs))); + + if (inlineComponent || isComponentExport) { + nodes.push(builder.assignment( + builder.memberExpression(templateVar, builder.identifier('Widget')), + builder.functionCall( + builder.memberExpression(transformHelper.markoWidgetsVar, builder.identifier('w')), + [ + renderingLogic, + templateRendererMember + ]))); + } + + return nodes; + }; + }); + } + + + + // let widgetNode = el.data.widgetNode; + // + // if (widgetNode) { + // widgetNode.setAttributeValues(widgetProps); + // } else { + // widgetNode = context.createNodeForEl('_widget', widgetProps); + // el.wrapWith(widgetNode); + // } + var ref = el.getAttributeValue('ref'); if (el.hasAttribute('ref')) { - var roots = widgetNode.getAttributeValue('roots'); - if (roots) { - roots.value.push(ref); - } else { - widgetNode.setAttributeValue('roots', builder.literal([ref])); + if (!widgetProps.roots) { + widgetProps.roots = []; } + widgetProps.roots.push(ref); } else { el.setAttributeValue('id', builder.memberExpression( @@ -190,63 +269,9 @@ module.exports = function handleWidgetBind() { builder.identifier('id'))); } - this.widgetStack.push({ - widgetNode: widgetNode, - el: el, - extend: false - }); -}; - -function buildComponentExport(transformHelper, component, template) { - let builder = transformHelper.builder; - return [ - builder.assignment( - builder.var('component'), - component - ), - builder.var(transformHelper.markoWidgetsVar, builder.require(builder.literal(transformHelper.getMarkoWidgetsRequirePath('marko/widgets')))), - builder.assignment( - builder.memberExpression( - builder.identifier('module'), - builder.identifier('exports') - ), - builder.functionCall( - builder.memberExpression( - transformHelper.markoWidgetsVar, - builder.identifier('c') - ), - [ - builder.identifier('component'), - builder.identifier('template') - ] - ) - ) - ]; -} - -function buildRendererExport(transformHelper, renderer, template) { - let builder = transformHelper.builder; - return [ - builder.assignment( - builder.var('renderer'), - renderer - ), - builder.var(transformHelper.markoWidgetsVar, builder.require(builder.literal(transformHelper.getMarkoWidgetsRequirePath('marko/widgets')))), - builder.assignment( - builder.memberExpression( - builder.identifier('module'), - builder.identifier('exports') - ), - builder.functionCall( - builder.memberExpression( - transformHelper.markoWidgetsVar, - builder.identifier('r') - ), - [ - builder.identifier('renderer'), - builder.identifier('template') - ] - ) - ) - ]; -} \ No newline at end of file + // this.widgetStack.push({ + // widgetNode: widgetNode, + // el: el, + // extend: false + // }); +}; \ No newline at end of file diff --git a/widgets/taglib/TransformHelper/handleWidgetEvents.js b/widgets/taglib/TransformHelper/handleWidgetEvents.js index 6a4fca5df..6d0140ed6 100644 --- a/widgets/taglib/TransformHelper/handleWidgetEvents.js +++ b/widgets/taglib/TransformHelper/handleWidgetEvents.js @@ -15,10 +15,9 @@ function isUpperCase(c) { } function addBubblingEventListener(transformHelper, eventType, targetMethod, extraArgs) { - var containingWidgetNode = transformHelper.getContainingWidgetNode(); var el = transformHelper.el; - if (!containingWidgetNode) { + if (transformHelper.hasBoundWidgetForTemplate() === false) { transformHelper.addError('Unable to handle event "' + eventType + '". HTML element is not nested within a widget.'); return; } diff --git a/widgets/taglib/TransformHelper/index.js b/widgets/taglib/TransformHelper/index.js index 6e0b55dcb..519cbbdad 100644 --- a/widgets/taglib/TransformHelper/index.js +++ b/widgets/taglib/TransformHelper/index.js @@ -5,6 +5,8 @@ var buildWidgetTypeNode = require('../util/buildWidgetTypeNode'); var resolveFrom = require('resolve-from'); var INLINE_COMPONENT_KEY = Symbol('INLINE_COMPONENT'); var MARKO_WIDGETS_VAR_KEY = Symbol('MARKO_WIDGETS_VAR'); +var WIDGET_PROPS_KEY; + class TransformHelper { constructor(el, context) { @@ -17,7 +19,20 @@ class TransformHelper { this.widgetArgs = undefined; this.containingWidgetNode = undefined; this._markoWidgetsVar = context.data.markoWidgetsVar; - this.widgetStack = context.data.widgetStack || (context.data.widgetStack = []); + this.firstBind = false; + } + + hasBoundWidgetForTemplate() { + return this.context.data[WIDGET_PROPS_KEY] != null; + } + + getWidgetProps() { + var widgetProps = this.context.data[WIDGET_PROPS_KEY]; + if (!widgetProps) { + this.firstBind = true; + widgetProps = this.context.data[WIDGET_PROPS_KEY] = {}; + } + return widgetProps; } addError(message, code) { @@ -127,7 +142,6 @@ class TransformHelper { } TransformHelper.prototype.assignWidgetId = require('./assignWidgetId'); -TransformHelper.prototype.getContainingWidgetNode = require('./getContainingWidgetNode'); TransformHelper.prototype.handleRootNodes = require('./handleRootNodes'); TransformHelper.prototype.handleIncludeNode = require('./handleIncludeNode'); TransformHelper.prototype.handleWidgetEvents = require('./handleWidgetEvents'); diff --git a/widgets/taglib/helpers/bindWidget.js b/widgets/taglib/helpers/bindWidget.js new file mode 100644 index 000000000..a58f2e3e7 --- /dev/null +++ b/widgets/taglib/helpers/bindWidget.js @@ -0,0 +1,16 @@ +var createRendererFunc = require('../../renderer'); + +module.exports = function(widgetProps) { + var renderer = createRendererFunc( + function(data, out, widget, state) { + data.$renderBody(out, widget, state); + }, + widgetProps, + null); + + return function bindWidget(renderBody, out) { + renderer({ + $renderBody: renderBody + }, out); + }; +}; \ No newline at end of file diff --git a/widgets/taglib/helpers/widgetArgs.js b/widgets/taglib/helpers/widgetArgs.js index 9a4de0b26..dbcec5c71 100644 --- a/widgets/taglib/helpers/widgetArgs.js +++ b/widgets/taglib/helpers/widgetArgs.js @@ -1,27 +1,10 @@ var widgetArgsHelper = module.exports = function widgetArgsHelper( out, - scope, - assignedId, - customEvents) { + widgetArgs) { - var data = out.data; - var widgetArgs = data.widgetArgs; - var id; - - if (!widgetArgs) { - if (assignedId != null) { - id = assignedId.toString(); - } - - widgetArgs = data.widgetArgs = { - out: out, - id: id, - scope: scope, - customEvents: customEvents - }; - } + out.data.$w = widgetArgs; }; widgetArgsHelper.cleanup = function(out) { - delete out.data.widgetArgs; + delete out.data.$w; }; \ No newline at end of file diff --git a/widgets/taglib/include-tag.js b/widgets/taglib/include-tag.js index e16284788..2dc732c5b 100644 --- a/widgets/taglib/include-tag.js +++ b/widgets/taglib/include-tag.js @@ -10,7 +10,7 @@ module.exports = function include(input, out) { } else if (target) { normalInclude(input, out); } else if (isBrowser) { - var widgetId = input._widgetId; + var widgetId = input._arg.id; // Thereis no body content so let's see if we should reuse // the existing body content in the DOM diff --git a/widgets/taglib/marko.json b/widgets/taglib/marko.json index e0bd66992..084b5ab2b 100644 --- a/widgets/taglib/marko.json +++ b/widgets/taglib/marko.json @@ -1,5 +1,9 @@ { "<*>": { + "@$w": { + "target-property": null, + "autocomplete": [] + }, "@w-bind": { "type": "string", "preserve-name": true, @@ -191,20 +195,7 @@ "transformer": "./widgets-transformer.js" }, "<_widget>": { - "renderer": "./widget-tag.js", - "@type": "object", - "@config": "object", - "@id": "string", - "@hasDomEvents": "number", - "@body": "string", - "@roots": "array", - "vars": ["widget", "state"], - "import-var": { - "_cfg": "data.widgetConfig", - "_state": "data.widgetState", - "_props": "data.widgetProps", - "_body": "data.widgetBody" - }, + "code-generator": "./widget-tag.js", "autocomplete": [] }, "": { @@ -230,7 +221,7 @@ "@*": "string", "autocomplete": [ { - "displayText": "widget-types default=\"\" alt=\"\"", + "displayText": "widget-types default=\"\" alt=\"\"", "snippet": "widget-types default=\"${1:./widget}\"", "openTagOnly": true } diff --git a/widgets/taglib/widget-tag.js b/widgets/taglib/widget-tag.js index 2d93cf7fd..5cd3b0550 100644 --- a/widgets/taglib/widget-tag.js +++ b/widgets/taglib/widget-tag.js @@ -1,177 +1,32 @@ 'use strict'; -var markoWidgets = require('../'); -var widgetLookup = require('../lookup').widgets; -var widgetArgsId = require('../widget-args-id'); -var includeTag = require('./include-tag'); -var DUMMY_WIDGET_DEF = { - elId: function () { - } - }; +var BIND_WIDGET_KEY = Symbol(); +module.exports = function codeGenerator(el, codegen) { + var builder = codegen.builder; + var context = codegen.context; -function preserveWidgetEl(existingWidget, out, widgetsContext, widgetBody) { - var tagName = existingWidget.el.tagName; - var hasUnpreservedBody = false; + var bodyFunc = builder.renderBodyFunction(el.body, [ + builder.identifierOut(), + builder.identifier('widget'), + builder.identifier('state') + ]); - // We put a placeholder element in the output stream to ensure that the existing - // DOM node is matched up correctly when using morphdom. - out.beginElement(tagName, { id: existingWidget.id }); + var widgetProps = el.getAttributeValue('props'); - if (widgetBody && existingWidget.bodyEl) { - hasUnpreservedBody = true; - includeTag({ - _target: widgetBody, - _widgetId: existingWidget.bodyEl.id - }, out); + var bindWidgetVar = context.addStaticVar('marko_bindWidget', + builder.require( + builder.literal('marko/widgets/taglib/helpers/bindWidget'))); + + if (context.data[BIND_WIDGET_KEY] == null) { + context.data[BIND_WIDGET_KEY] = 0; } - out.endElement(); + var varName = context.addStaticVar( + 'marko_bindWidget' + (context.data[BIND_WIDGET_KEY]++), + builder.functionCall(bindWidgetVar, [ + widgetProps + ])); - existingWidget._reset(); // The widget is no longer dirty so reset internal flags - widgetsContext.addPreservedDOMNode(existingWidget.el, null, hasUnpreservedBody); // Mark the element as being preserved (for morphdom) -} - - -function handleBeginAsync(event) { - var parentOut = event.parentOut; - var asyncOut = event.out; - var widgetsContext = asyncOut.global.widgets; - var widgetStack; - - if (widgetsContext && (widgetStack = widgetsContext.widgetStack).length) { - // All of the widgets in this async block should be - // initialized after the widgets in the parent. Therefore, - // we will create a new WidgetsContext for the nested - // async block and will create a new widget stack where the current - // widget in the parent block is the only widget in the nested - // stack (to begin with). This will result in top-level widgets - // of the async block being added as children of the widget in the - // parent block. - var nestedWidgetsContext = new markoWidgets.WidgetsContext(asyncOut); - nestedWidgetsContext.widgetStack = [widgetStack[widgetStack.length-1]]; - asyncOut.data.widgets = nestedWidgetsContext; - } - - asyncOut.data.widgetArgs = parentOut.data.widgetArgs; -} - -module.exports = function widgetTag(input, out) { - var global = out.global; - - if (!global.__widgetsBeginAsyncAdded) { - global.__widgetsBeginAsyncAdded = true; - out.on('beginAsync', handleBeginAsync); - } - - var typeName = input.type; - var config = input.config || input._cfg; - var state = input.state || input._state; - var props = input.props || input._props; - var widgetArgs = out.data.widgetArgs; - var bodyElId = input.body; - var widgetBody = input._body; - var roots = input.roots; - var id = input.id; - var hasDomEvents = input.hasDomEvents; - var customEvents; - var scope; - - if (widgetArgs) { - delete out.data.widgetArgs; - scope = widgetArgs.scope; - - id = id || widgetArgsId(widgetArgs); - customEvents = widgetArgs.customEvents; - } - - var rerenderWidget = global.__rerenderWidget; - var isRerender = global.__rerender === true; - - var widgetsContext = markoWidgets.getWidgetsContext(out); - - if (!id) { - var parentWidget = widgetsContext.getCurrentWidget(); - - if (parentWidget) { - id = parentWidget.nextId(); - } - } - - var existingWidget; - - if (rerenderWidget) { - existingWidget = rerenderWidget; - id = rerenderWidget.id; - delete global.__rerenderWidget; - } else if (isRerender) { - // Look in in the DOM to see if a widget with the same ID and type already exists. - existingWidget = widgetLookup[id]; - if (existingWidget && existingWidget.__type !== typeName) { - existingWidget = undefined; - } - } - - if (!id && input.hasOwnProperty('id')) { - throw new Error('Invalid widget ID for "' + typeName + '"'); - } - - if (typeName) { - var shouldRenderBody = true; - - if (existingWidget && !rerenderWidget) { - // This is a nested widget found during a rerender. We don't want to needlessly - // rerender the widget if that is not necessary. If the widget is a stateful - // widget then we update the existing widget with the new state. - if (state) { - existingWidget._replaceState(state); // Update the existing widget state using the internal/private - // method to ensure that another update is not queued up - - // If the widget has custom state update handlers then we will use those methods - // to update the widget. - if (existingWidget._processUpdateHandlers() === true) { - // If _processUpdateHandlers() returns true then that means - // that the widget is now up-to-date and we can skip rerendering it. - shouldRenderBody = false; - preserveWidgetEl(existingWidget, out, widgetsContext, widgetBody); - return; - } - } - - // If the widget is not dirty (no state changes) and shouldUpdate() returns false - // then skip rerendering the widget. - if (!existingWidget.isDirty() && !existingWidget.shouldUpdate(props, state)) { - shouldRenderBody = false; - preserveWidgetEl(existingWidget, out, widgetsContext, widgetBody); - return; - } - } - - if (existingWidget) { - existingWidget._emitLifecycleEvent('beforeUpdate'); - } - - var widgetDef = widgetsContext.beginWidget({ - type: typeName, - id: id, - config: config, - state: state, - hasDomEvents: hasDomEvents, - customEvents: customEvents, - scope: scope, - createWidget: input.createWidget, - existingWidget: existingWidget, - bodyElId: bodyElId, - roots: roots - }); - - // Only render the widget if it needs to be rerendered - if (shouldRenderBody) { - input.renderBody(out, widgetDef, state); - } - - widgetDef.end(); - } else { - input.renderBody(out, DUMMY_WIDGET_DEF); - } + return builder.functionCall(varName, [bodyFunc, builder.identifierOut()]); }; \ No newline at end of file diff --git a/widgets/taglib/widget-types-tag.js b/widgets/taglib/widget-types-tag.js index 52a72c1a3..79ab0497f 100644 --- a/widgets/taglib/widget-types-tag.js +++ b/widgets/taglib/widget-types-tag.js @@ -20,4 +20,6 @@ module.exports = function codeGenerator(el, codegen) { }); codegen.addStaticVar('marko_widgetTypes', builder.literal(typesObject)); + + return null; }; \ No newline at end of file diff --git a/widgets/widget-args-id.js b/widgets/widget-args-id.js deleted file mode 100644 index cbaa5feb1..000000000 --- a/widgets/widget-args-id.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2011 eBay Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var repeatedId = require('./repeated-id'); - -module.exports = function widgetArgsId(widgetArgs) { - var widgetId = widgetArgs.id; - - if (widgetId) { - var out = widgetArgs.out; - var scope = widgetArgs.scope; - - if (widgetId.charAt(0) === '#') { - return widgetId.substring(1); - } else { - var resolvedId; - - if (widgetId.endsWith('[]')) { - resolvedId = repeatedId.nextId(out, scope, widgetId); - } else { - resolvedId = scope + '-' + widgetId; - } - - return resolvedId; - } - } -}; \ No newline at end of file