Skip to content

Commit

Permalink
Support objects created with Object.create(null) by following http://…
Browse files Browse the repository at this point in the history
  • Loading branch information
asprouse committed Jul 29, 2017
1 parent afdc5d9 commit c41ec38
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 8 deletions.
6 changes: 3 additions & 3 deletions src/compiler.js
Expand Up @@ -838,7 +838,7 @@ var Compiler = Object.extend({
'var callerFrame = frame;',
'frame = ' + ((keepFrame) ? 'frame.push(true);' : 'new runtime.Frame();'),
'kwargs = kwargs || {};',
'if (kwargs.hasOwnProperty("caller")) {',
'if (Object.prototype.hasOwnProperty.call(kwargs, "caller")) {',
'frame.set("caller", kwargs.caller); }'
);

Expand All @@ -856,7 +856,7 @@ var Compiler = Object.extend({
lib.each(kwargs.children, function(pair) {
var name = pair.key.value;
this.emit('frame.set("' + name + '", ' +
'kwargs.hasOwnProperty("' + name + '") ? ' +
'Object.prototype.hasOwnProperty.call(kwargs, "' + name + '") ? ' +
'kwargs["' + name + '"] : ');
this._compileExpression(pair.value, frame);
this.emitLine(');');
Expand Down Expand Up @@ -954,7 +954,7 @@ var Compiler = Object.extend({
alias = name;
}

this.emitLine('if(' + importedId + '.hasOwnProperty("' + name + '")) {');
this.emitLine('if(Object.prototype.hasOwnProperty.call(' + importedId + ', "' + name + '")) {');
this.emitLine('var ' + id + ' = ' + importedId + '.' + name + ';');
this.emitLine('} else {');
this.emitLine('cb(new Error("cannot import \'' + name + '\'")); return;');
Expand Down
2 changes: 1 addition & 1 deletion src/environment.js
Expand Up @@ -339,7 +339,7 @@ var Context = Obj.extend({
// Make a duplicate of ctx
this.ctx = {};
for(var k in ctx) {
if(ctx.hasOwnProperty(k)) {
if(Object.prototype.hasOwnProperty.call(ctx, k)) {
this.ctx[k] = ctx[k];
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/filters.js
Expand Up @@ -513,7 +513,7 @@ var filters = {
} else {
parts = [];
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
parts.push(enc(k) + '=' + enc(obj[k]));
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib.js
Expand Up @@ -277,7 +277,7 @@ exports.keys = function(obj) {
else {
var keys = [];
for(var k in obj) {
if(obj.hasOwnProperty(k)) {
if(Object.prototype.hasOwnProperty.call(obj, k)) {
keys.push(k);
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/runtime.js
Expand Up @@ -126,11 +126,15 @@ function makeKeywordArgs(obj) {
return obj;
}

function isKeywordArgs(obj) {
return obj && Object.prototype.hasOwnProperty.call(obj, '__keywords');
}

function getKeywordArgs(args) {
var len = args.length;
if(len) {
var lastArg = args[len - 1];
if(lastArg && lastArg.hasOwnProperty('__keywords')) {
if(isKeywordArgs(lastArg)) {
return lastArg;
}
}
Expand All @@ -144,7 +148,7 @@ function numArgs(args) {
}

var lastArg = args[len - 1];
if(lastArg && lastArg.hasOwnProperty('__keywords')) {
if(isKeywordArgs(lastArg)) {
return len - 1;
}
else {
Expand Down
16 changes: 16 additions & 0 deletions tests/compiler.js
Expand Up @@ -53,6 +53,22 @@
finish(done);
});

it('should compile references - object without prototype', function(done) {
var context = Object.create(null);
context.foo = Object.create(null);
context.foo.bar = 'baz';

equal('{{ foo.bar }}',
context,
'baz');

equal('{{ foo["bar"] }}',
context,
'baz');

finish(done);
});

it('should fail silently on undefined values', function(done) {
equal('{{ foo }}', '');
equal('{{ foo.bar }}', '');
Expand Down
9 changes: 9 additions & 0 deletions tests/filters.js
Expand Up @@ -586,6 +586,15 @@
finish(done);
});

it('urlencode - object without prototype', function(done) {
var obj = Object.create(null);
obj['1'] = 2;
obj['&1'] = '&2';

equal('{{ obj | urlencode | safe }}', { obj: obj}, '1=2&%261=%262');
finish(done);
});

it('urlize', function(done) {
// from jinja test suite:
// https://github.com/mitsuhiko/jinja2/blob/8db47916de0e888dd8664b2511e220ab5ecf5c15/jinja2/testsuite/filters.py#L236-L239
Expand Down
17 changes: 17 additions & 0 deletions tests/runtime.js
Expand Up @@ -76,5 +76,22 @@

finish(done);
});

it('should allow for objects without a prototype macro arguments in the last position', function(done) {
var noProto = Object.create(null);
noProto.qux = 'world';

render('{% macro foo(bar, baz) %}' +
'{{ bar }} {{ baz.qux }}{% endmacro %}' +
'{{ foo("hello", noProto) }}',
{noProto: noProto},
{ noThrow: true },
function(err, res) {
expect(err).to.equal(null);
expect(res).to.equal('hello world');
});

finish(done);
});
});
})();

0 comments on commit c41ec38

Please sign in to comment.