diff --git a/mustache.js b/mustache.js index e45861f..433714b 100644 --- a/mustache.js +++ b/mustache.js @@ -51,8 +51,8 @@ */ function primitiveHasOwnProperty (primitive, propName) { return ( - typeof primitive !== 'object' - && primitive !== undefined + primitive != null + && typeof primitive !== 'object' && primitive.hasOwnProperty && primitive.hasOwnProperty(propName) ); @@ -408,6 +408,12 @@ * * This is specially necessary for when the value has been set to * `undefined` and we want to avoid looking up parent contexts. + * + * In the case where dot notation is used, we consider the lookup + * to be successful even if the last "object" in the path is + * not actually an object but a primitive (e.g., a string, or an + * integer), because it is sometimes useful to access a property + * of an autoboxed primitive, such as the length of a string. **/ while (intermediateValue != null && index < names.length) { if (index === names.length - 1) @@ -420,6 +426,19 @@ } } else { intermediateValue = context.view[name]; + + /** + * Only checking against hasProperty, which always returns false if + * context.view is not an object. Deliberately omitting the check + * against primitiveHasOwnProperty if dot notation is not used. + * + * Consider this example: + * Mustache.render("{{#length}}{{length}}{{/length}}", {length: "hello"}) + * + * If we were to check also against primitiveHasOwnProperty, as we do + * in the dot notation case, then render call would return 5, rather + * than the expected "hello". + **/ lookupHit = hasProperty(context.view, name); }