Fixes #455 - Simplify compiled code for UI components

This commit is contained in:
Patrick Steele-Idem 2016-12-13 11:34:19 -07:00
parent 40236b6cab
commit 5b9977913e
115 changed files with 1260 additions and 1061 deletions

View File

@ -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.';

View File

@ -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,

View File

@ -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 createHotReloadProxy(func, template, methodName) {
var hotReloadData = template[HOT_RELOAD_KEY];
if (!hotReloadData) {
hotReloadData = template[HOT_RELOAD_KEY] = {
modifiedId: modifiedId,
latest: template,
originals: {}
};
}
function patchMethods(obj, methodNames, reloadFunc) {
var hotReloadData = obj[HOT_RELOAD_KEY] || (obj[HOT_RELOAD_KEY] = {});
hotReloadData._modifiedId = modifiedId;
hotReloadData._latest = obj;
hotReloadData.originals[methodName] = func;
methodNames.forEach(function(methodName) {
hotReloadData[methodName] = obj[methodName];
var templatePath = template.path;
obj[methodName] = function hotReloadWrapper() {
function hotReloadProxy() {
if (hotReloadData.modifiedId !== modifiedId) {
hotReloadData.modifiedId = modifiedId;
hotReloadData._latest = reloadFunc() || obj;
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;
return latest[HOT_RELOAD_KEY][methodName].apply(latest, arguments);
};
});
var latest = hotReloadData.latest;
var originals = latest[HOT_RELOAD_KEY] && latest[HOT_RELOAD_KEY].originals;
if (!originals) {
originals = latest;
}
runtime.c = function hotReloadCreateTemplate(path) {
var targetFunc = originals._;
return targetFunc.apply(latest, arguments);
}
return hotReloadProxy;
}
var oldCreateTemplate = runtime.t;
runtime.t = function hotReloadCreateTemplate(path) {
var originalTemplate = oldCreateTemplate.apply(runtime, arguments);
path = path.replace(/\.js$/, '');
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++;
}

View File

@ -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);
};

View File

@ -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);
};

View File

@ -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("<div></div>");
}
template._ = render;
marko_template._ = render;

View File

@ -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("<div></div>");
}
template._ = render;
marko_template._ = render;

View File

@ -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("<div></div>");
}
template._ = render;
marko_template._ = render;

View File

@ -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("<div></div>");
}
template._ = render;
marko_template._ = render;

View File

@ -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("<div></div>");
}
template._ = render;
marko_template._ = render;

View File

@ -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("<div></div>");
}
template._ = render;
marko_template._ = render;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
};

View File

@ -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;

View File

@ -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("<div></div>");
}
template._ = render;
marko_template._ = render;
template.meta = {
marko_template.meta = {
deps: [
"./foo"
]

View File

@ -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("<div></div>");
}
template._ = render;
marko_template._ = render;

View File

@ -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("<div class=\"foo\"><span class=\"bar\"></span></div>");
}
template._ = render;
marko_template._ = render;

View File

@ -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;

View File

@ -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\"></div>");
}
template._ = render;
marko_template._ = render;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 &amp; Suzy Invalid Entity: &b ; Valid Numeric Entity: &#34; Valid Hexadecimal Entity: &#x00A2;");
}
template._ = render;
marko_template._ = render;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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("<div replaced=\"test-replaceWith\"></div>");
}
template._ = render;
marko_template._ = render;

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1 @@
template.temp.marko

View File

@ -0,0 +1,7 @@
module.exports = {
onInput(input) {
this.state = {
name: input.name
};
}
};

View File

@ -0,0 +1,3 @@
<div class="a">
Hello ${state.name}
</div>

View File

@ -0,0 +1,3 @@
<div class="b">
Hello ${data.name}
</div>

View File

@ -0,0 +1,3 @@
<div class="b">
Hello ${data.name}
</div>

View File

@ -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('<div class="a" id="w0">Hello Frank</div>');
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('<div class="b">Hello Jane</div>');
};

View File

@ -0,0 +1 @@
template.temp.marko

View File

@ -0,0 +1,3 @@
<div class="a">
Hello ${data.name}
</div>

View File

