From a0204307c67cc1291957ce54a2a289077eaf06d7 Mon Sep 17 00:00:00 2001 From: David da Silva Date: Thu, 18 Dec 2014 02:48:16 +0100 Subject: [PATCH] fixing null and undefined lookup, fixes #390, #397, #409 --- mustache.js | 26 ++++++++++++++++++++----- test/_files/falsy_array.js | 10 ++++++++++ test/_files/falsy_array.mustache | 3 +++ test/_files/falsy_array.txt | 6 ++++++ test/_files/null_lookup_array.js | 9 +++++++++ test/_files/null_lookup_array.mustache | 3 +++ test/_files/null_lookup_array.txt | 3 +++ test/_files/null_lookup_object.js | 18 +++++++++++++++++ test/_files/null_lookup_object.mustache | 3 +++ test/_files/null_lookup_object.txt | 3 +++ 10 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 test/_files/falsy_array.js create mode 100644 test/_files/falsy_array.mustache create mode 100644 test/_files/falsy_array.txt create mode 100644 test/_files/null_lookup_array.js create mode 100644 test/_files/null_lookup_array.mustache create mode 100644 test/_files/null_lookup_array.txt create mode 100644 test/_files/null_lookup_object.js create mode 100644 test/_files/null_lookup_object.mustache create mode 100644 test/_files/null_lookup_object.txt diff --git a/mustache.js b/mustache.js index dbc9823..2aa2874 100644 --- a/mustache.js +++ b/mustache.js @@ -334,7 +334,7 @@ * maintaining a reference to the parent context. */ function Context(view, parentContext) { - this.view = view == null ? {} : view; + this.view = view; this.cache = { '.': this.view }; this.parent = parentContext; } @@ -358,7 +358,7 @@ if (name in cache) { value = cache[name]; } else { - var context = this, names, index; + var context = this, names, index, lookupHit = false; while (context) { if (name.indexOf('.') > 0) { @@ -366,13 +366,29 @@ names = name.split('.'); index = 0; - while (value != null && index < names.length) + /** + * Using the dot notion path in `name`, we descend through the + * nested objects. + * + * To be certain that the lookup has been successful, we have to + * check if the last object in the path actually has the property + * we are looking for. We store the result in `lookupHit`. + * + * This is specially necessary for when the value has been set to + * `undefined` and we want to avoid looking up parent contexts. + **/ + while (value != null && index < names.length) { + if (index === names.length - 1 && value != null) + lookupHit = (typeof value === 'object') && + value.hasOwnProperty(names[index]); value = value[names[index++]]; - } else if (typeof context.view == 'object') { + } + } else if (context.view != null && typeof context.view === 'object') { value = context.view[name]; + lookupHit = context.view.hasOwnProperty(name); } - if (value != null) + if (lookupHit) break; context = context.parent; diff --git a/test/_files/falsy_array.js b/test/_files/falsy_array.js new file mode 100644 index 0000000..f265308 --- /dev/null +++ b/test/_files/falsy_array.js @@ -0,0 +1,10 @@ +({ + "list": [ + ["", "emptyString"], + [[], "emptyArray"], + [0, "zero"], + [null, "null"], + [undefined, "undefined"], + [0/0, "NaN"] + ] +}) \ No newline at end of file diff --git a/test/_files/falsy_array.mustache b/test/_files/falsy_array.mustache new file mode 100644 index 0000000..2be7b37 --- /dev/null +++ b/test/_files/falsy_array.mustache @@ -0,0 +1,3 @@ +{{#list}} +{{#.}}{{#.}}{{.}}{{/.}}{{^.}}inverted {{/.}}{{/.}} +{{/list}} \ No newline at end of file diff --git a/test/_files/falsy_array.txt b/test/_files/falsy_array.txt new file mode 100644 index 0000000..6f24529 --- /dev/null +++ b/test/_files/falsy_array.txt @@ -0,0 +1,6 @@ +inverted emptyString +inverted emptyArray +inverted zero +inverted null +inverted undefined +inverted NaN diff --git a/test/_files/null_lookup_array.js b/test/_files/null_lookup_array.js new file mode 100644 index 0000000..9ebf56a --- /dev/null +++ b/test/_files/null_lookup_array.js @@ -0,0 +1,9 @@ +({ + "name": "David", + "twitter": "@dasilvacontin", + "farray": [ + ["Flor", "@florrts"], + ["Miquel", null], + ["Chris", undefined] + ] +}) diff --git a/test/_files/null_lookup_array.mustache b/test/_files/null_lookup_array.mustache new file mode 100644 index 0000000..0543895 --- /dev/null +++ b/test/_files/null_lookup_array.mustache @@ -0,0 +1,3 @@ +{{#farray}} +{{#.}}{{#.}}{{.}} {{/.}}{{^.}}no twitter{{/.}}{{/.}} +{{/farray}} diff --git a/test/_files/null_lookup_array.txt b/test/_files/null_lookup_array.txt new file mode 100644 index 0000000..94edf99 --- /dev/null +++ b/test/_files/null_lookup_array.txt @@ -0,0 +1,3 @@ +Flor @florrts +Miquel no twitter +Chris no twitter diff --git a/test/_files/null_lookup_object.js b/test/_files/null_lookup_object.js new file mode 100644 index 0000000..2f758a5 --- /dev/null +++ b/test/_files/null_lookup_object.js @@ -0,0 +1,18 @@ +({ + "name": "David", + "twitter": "@dasilvacontin", + "fobject": [ + { + "name": "Flor", + "twitter": "@florrts" + }, + { + "name": "Miquel", + "twitter": null + }, + { + "name": "Chris", + "twitter": undefined + } + ] +}) diff --git a/test/_files/null_lookup_object.mustache b/test/_files/null_lookup_object.mustache new file mode 100644 index 0000000..e709ae4 --- /dev/null +++ b/test/_files/null_lookup_object.mustache @@ -0,0 +1,3 @@ +{{#fobject}} +{{name}}'s twitter: {{#twitter}}{{.}}{{/twitter}}{{^twitter}}unknown{{/twitter}}. +{{/fobject}} diff --git a/test/_files/null_lookup_object.txt b/test/_files/null_lookup_object.txt new file mode 100644 index 0000000..c1c727b --- /dev/null +++ b/test/_files/null_lookup_object.txt @@ -0,0 +1,3 @@ +Flor's twitter: @florrts. +Miquel's twitter: unknown. +Chris's twitter: unknown.