diff --git a/packages/spacebars-compiler/codegen.js b/packages/spacebars-compiler/codegen.js
index 4a4d1a41f9..f6ac43a820 100644
--- a/packages/spacebars-compiler/codegen.js
+++ b/packages/spacebars-compiler/codegen.js
@@ -7,10 +7,10 @@
var CodeGen = SpacebarsCompiler.CodeGen = function () {};
var builtInBlockHelpers = SpacebarsCompiler._builtInBlockHelpers = {
- 'if': 'UI.If',
- 'unless': 'UI.Unless',
- 'with': 'Spacebars.With',
- 'each': 'UI.Each'
+ 'if': 'Blaze.If',
+ 'unless': 'Blaze.Unless',
+ 'with': 'Spacebars.With2',
+ 'each': 'Spacebars.Each'
};
// These must be prefixed with `UI.` when you use them in a template.
@@ -36,80 +36,89 @@ _.extend(CodeGen.prototype, {
codeGenTemplateTag: function (tag) {
var self = this;
if (tag.position === HTMLTools.TEMPLATE_TAG_POSITION.IN_START_TAG) {
+ // Special dynamic attributes: `
...`
// only `tag.type === 'DOUBLE'` allowed (by earlier validation)
- return BlazeTools.EmitCode('function () { return ' +
- self.codeGenMustache(tag.path, tag.args, 'attrMustache')
- + '; }');
+ return BlazeTools.EmitCode(
+ 'Blaze.Var(function () { return ' +
+ self.codeGenMustache(tag.path, tag.args, 'attrMustache')
+ + '; })');
} else {
if (tag.type === 'DOUBLE') {
- return BlazeTools.EmitCode('function () { return ' +
- self.codeGenMustache(tag.path, tag.args) + '; }');
+ return BlazeTools.EmitCode('Blaze.Isolate(function () { return ' +
+ self.codeGenMustache(tag.path, tag.args) + '; })');
} else if (tag.type === 'TRIPLE') {
- return BlazeTools.EmitCode('function () { return Spacebars.makeRaw(' +
- self.codeGenMustache(tag.path, tag.args) + '); }');
+ return BlazeTools.EmitCode('Blaze.Isolate(function () { return Spacebars.makeRaw(' +
+ self.codeGenMustache(tag.path, tag.args) + '); })');
} else if (tag.type === 'INCLUSION' || tag.type === 'BLOCKOPEN') {
var path = tag.path;
-
+
if (tag.type === 'BLOCKOPEN' &&
builtInBlockHelpers.hasOwnProperty(path[0])) {
// if, unless, with, each.
//
// If someone tries to do `{{> if}}`, we don't
// get here, but an error is thrown when we try to codegen the path.
-
+
// Note: If we caught these errors earlier, while scanning, we'd be able to
// provide nice line numbers.
if (path.length > 1)
throw new Error("Unexpected dotted path beginning with " + path[0]);
if (! tag.args.length)
throw new Error("#" + path[0] + " requires an argument");
-
- var codeParts = self.codeGenInclusionParts(tag);
- var dataFunc = codeParts.dataFunc; // must exist (tag.args.length > 0)
- var contentBlock = codeParts.content; // must exist
- var elseContentBlock = codeParts.elseContent; // may not exist
-
- var callArgs = [dataFunc, contentBlock];
+
+ // `args` must exist (tag.args.length > 0)
+ var dataCode = self.codeGenInclusionArgs(tag.args);
+ // `content` must exist
+ var contentBlock = (('content' in tag) ?
+ self.codeGenBlock(tag.content) : null);
+ // `elseContent` may not exist
+ var elseContentBlock = (('elseContent' in tag) ?
+ self.codeGenBlock(tag.elseContent) : null);
+
+ var callArgs = ['function () { return ' + dataCode + '; }',
+ contentBlock];
if (elseContentBlock)
callArgs.push(elseContentBlock);
-
+
return BlazeTools.EmitCode(
builtInBlockHelpers[path[0]] + '(' + callArgs.join(', ') + ')');
-
+
} else {
var compCode = self.codeGenPath(path, {lookupTemplate: true});
-
+
if (path.length !== 1) {
// path code may be reactive; wrap it
compCode = 'function () { return ' + compCode + '; }';
}
-
- var codeParts = self.codeGenInclusionParts(tag);
- var dataFunc = codeParts.dataFunc;
- var content = codeParts.content;
- var elseContent = codeParts.elseContent;
-
+
+ var dataCode = self.codeGenInclusionArgs(tag.args);
+ var content = (('content' in tag) ?
+ self.codeGenBlock(tag.content) : null);
+ var elseContent = (('elseContent' in tag) ?
+ self.codeGenBlock(tag.elseContent) : null);
+
var includeArgs = [compCode];
if (content) {
includeArgs.push(content);
if (elseContent)
includeArgs.push(elseContent);
}
-
+
var includeCode =
'Spacebars.include(' + includeArgs.join(', ') + ')';
-
- if (dataFunc) {
+
+ if (dataCode) {
includeCode =
- 'Spacebars.TemplateWith(' + dataFunc + ', UI.block(' +
+ 'Spacebars.TemplateWith(function () { return ' +
+ dataCode + '; }, UI.block(' +
SpacebarsCompiler.codeGen(BlazeTools.EmitCode(includeCode)) + '))';
}
-
+
if (path[0] === 'UI' &&
(path[1] === 'contentBlock' || path[1] === 'elseBlock')) {
includeCode = 'UI.InTemplateScope(template, ' + includeCode + ')';
}
-
+
return BlazeTools.EmitCode(includeCode);
}
} else {
@@ -147,11 +156,11 @@ _.extend(CodeGen.prototype, {
return builtInLexicals[path[1]];
}
- var args = [BlazeTools.toJSLiteral(path[0])];
+ var args = [BlazeTools.toJSLiteral(path[0]), 'self2'];
var lookupMethod = 'lookup';
if (opts && opts.lookupTemplate && path.length === 1)
lookupMethod = 'lookupTemplate';
- var code = 'self.' + lookupMethod + '(' + args.join(', ') + ')';
+ var code = 'Blaze.' + lookupMethod + '(' + args.join(', ') + ')';
if (path.length > 1) {
code = 'Spacebars.dot(' + code + ', ' +
@@ -168,7 +177,7 @@ _.extend(CodeGen.prototype, {
// more than one element) and is not wrapped in a closure.
codeGenArgValue: function (arg) {
var self = this;
-
+
var argType = arg[0];
var argValue = arg[1];
@@ -196,7 +205,7 @@ _.extend(CodeGen.prototype, {
// one for fine-grained reactivity.
codeGenMustache: function (path, args, mustacheType) {
var self = this;
-
+
var nameCode = self.codeGenPath(path);
var argCode = self.codeGenMustacheArgs(args);
var mustache = (mustacheType || 'mustache');
@@ -209,7 +218,7 @@ _.extend(CodeGen.prototype, {
// args at all.
codeGenMustacheArgs: function (tagArgs) {
var self = this;
-
+
var kwArgs = null; // source -> source
var args = null; // [source]
@@ -237,6 +246,10 @@ _.extend(CodeGen.prototype, {
return args;
},
+ codeGenBlock: function (content) {
+ return SpacebarsCompiler.codeGen(content);
+ },
+
// Takes an inclusion tag and returns an object containing these properties,
// all optional, whose values are JS source code:
//
@@ -245,25 +258,14 @@ _.extend(CodeGen.prototype, {
// - `elseContent` - source code of an elseContent block
//
// Implements the calling convention for inclusions.
- codeGenInclusionParts: function (tag) {
+ codeGenInclusionArgs: function (args) {
var self = this;
- var ret = {};
-
- if ('content' in tag) {
- ret.content = (
- 'UI.block(' + SpacebarsCompiler.codeGen(tag.content) + ')');
- }
- if ('elseContent' in tag) {
- ret.elseContent = (
- 'UI.block(' + SpacebarsCompiler.codeGen(tag.elseContent) + ')');
- }
var dataFuncCode = null;
- var args = tag.args;
if (! args.length) {
// e.g. `{{#foo}}`
- return ret;
+ return null;
} else if (args[0].length === 3) {
// keyword arguments only, e.g. `{{> point x=1 y=2}}`
var dataProps = {};
@@ -288,9 +290,7 @@ _.extend(CodeGen.prototype, {
'dataMustache');
}
- ret.dataFunc = 'function () { return ' + dataFuncCode + '; }';
-
- return ret;
+ return dataFuncCode;
}
-
+
});
diff --git a/packages/spacebars-compiler/codegen2.js b/packages/spacebars-compiler/codegen2.js
deleted file mode 100644
index 3c563b6d71..0000000000
--- a/packages/spacebars-compiler/codegen2.js
+++ /dev/null
@@ -1,296 +0,0 @@
-// ============================================================
-// Code-generation of template tags
-
-// The `CodeGen` class currently has no instance state, but in theory
-// it could be useful to track per-function state, like whether we
-// need to emit `var self = this` or not.
-var CodeGen2 = SpacebarsCompiler.CodeGen2 = function () {};
-
-var builtInBlockHelpers = SpacebarsCompiler._builtInBlockHelpers = {
- 'if': 'Blaze.If',
- 'unless': 'Blaze.Unless',
- 'with': 'Spacebars.With2',
- 'each': 'Spacebars.Each'
-};
-
-// These must be prefixed with `UI.` when you use them in a template.
-var builtInLexicals = SpacebarsCompiler._builtInLexicals = {
- 'contentBlock': 'template.__content',
- 'elseBlock': 'template.__elseContent'
-};
-
-// A "reserved name" can't be used as a
name. This
-// function is used by the template file scanner.
-SpacebarsCompiler.isReservedName = function (name) {
- return builtInBlockHelpers.hasOwnProperty(name);
-};
-
-var makeObjectLiteral = function (obj) {
- var parts = [];
- for (var k in obj)
- parts.push(BlazeTools.toObjectLiteralKey(k) + ': ' + obj[k]);
- return '{' + parts.join(', ') + '}';
-};
-
-_.extend(CodeGen2.prototype, {
- codeGenTemplateTag: function (tag) {
- var self = this;
- if (tag.position === HTMLTools.TEMPLATE_TAG_POSITION.IN_START_TAG) {
- // Special dynamic attributes: `...`
- // only `tag.type === 'DOUBLE'` allowed (by earlier validation)
- return BlazeTools.EmitCode(
- 'Blaze.Var(function () { return ' +
- self.codeGenMustache(tag.path, tag.args, 'attrMustache')
- + '; })');
- } else {
- if (tag.type === 'DOUBLE') {
- return BlazeTools.EmitCode('Blaze.Isolate(function () { return ' +
- self.codeGenMustache(tag.path, tag.args) + '; })');
- } else if (tag.type === 'TRIPLE') {
- return BlazeTools.EmitCode('Blaze.Isolate(function () { return Spacebars.makeRaw(' +
- self.codeGenMustache(tag.path, tag.args) + '); })');
- } else if (tag.type === 'INCLUSION' || tag.type === 'BLOCKOPEN') {
- var path = tag.path;
-
- if (tag.type === 'BLOCKOPEN' &&
- builtInBlockHelpers.hasOwnProperty(path[0])) {
- // if, unless, with, each.
- //
- // If someone tries to do `{{> if}}`, we don't
- // get here, but an error is thrown when we try to codegen the path.
-
- // Note: If we caught these errors earlier, while scanning, we'd be able to
- // provide nice line numbers.
- if (path.length > 1)
- throw new Error("Unexpected dotted path beginning with " + path[0]);
- if (! tag.args.length)
- throw new Error("#" + path[0] + " requires an argument");
-
- // `args` must exist (tag.args.length > 0)
- var dataCode = self.codeGenInclusionArgs(tag.args);
- // `content` must exist
- var contentBlock = (('content' in tag) ?
- self.codeGenBlock(tag.content) : null);
- // `elseContent` may not exist
- var elseContentBlock = (('elseContent' in tag) ?
- self.codeGenBlock(tag.elseContent) : null);
-
- var callArgs = ['function () { return ' + dataCode + '; }',
- contentBlock];
- if (elseContentBlock)
- callArgs.push(elseContentBlock);
-
- return BlazeTools.EmitCode(
- builtInBlockHelpers[path[0]] + '(' + callArgs.join(', ') + ')');
-
- } else {
- var compCode = self.codeGenPath(path, {lookupTemplate: true});
-
- if (path.length !== 1) {
- // path code may be reactive; wrap it
- compCode = 'function () { return ' + compCode + '; }';
- }
-
- var dataCode = self.codeGenInclusionArgs(tag.args);
- var content = (('content' in tag) ?
- self.codeGenBlock(tag.content) : null);
- var elseContent = (('elseContent' in tag) ?
- self.codeGenBlock(tag.elseContent) : null);
-
- var includeArgs = [compCode];
- if (content) {
- includeArgs.push(content);
- if (elseContent)
- includeArgs.push(elseContent);
- }
-
- var includeCode =
- 'Spacebars.include(' + includeArgs.join(', ') + ')';
-
- if (dataCode) {
- includeCode =
- 'Spacebars.TemplateWith(function () { return ' +
- dataCode + '; }, UI.block(' +
- SpacebarsCompiler.codeGen(BlazeTools.EmitCode(includeCode)) + '))';
- }
-
- if (path[0] === 'UI' &&
- (path[1] === 'contentBlock' || path[1] === 'elseBlock')) {
- includeCode = 'UI.InTemplateScope(template, ' + includeCode + ')';
- }
-
- return BlazeTools.EmitCode(includeCode);
- }
- } else {
- // Can't get here; TemplateTag validation should catch any
- // inappropriate tag types that might come out of the parser.
- throw new Error("Unexpected template tag type: " + tag.type);
- }
- }
- },
-
- // `path` is an array of at least one string.
- //
- // If `path.length > 1`, the generated code may be reactive
- // (i.e. it may invalidate the current computation).
- //
- // No code is generated to call the result if it's a function.
- //
- // Options:
- //
- // - lookupTemplate {Boolean} If true, generated code also looks in
- // the list of templates. (After helpers, before data context).
- // Used when generating code for `{{> foo}}` or `{{#foo}}`. Only
- // used for non-dotted paths.
- codeGenPath: function (path, opts) {
- if (builtInBlockHelpers.hasOwnProperty(path[0]))
- throw new Error("Can't use the built-in '" + path[0] + "' here");
- // Let `{{#if UI.contentBlock}}` check whether this template was invoked via
- // inclusion or as a block helper, in addition to supporting
- // `{{> UI.contentBlock}}`.
- if (path.length >= 2 &&
- path[0] === 'UI' && builtInLexicals.hasOwnProperty(path[1])) {
- if (path.length > 2)
- throw new Error("Unexpected dotted path beginning with " +
- path[0] + '.' + path[1]);
- return builtInLexicals[path[1]];
- }
-
- var args = [BlazeTools.toJSLiteral(path[0]), 'self2'];
- var lookupMethod = 'lookup';
- if (opts && opts.lookupTemplate && path.length === 1)
- lookupMethod = 'lookupTemplate';
- var code = 'Blaze.' + lookupMethod + '(' + args.join(', ') + ')';
-
- if (path.length > 1) {
- code = 'Spacebars.dot(' + code + ', ' +
- _.map(path.slice(1), BlazeTools.toJSLiteral).join(', ') + ')';
- }
-
- return code;
- },
-
- // Generates code for an `[argType, argValue]` argument spec,
- // ignoring the third element (keyword argument name) if present.
- //
- // The resulting code may be reactive (in the case of a PATH of
- // more than one element) and is not wrapped in a closure.
- codeGenArgValue: function (arg) {
- var self = this;
-
- var argType = arg[0];
- var argValue = arg[1];
-
- var argCode;
- switch (argType) {
- case 'STRING':
- case 'NUMBER':
- case 'BOOLEAN':
- case 'NULL':
- argCode = BlazeTools.toJSLiteral(argValue);
- break;
- case 'PATH':
- argCode = self.codeGenPath(argValue);
- break;
- default:
- // can't get here
- throw new Error("Unexpected arg type: " + argType);
- }
-
- return argCode;
- },
-
- // Generates a call to `Spacebars.fooMustache` on evaluated arguments.
- // The resulting code has no function literals and must be wrapped in
- // one for fine-grained reactivity.
- codeGenMustache: function (path, args, mustacheType) {
- var self = this;
-
- var nameCode = self.codeGenPath(path);
- var argCode = self.codeGenMustacheArgs(args);
- var mustache = (mustacheType || 'mustache');
-
- return 'Spacebars.' + mustache + '(' + nameCode +
- (argCode ? ', ' + argCode.join(', ') : '') + ')';
- },
-
- // returns: array of source strings, or null if no
- // args at all.
- codeGenMustacheArgs: function (tagArgs) {
- var self = this;
-
- var kwArgs = null; // source -> source
- var args = null; // [source]
-
- // tagArgs may be null
- _.each(tagArgs, function (arg) {
- var argCode = self.codeGenArgValue(arg);
-
- if (arg.length > 2) {
- // keyword argument (represented as [type, value, name])
- kwArgs = (kwArgs || {});
- kwArgs[arg[2]] = argCode;
- } else {
- // positional argument
- args = (args || []);
- args.push(argCode);
- }
- });
-
- // put kwArgs in options dictionary at end of args
- if (kwArgs) {
- args = (args || []);
- args.push('Spacebars.kw(' + makeObjectLiteral(kwArgs) + ')');
- }
-
- return args;
- },
-
- codeGenBlock: function (content) {
- return SpacebarsCompiler.codeGen(content, {codegen2: true});
- },
-
- // Takes an inclusion tag and returns an object containing these properties,
- // all optional, whose values are JS source code:
- //
- // - `dataFunc` - source code of a data function literal
- // - `content` - source code of a content block
- // - `elseContent` - source code of an elseContent block
- //
- // Implements the calling convention for inclusions.
- codeGenInclusionArgs: function (args) {
- var self = this;
-
- var dataFuncCode = null;
-
- if (! args.length) {
- // e.g. `{{#foo}}`
- return null;
- } else if (args[0].length === 3) {
- // keyword arguments only, e.g. `{{> point x=1 y=2}}`
- var dataProps = {};
- _.each(args, function (arg) {
- var argKey = arg[2];
- dataProps[argKey] = 'Spacebars.call(' + self.codeGenArgValue(arg) + ')';
- });
- dataFuncCode = makeObjectLiteral(dataProps);
- } else if (args[0][0] !== 'PATH') {
- // literal first argument, e.g. `{{> foo "blah"}}`
- //
- // tag validation has confirmed, in this case, that there is only
- // one argument (`args.length === 1`)
- dataFuncCode = self.codeGenArgValue(args[0]);
- } else if (args.length === 1) {
- // one argument, must be a PATH
- dataFuncCode = 'Spacebars.call(' + self.codeGenPath(args[0][1]) + ')';
- } else {
- // Multiple positional arguments; treat them as a nested
- // "data mustache"
- dataFuncCode = self.codeGenMustache(args[0][1], args.slice(1),
- 'dataMustache');
- }
-
- return dataFuncCode;
- }
-
-});
diff --git a/packages/spacebars-compiler/compiler.js b/packages/spacebars-compiler/compiler.js
index ee33aaf35d..5b3ec23562 100644
--- a/packages/spacebars-compiler/compiler.js
+++ b/packages/spacebars-compiler/compiler.js
@@ -44,9 +44,7 @@ SpacebarsCompiler.codeGen = function (parseTree, options) {
tree = SpacebarsCompiler.optimize(tree);
}
- var codegen = ((options && options.codegen2) ?
- new SpacebarsCompiler.CodeGen2 :
- new SpacebarsCompiler.CodeGen);
+ var codegen = new SpacebarsCompiler.CodeGen;
tree = (new SpacebarsCompiler._TemplateTagReplacer(
{codegen: codegen})).visit(tree);
diff --git a/packages/spacebars-compiler/package.js b/packages/spacebars-compiler/package.js
index e5404a6fac..b18fc8cfca 100644
--- a/packages/spacebars-compiler/package.js
+++ b/packages/spacebars-compiler/package.js
@@ -18,7 +18,6 @@ Package.on_use(function (api) {
api.add_files(['templatetag.js',
'optimizer.js',
'codegen.js',
- 'codegen2.js',
'compiler.js']);
});
diff --git a/packages/templating/plugin/html_scanner.js b/packages/templating/plugin/html_scanner.js
index 71c44197e9..4ca8f0276b 100644
--- a/packages/templating/plugin/html_scanner.js
+++ b/packages/templating/plugin/html_scanner.js
@@ -158,8 +158,7 @@ html_scanner = {
var renderFuncCode = SpacebarsCompiler.compile(
contents, {
isTemplate: true,
- sourceName: 'Template "' + name + '"',
- codegen2: true
+ sourceName: 'Template "' + name + '"'
});
results.js += "\nTemplate.__define__(" + JSON.stringify(name) +
@@ -172,8 +171,7 @@ html_scanner = {
var renderFuncCode = SpacebarsCompiler.compile(
contents, {
isBody: true,
- sourceName: "",
- codegen2: true
+ sourceName: ""
});
// We may be one of many `` tags.
diff --git a/packages/webapp/webapp_server.js b/packages/webapp/webapp_server.js
index 0929326154..4bbdb6900d 100644
--- a/packages/webapp/webapp_server.js
+++ b/packages/webapp/webapp_server.js
@@ -619,7 +619,7 @@ var runWebAppServer = function () {
var boilerplateTemplateSource = Assets.getText("boilerplate.html");
var boilerplateRenderCode = SpacebarsCompiler.compile(
- boilerplateTemplateSource, { isBody: true, codegen2: true });
+ boilerplateTemplateSource, { isBody: true });
// Note that we are actually depending on eval's local environment capture
// so that UI and HTML are visible to the eval'd code.