@ -0,0 +1,7 @@
module.exports = {
onInput(input) {
this.state = {
name: input.name
};
}
};

View File

@ -0,0 +1,3 @@
<div class="b">
Hello ${state.name}
</div>

View File

@ -0,0 +1,7 @@
module.exports = {
onInput(input) {
this.state = {
name: input.name
};
}
};

View File

@ -0,0 +1,3 @@
<div class="b">
Hello ${state.name}
</div>

View File

@ -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('<div class="a">Hello Frank</div>');
hotReload.handleFileModified(tempTemplatePath);
copyFiles(nodePath.join(__dirname, 'b'));
expect(component.renderSync({ name: 'Jane' }).toString()).to.equal('<div class="b" id="w0">Hello Jane</div>');
};

View File

@ -10,6 +10,7 @@
"for",
"include",
"while",
"$w",
"w-bind",
"w-scope",
"w-config",

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1,5 @@
module.exports = {
emitTestEvent: function() {
this.emit('test', 'abc', '123');
}
};

View File

@ -0,0 +1,3 @@
<div.foo>
[app-foo]
</div>

View File

@ -0,0 +1,16 @@
<div>
<app-foo onTest('handleFooTest')/>
</div>
<script>
module.exports = {
onMount: function() {
var fooEl = document.querySelector('.foo');
var fooWidget = this.fooWidget = require('marko/widgets').getWidgetForEl(fooEl);
fooWidget.emitTestEvent();
},
handleFooTest: function() {
this.fooEvent = arguments;
}
};
</script>

View File

@ -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);
};

View File

@ -1,5 +1,5 @@
<div w-bind>
Hello ${data.name}!
Hello ${state.name}!
</div>
<script>

View File

@ -0,0 +1,10 @@
<script>
module.exports = {
onMount: function() {
}
};
</script>
<div.foo>
</div>

View File

@ -0,0 +1,12 @@
<script>
module.exports = {
onMount: function() {
}
};
</script>
<div.root>
<app-foo ref="foo"/>
<a href="ebay.com" ref="link">eBay</a>
</div>

View File

@ -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');
};

View File

@ -12,5 +12,5 @@
</script>
<div>
Hello ${data.name}!
Hello ${state.name}!
</div>

View File

@ -2,7 +2,7 @@ module.exports = {
onInput: function(input) {
this.state = {
name: input.name
}
};
},
setName: function(newName) {
this.state.name = newName;

View File

@ -1,3 +1,3 @@
<div w-bind>
Hello ${data.name}!
Hello ${state.name}!
</div>

View File

@ -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) {
function render(data, out, widget, state) {
out.w("<div" +
marko_attr("id", widget.id) +
"></div>");
}
}, out);
}
template._ = render;
marko_template._ = marko_widgets.r(render, {
type: marko_widgetType
});

View File

@ -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) {
function render(data, out, widget, state) {
out.w("<div" +
marko_attr("id", widget.id) +
"></div>");
}
}, out);
}
template._ = render;
marko_template._ = marko_widgets.r(render, {
type: marko_widgetType
});

View File

@ -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,18 +10,9 @@ 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) {
function render(data, out, widget, state) {
out.w("<div" +
marko_attr("id", widget.id) +
"><h1>Header</h1><div" +
@ -29,14 +20,15 @@ function render(data, out) {
">");
include_tag({
_target: data.widgetBody,
_target: widget.body,
_widgetId: widget.elId(0),
_arg: widget
}, out);
out.w("</div></div>");
}
}, out);
}
template._ = render;
marko_template._ = marko_widgets.r(render, {
type: marko_widgetType,
body: 0
});

View File

@ -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("<div" +
marko_attr("id", widget.elId("_r0")) +
">A</div><span" +
marko_attr("id", widget.elId("_r1")) +
">B</span>");
}
marko_template._ = marko_widgets.r(render, {
type: marko_widgetType,
roots: [
"_r0",
"_r1"
]
}, marko_component);
marko_template.Widget = marko_widgets.w(marko_component, marko_template._);

View File

@ -0,0 +1,10 @@
<script>
module.exports = {};
</script>
<div>
A
</div>
<span>
B
</span>

View File

