Permalink
Browse files

Update uglify-js dependency version

Compiler now inserts `__.bd=1` into templates if they contain any block declarations, even if the block is not declared at runtime
Cleanup runtime: remove unsafe block action stuff, etc.
Includes now check `info.bd` to see if the included template contains any block declarations; if not, the included HTML can be safely captured and wrapped in a branch label (closes #116)
"foreach" items are now separately reactive and wrapped in `LiveUpdate.isolate` calls
  • Loading branch information...
bminer committed Jan 8, 2013
1 parent dc62e5a commit d28c5a75faebff6cd3d022a3b4ffc65a6d3a582e
Showing with 43 additions and 30 deletions.
  1. +4 −0 lib/compiler.js
  2. +37 −28 lib/runtime.js
  3. +2 −2 package.json
View
@@ -83,6 +83,7 @@ Compiler.prototype.compile = function(cb) {
try {
//Convert to JS function
this.buf = "";
+ this.blockDeclarations = false;
this._pushOff(ns + ' = ' + ns + ' || [];' + //Define ns as an array
ns + '.r = ' + ns + '.r || blade.Runtime;' + //Define ns.r to point to the runtime
'if(!' + ns + '.func) ' + ns + '.func = {},' + //Define ns.func to hold all functions
@@ -112,6 +113,8 @@ Compiler.prototype.compile = function(cb) {
this._pushOff("} catch(e){return cb(" + ns + ".r.rethrow(e, " + ns + ") );}");
//End of template callback
this._pushOff('if(!' + ns + '.inc) ' + ns + '.r.done(' + ns + ');');
+ if(this.blockDeclarations)
+ this._pushOff(ns + '.bd = 1;');
this._pushOff('cb(null, ' + ns + '.join(""), ' + ns + ');');
//Add base and rel properties to buffer if includes were used
if(this.includes > 0)
@@ -477,6 +480,7 @@ Compiler.prototype._compileNode = function(node) {
}
break;
case 'block':
+ this.blockDeclarations = true;
var paramStr = node.parameters == null ? "" : "," + node.parameters.join(",");
this._pushOff(ns + ".r.blockDef(" + JSON.stringify(node.name) + ", " + ns +
", function(" + ns + paramStr + ") {");
View
@@ -341,9 +341,7 @@
pLine = info.line,
pCol = info.col,
pSource = info.source,
- pLocals = info.locals,
- pUnsafeBlockAction = info.unsafeBlockAction,
- pPreserve = info.preserve;
+ pLocals = info.locals;
info.inc = true;
//If exposing locals, the included view gets its own set of locals
if(arguments.length > 2)
@@ -356,6 +354,7 @@
var sync = runtime.loadTemplate(info.base, info.rel + "/" + relFilename,
runtime.compileOptions, function(err, tmpl) {
if(err) throw err;
+ var len = info.length;
tmpl(info.locals, function(err, html) {
//This is run after the template has been rendered
if(err) throw err;
@@ -368,8 +367,13 @@
info.col = pCol;
info.source = pSource;
info.locals = pLocals;
- info.unsafeBlockAction = pUnsafeBlockAction;
- info.preserve = pPreserve;
+ //If the file did not declare any blocks, capture output as HTML and add a branch label
+ if(!info.bd)
+ {
+ html = runtime.capture(info, len);
+ info.push(liveUpdate.labelBranch(info.filename + ":" + info.line + ":inc:" + relFilename,
+ function() {return html;}) );
+ }
}, info);
});
if(!sync) throw new Error("Included file [" + info.rel + "/" + relFilename +
@@ -444,23 +448,35 @@
};
};
- /* Define an isolate block */
- runtime.isolate = function(func, buf) {
- buf.push(liveUpdate.isolate(function() {
+ /* isolateWrapper is a helper function
+ - func - a function to be called anytime its data dependencies change
+ - buf - the template buffer
+ Returns HTML generated by liveUpdate.isolate(...)
+ */
+ function isolateWrapper(func, buf, disableReactivity) {
+ function wrapper() {
+ //Temporarily make blocks inaccessible to func()
+ var blocks = buf.blocks;
+ buf.blocks = {};
/* Note: This following line is the same as:
var len = buf.length;
func();
return runtime.capture(buf, len);
*/
- return runtime.capture(buf, buf.length, func() );
- }) );
+ var html = runtime.capture(buf, buf.length, func() );
+ //Restore blocks
+ buf.blocks = blocks;
+ return html;
+ }
+ return disableReactivity ? wrapper() : liveUpdate.isolate(wrapper);
+ }
+ /* Define an isolate block */
+ runtime.isolate = function(func, buf) {
+ buf.push(isolateWrapper(func, buf) );
};
/* Define a constant block */
runtime.constant = function(label, func, buf) {
- if(buf.unsafeBlockAction)
- throw new Error("You cannot preserve elements here because this template either defines a block or performs a block modification.");
- buf.preserve = true;
buf.push(liveUpdate.labelBranch(buf.filename + ":" + label, function () {
return liveUpdate.createLandmark({"constant": true}, function(landmark) {
/* Note: This following line is the same as:
@@ -475,9 +491,6 @@
/* Define a preserve block */
runtime.preserve = function(label, preserved, func, buf) {
- if(buf.unsafeBlockAction)
- throw new Error("You cannot preserve elements here because this template either defines a block or performs a block modification.");
- buf.preserve = true;
buf.push(liveUpdate.labelBranch(buf.filename + ":" + label, function () {
return liveUpdate.createLandmark({"preserve": preserved}, function(landmark) {
/* Note: This following line is the same as:
@@ -492,23 +505,28 @@
/* Foreach/else block */
runtime.foreach = function(buf, cursor, itemFunc, elseFunc) {
+ var disableReactivity = false;
//Define wrapper functions for itemFunc and elseFunc
function itemFuncWrapper(item) {
- var label = (item._id || (typeof item === 'string' ? item : null) || liveUpdate.UNIQUE_LABEL);
+ var label = item._id || (typeof item === "string" ? item : null) ||
+ liveUpdate.UNIQUE_LABEL;
return liveUpdate.labelBranch(label, function() {
- return runtime.capture(buf, buf.length, itemFunc.call(item, item) );
+ return isolateWrapper(function() {
+ return itemFunc.call(item, item);
+ }, buf, disableReactivity);
});
}
function elseFuncWrapper() {
return liveUpdate.labelBranch("else", function() {
- return elseFunc ? runtime.capture(buf, buf.length, elseFunc() ) : "";
+ return elseFunc ? isolateWrapper(elseFunc, buf, disableReactivity) : "";
});
}
//Call liveUpdate.list for Cursor Objects
if(cursor && "observe" in cursor)
buf.push(liveUpdate.list(cursor, itemFuncWrapper, elseFuncWrapper) );
else
{
+ disableReactivity = true;
//Allow non-Cursor Objects or Arrays to work, as well
var html = "", empty = 1;
for(var i in cursor)
@@ -534,9 +552,6 @@
/* Defines a block */
runtime.blockDef = function(blockName, buf, childFunc) {
- if(buf.preserve)
- throw new Error("You cannot define a block in this template because element preservation is being used.");
- buf.unsafeBlockAction = true;
var block = buf.blocks[blockName] = {
'parent': buf.block || null, //set parent block
'buf': [], //block get its own buffer
@@ -572,15 +587,12 @@
"r" ==> replace
*/
runtime.blockRender = function(type, blockName, buf) {
- if(buf.preserve)
- throw new Error("You cannot render a block in this template because element preservation is being used.");
var block = buf.blocks[blockName];
if(block == null)
throw new Error("Block '" + blockName + "' is undefined.");
if(block.paramBlock == null)
throw new Error("Block '" + blockName +
"' is a regular, non-parameterized block, which cannot be rendered.");
- buf.unsafeBlockAction = true;
//Extract arguments
var args = [block.buf];
for(var i = 3; i < arguments.length; i++)
@@ -613,12 +625,9 @@
"r" ==> replace
*/
runtime.blockMod = function(type, blockName, buf, childFunc) {
- if(buf.preserve)
- throw new Error("You cannot modify a block in this template because element preservation is being used.");
var block = buf.blocks[blockName];
if(block == null)
throw new Error("Block '" + blockName + "' is undefined.");
- buf.unsafeBlockAction = true;
if(type == "r") //replace
{
//Empty buffer and delete parameterized block function
View
@@ -29,10 +29,10 @@
},
"devDependencies": {
"pegjs": ">=0.7",
- "uglify-js": ">=2.3 || >=1.2 <2"
+ "uglify-js": ">=2.2.3 || >=1.2 <2"
},
"optionalDependencies": {
- "uglify-js": ">=2.3 || >=1.2 <2"
+ "uglify-js": ">=2.2.3 || >=1.2 <2"
},
"engines": {
"node": ">=0.6"

0 comments on commit d28c5a7

Please sign in to comment.