Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add context.clone and context.pop #559

Merged
merged 1 commit into from
Mar 24, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 47 additions & 27 deletions lib/dust.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,25 @@
return (!value);
};

dust.isEmptyObject = function(obj) {
var key;
if (obj === null) {
return false;
}
if (obj === undefined) {
return false;
}
if (obj.length > 0) {
return false;
}
for (key in obj) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object.keys is available in IE9+

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, my first version used Object.keys, but I benchmarked:

https://jsperf.com/empty-object-comparisons/8

if (Object.prototype.hasOwnProperty.call(obj, key)) {
return false;
}
}
return true;
};

// apply the filter chain and return the output string
dust.filter = function(string, auto, filters) {
if (filters) {
Expand Down Expand Up @@ -308,7 +327,7 @@
* @return {string | object}
*/
Context.prototype._get = function(cur, down) {
var ctx = this.stack,
var ctx = this.stack || {},
i = 1,
value, first, len, ctxThis, fn;
first = down[0];
Expand Down Expand Up @@ -381,12 +400,24 @@
return new Context(new Stack(head, this.stack, idx, len), this.global, this.blocks, this.getTemplateName());
};

Context.prototype.pop = function() {
var head = this.current();
this.stack = this.stack && this.stack.tail;
return head;
};

Context.prototype.rebase = function(head) {
return new Context(new Stack(head), this.global, this.blocks, this.getTemplateName());
};

Context.prototype.clone = function() {
var context = this.rebase();
context.stack = this.stack;
return context;
};

Context.prototype.current = function() {
return this.stack.head;
return this.stack && this.stack.head;
};

Context.prototype.getBlock = function(key, chk, ctx) {
Expand Down Expand Up @@ -743,37 +774,26 @@
};

Chunk.prototype.partial = function(elem, context, params) {
var partialContext;
//put the params context second to match what section does. {.} matches the current context without parameters
// start with an empty context
partialContext = dust.makeBase(context.global);
partialContext.blocks = context.blocks;
if (context.stack && context.stack.tail){
// grab the stack(tail) off of the previous context if we have it
partialContext.stack = context.stack.tail;
}
if (params){
//put params on
partialContext = partialContext.push(params);
}
var head;

if(typeof elem === 'string') {
partialContext.templateName = elem;
if (!dust.isEmptyObject(params)) {
context = context.clone();
head = context.pop();
context = context.push(params)
.push(head);
}

//reattach the head
partialContext = partialContext.push(context.stack.head);

var partialChunk;
if (typeof elem === 'function') {
partialChunk = this.capture(elem, partialContext, function(name, chunk) {
partialContext.templateName = partialContext.templateName || name;
dust.load(name, chunk, partialContext).end();
if (elem.__dustBody) {
// The eventual result of evaluating `elem` is a partial name
// Load the partial after getting its name and end the async chunk
return this.capture(elem, context, function(name, chunk) {
context.templateName = name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

be careful when you add the template name. This looks to tack templateName after the head is reattached.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The templateName is stored outside of the stack, so there shouldn't be any effect by attaching it at an arbitrary time as it's not part of the stack traversal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(and this was done in the same way before on line old:770)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to find old: 760-762

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That logic was "if the partial name is already a string, e.g. {>foo/}, just set the template name with it."

It's now on line new:794

dust.load(name, chunk, context).end();
});
} else {
partialChunk = dust.load(elem, this, partialContext);
context.templateName = elem;
return dust.load(elem, this, context);
}
return partialChunk;
};

Chunk.prototype.helper = function(name, context, bodies, params) {
Expand Down
9 changes: 8 additions & 1 deletion test/jasmine-test/spec/coreTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1056,11 +1056,18 @@ var coreTests = [
tests : [
{
name: "partials",
source: '{>partial/} {>"hello_world"/} {>"{ref}"/}',
source: '{>partial foo=0 /} {>"hello_world" foo=1 /} {>"{ref}" foo=2 /}',
context: { name: "Jim", count: 42, ref: "hello_world" },
expected: "Hello Jim! You have 42 new messages. Hello World! Hello World!",
message: "should test partials"
},
{
name: "partial with async ref as name",
source: '{>"{ref}" /}',
context: { ref: function(chunk, context) { return chunk.map(function(chunk) { setTimeout(function() { chunk.end('hello_world'); }) }); }},
expected: "Hello World!",
message: "should test partial with an asynchronously-resolved template name"
},
{
name: "partial with context",
source: "{>partial:.profile/}",
Expand Down
4 changes: 3 additions & 1 deletion test/jasmine-test/spec/renderTestSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ function render(test) {
err = err.message || err;
expect(err).toContain(test.error);
} else {
expect(err).toBeNull();
if(err) {
expect(err.message).toBeNull();
}
}
if (test.log) {
for(var i=0; i<log.length; i++) {
Expand Down