@ -1,39 +1,30 @@
var template = require("marko/html").c(__filename);
var marko_template = require("marko/html").t(__filename);
var component = (function() {
module.exports = marko_template;
var marko_component = (function() {
var marko_component;
marko_component = {};
return marko_component;
})();
var marko_widgets = require("marko/widgets");
module.exports = marko_widgets.c(component, template);
var marko_registerWidget = marko_widgets.registerWidget,
})(),
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) {
function render(data, out, widget, state) {
out.w("<div" +
marko_attr("id", widget.id) +
"></div>");
}
}, out);
}
template._ = render;
marko_template._ = marko_widgets.r(render, {
type: marko_widgetType
}, marko_component);
marko_template.Widget = marko_widgets.w(marko_component, marko_template._);

View File

@ -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) {
function render(data, out, widget, state) {
out.w("<div" +
marko_attr("id", widget.id) +
"></div>");
}
}, out);
}
template._ = render;
marko_template._ = marko_widgets.r(render, {
type: marko_widgetType
}, marko_component);

View File

@ -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) {
function render(data, out, widget, state) {
out.w("<div" +
marko_attr("id", widget.id) +
"></div>");
}
}, out);
}
template._ = render;
marko_template._ = marko_widgets.r(render, {
type: marko_widgetType
}, marko_component);
marko_template.Widget = marko_widgets.w(marko_component, marko_template._);

View File

@ -0,0 +1,10 @@
<script>
module.exports = {
onMount: function() {
}
};
</script>
<div.foo>
</div>

View File

@ -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("<div class=\"root\"" +
marko_attr("id", widget.id) +
">");
app_foo_tag({
$w: [
widget,
"foo"
]
}, out);
out.w("<a href=\"ebay.com\"" +
marko_attr("id", widget.elId("link")) +
">eBay</a></div>");
}
marko_template._ = marko_widgets.r(render, {
type: marko_widgetType
}, marko_component);
marko_template.Widget = marko_widgets.w(marko_component, marko_template._);

View File

@ -0,0 +1,12 @@
<script>
module.exports = {
onMount: function() {
}
};
</script>
<div.root>
<app-foo ref="foo"/>
<a href="ebay.com" ref="link">eBay</a>
</div>

View File

@ -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("<div></div>");
}
template._ = render;
marko_template._ = render;
template.meta = {
marko_template.meta = {
deps: [
"./style.css"
]

View File

@ -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("<div></div>");
}
template._ = render;
marko_template._ = render;
template.meta = {
marko_template.meta = {
deps: [
{
type: "css",

View File

@ -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("<widget-types default=\"./widget\" mobile=\"./widget-mobile\"></widget-types>");
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("<div" +
marko_attr("id", widget.id) +
"></div>");
}
}, out);
}
template._ = render;
marko_template._ = marko_widgets.r(render, {});

View File

@ -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("</body></html>");
}
template._ = render;
marko_template._ = render;

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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<len; i++) {
var widgetDef = widgetDefs[i];
if (widgetDef.children.length) {
if (widgetDef.children) {
initClientRendered(widgetDef.children, doc);
}
if (!widgetDef.type) {
continue;
}
var widget = initWidget(
widgetDef,
doc);

View File

@ -1 +1,311 @@
module.exports = require('raptor-renderer');
var markoWidgets = require('./');
var widgetLookup = require('./lookup').widgets;
var includeTag = require('./taglib/include-tag');
var repeatedId = require('./repeated-id');
function resolveWidgetRef(out, ref, scope) {
if (ref.charAt(0) === '#') {
return ref.substring(1);
} else {
var resolvedId;
if (ref.endsWith('[]')) {
resolvedId = repeatedId.nextId(out, scope, ref);
} else {
resolvedId = scope + '-' + ref;
}
return resolvedId;
}
}
function preserveWidgetEl(existingWidget, out, widgetsContext, widgetBody) {
var tagName = existingWidget.el.tagName;
var hasUnpreservedBody = false;
// 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 });
if (widgetBody && existingWidget.bodyEl) {
hasUnpreservedBody = true;
includeTag({
_target: widgetBody,
_widgetId: existingWidget.bodyEl.id
}, out);
}
out.endElement();
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.$w = parentOut.data.$w;
}
module.exports = function createRendererFunc(templateRenderFunc, widgetProps, renderingLogic) {
var onInput;
var getInitialProps;
var getTemplateData;
var getInitialState;
var getWidgetConfig;
var getInitialBody;
function initRendereringLogic() {
onInput = renderingLogic.onInput;
getInitialProps = renderingLogic.getInitialProps; //deprecate
getTemplateData = renderingLogic.getTemplateData;
getInitialState = renderingLogic.getInitialState; //deprecate
getWidgetConfig = renderingLogic.getWidgetConfig; //deprecate
getInitialBody = renderingLogic.getInitialBody;
}
if (renderingLogic) {
initRendereringLogic();
}
var typeName = widgetProps.type;
var bodyElId = widgetProps.body;
var roots = widgetProps.roots;
var assignedId = widgetProps.id;
return function renderer(input, out, renderingLogicLegacy /* needed by defineRenderer */) {
var outGlobal = out.global;
if (!outGlobal.__widgetsBeginAsyncAdded) {
outGlobal.__widgetsBeginAsyncAdded = true;
out.on('beginAsync', handleBeginAsync);
}
if (!input) {
// Make sure we always have a non-null input object
input = {};
}
if (renderingLogic === undefined) {
// LEGACY - This should be removed when `defineRenderer` is removed but we use it
// now to run the rendering logic that is passed in at render time. The reason we don't
// get the rendering logic until now is that in older versions the `defineRenderer` was
// invoked before template rendering
if ((renderingLogic = renderingLogicLegacy)) {
initRendereringLogic();
}
}
var widgetState;
var widgetConfig;
var widgetBody;
if (outGlobal.__rerenderWidget && outGlobal.__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 = !outGlobal.__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;
input = null;
}
}
var widgetArgs;
if (input) {
if (onInput) {
var lightweightWidget = Object.create(renderingLogic);
lightweightWidget.onInput(input);
widgetState = lightweightWidget.state;
widgetConfig = lightweightWidget;
delete widgetConfig.state;
} else {
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.
widgetConfig = getWidgetConfig(input, out);
} else {
widgetConfig = input.widgetConfig;
}
}
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
widgetBody = getInitialBody(input, out);
} else {
// Default to using the nested content as the widget body
// getInitialBody was not implemented
widgetBody = input.renderBody;
}
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
input = getInitialProps(input, out) || {};
}
if (getInitialState) {
// This optional method is used to derive the widget state
// from the input properties
widgetState = getInitialState(input, out);
}
}
widgetArgs = input.$w;
}
outGlobal.__firstWidgetFound = true;
var customEvents;
var scope;
var id = assignedId;
if (!widgetArgs) {
widgetArgs = out.data.$w;
}
if (widgetArgs) {
scope = widgetArgs[0];
if (scope) {
scope = scope.id;
}
var ref = widgetArgs[1];
if (ref != null) {
ref = ref.toString();
}
id = id || resolveWidgetRef(out, ref, scope);
customEvents = widgetArgs[2];
}
var rerenderWidget = outGlobal.__rerenderWidget;
var isRerender = outGlobal.__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 outGlobal.__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 && widgetProps.hasOwnProperty('id')) {
throw new Error('Invalid widget ID for "' + 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 (widgetState) {
existingWidget._replaceState(widgetState); // 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(input, widgetState)) {
shouldRenderBody = false;
preserveWidgetEl(existingWidget, out, widgetsContext, widgetBody);
return;
}
}
// 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, input, out) :
(getInitialState && widgetState /*legacy*/) || input) || {};
if (existingWidget) {
existingWidget._emitLifecycleEvent('beforeUpdate');
}
var widgetDef = widgetsContext.beginWidget({
type: typeName,
id: id,
config: widgetConfig,
state: widgetState,
customEvents: customEvents,
scope: scope,
existingWidget: existingWidget,
bodyElId: bodyElId,
roots: roots,
body: widgetBody
});
// Only render the widget if it needs to be rerendered
if (shouldRenderBody) {
// Render the template associated with the component using the final template
// data that we constructed
templateRenderFunc(templateData, out, widgetDef, widgetState);
}
widgetDef.end();
};
};

Some files were not shown because too many files have changed in this diff Show More