From 1dc417f1a5b4ec5a81bc3113e63476b18d0efc17 Mon Sep 17 00:00:00 2001 From: Paul Lynch Date: Mon, 16 Nov 2015 18:23:25 -0500 Subject: Update uglify-js to avoid vulnerability --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6053803..1da9b09 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "source-map": "^0.4.4" }, "optionalDependencies": { - "uglify-js": "~2.4" + "uglify-js": "~2.6" }, "devDependencies": { "aws-sdk": "^2.1.49", -- cgit v1.1 From c21118d04bcd42c385536a2dcbab1a0f5ee68c57 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Thu, 19 Nov 2015 22:53:23 -0600 Subject: Include tests for minimized artifacts --- Gruntfile.js | 2 +- spec/env/browser.js | 7 ++++++- spec/env/runner.js | 24 ++++++++++++++++++++---- spec/env/runtime.js | 7 ++++++- tasks/test.js | 11 +++++++++++ 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 3bb1c16..1b705c4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -211,7 +211,7 @@ module.exports = function(grunt) { this.registerTask('globals', ['webpack']); this.registerTask('tests', ['concat:tests']); - this.registerTask('release', 'Build final packages', ['eslint', 'amd', 'uglify', 'copy:dist', 'copy:components', 'copy:cdnjs']); + this.registerTask('release', 'Build final packages', ['eslint', 'amd', 'uglify', 'test:min', 'copy:dist', 'copy:components', 'copy:cdnjs']); // Load tasks from npm grunt.loadNpmTasks('grunt-contrib-clean'); diff --git a/spec/env/browser.js b/spec/env/browser.js index 8049dda..60a5d35 100644 --- a/spec/env/browser.js +++ b/spec/env/browser.js @@ -4,7 +4,12 @@ var fs = require('fs'), vm = require('vm'); global.Handlebars = 'no-conflict'; -vm.runInThisContext(fs.readFileSync(__dirname + '/../../dist/handlebars.js'), 'dist/handlebars.js'); + +var filename = 'dist/handlebars.js'; +if (global.minimizedTest) { + filename = 'dist/handlebars.min.js'; +} +vm.runInThisContext(fs.readFileSync(__dirname + '/../../' + filename), filename); global.CompilerContext = { browser: true, diff --git a/spec/env/runner.js b/spec/env/runner.js index 4ff1e7e..f4b23d8 100644 --- a/spec/env/runner.js +++ b/spec/env/runner.js @@ -7,19 +7,35 @@ var errors = 0, testDir = path.dirname(__dirname), grep = process.argv[2]; +// Lazy hack, but whatever +if (grep === '--min') { + global.minimizedTest = true; + grep = undefined; +} + var files = fs.readdirSync(testDir) .filter(function(name) { return (/.*\.js$/).test(name); }) .map(function(name) { return testDir + '/' + name; }); -run('./runtime', function() { - run('./browser', function() { - run('./node', function() { +if (global.minimizedTest) { + run('./runtime', function() { + run('./browser', function() { /* eslint-disable no-process-exit */ process.exit(errors); /* eslint-enable no-process-exit */ }); }); -}); +} else { + run('./runtime', function() { + run('./browser', function() { + run('./node', function() { + /* eslint-disable no-process-exit */ + process.exit(errors); + /* eslint-enable no-process-exit */ + }); + }); + }); +} function run(env, callback) { diff --git a/spec/env/runtime.js b/spec/env/runtime.js index 9d1c049..642acd3 100644 --- a/spec/env/runtime.js +++ b/spec/env/runtime.js @@ -4,7 +4,12 @@ var fs = require('fs'), vm = require('vm'); global.Handlebars = 'no-conflict'; -vm.runInThisContext(fs.readFileSync(__dirname + '/../../dist/handlebars.runtime.js'), 'dist/handlebars.runtime.js'); + +var filename = 'dist/handlebars.runtime.js'; +if (global.minimizedTest) { + filename = 'dist/handlebars.runtime.min.js'; +} +vm.runInThisContext(fs.readFileSync(__dirname + '/../../' + filename), filename); var parse = require('../../dist/cjs/handlebars/compiler/base').parse; var compiler = require('../../dist/cjs/handlebars/compiler/compiler'); diff --git a/tasks/test.js b/tasks/test.js index 7d6659b..18a6c26 100644 --- a/tasks/test.js +++ b/tasks/test.js @@ -40,6 +40,17 @@ module.exports = function(grunt) { done(); }); }); + grunt.registerTask('test:min', function() { + var done = this.async(); + + var runner = childProcess.fork('./spec/env/runner', ['--min'], {stdio: 'inherit'}); + runner.on('close', function(code) { + if (code != 0) { + grunt.fatal(code + ' tests failed'); + } + done(); + }); + }); grunt.registerTask('test:check-cov', function() { var done = this.async(); -- cgit v1.1 From 251ec3b1288f4392ea63eba4fd3334efd1710318 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Thu, 19 Nov 2015 22:54:10 -0600 Subject: Work around uglify preserveComments some issue Root cause: https://github.com/gruntjs/grunt-contrib-uglify/issues/366 Fixes #1129 --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 1b705c4..fd76518 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -125,7 +125,7 @@ module.exports = function(grunt) { options: { mangle: true, compress: true, - preserveComments: 'some' + preserveComments: /(?:^!|@(?:license|preserve|cc_on))/ }, dist: { files: [{ -- cgit v1.1 From 0a3b3c28312d57f1bae1d4089341c6c417c57b84 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Thu, 19 Nov 2015 22:54:39 -0600 Subject: Further relax uglify dependency --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1da9b09..75cb456 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "source-map": "^0.4.4" }, "optionalDependencies": { - "uglify-js": "~2.6" + "uglify-js": "^2.6" }, "devDependencies": { "aws-sdk": "^2.1.49", -- cgit v1.1 From 7a6c22859279b42f5a12eef06cc99999e3152461 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Thu, 19 Nov 2015 22:55:03 -0600 Subject: Add webpack to dev dependency to support npm 3 --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 75cb456..3c86e73 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,9 @@ "mock-stdin": "^0.3.0", "mustache": "^2.1.3", "semver": "^5.0.1", - "underscore": "^1.5.1" + "underscore": "^1.5.1", + "webpack": "^1.12.6", + "webpack-dev-server": "^1.12.1" }, "main": "lib/index.js", "bin": { -- cgit v1.1 From 685cf92bcb67aba80665fc48bd6565a946ab32b7 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Thu, 19 Nov 2015 22:58:26 -0600 Subject: Return current handlebars instance from noConflict Fixes wycats/handlebars-site#131 --- lib/handlebars/no-conflict.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/handlebars/no-conflict.js b/lib/handlebars/no-conflict.js index ad41e96..40a44d7 100644 --- a/lib/handlebars/no-conflict.js +++ b/lib/handlebars/no-conflict.js @@ -8,5 +8,6 @@ export default function(Handlebars) { if (root.Handlebars === Handlebars) { root.Handlebars = $Handlebars; } + return Handlebars; }; } -- cgit v1.1 From ddaff8ea2987812f600dbbace75c71f805cf67f7 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Thu, 19 Nov 2015 23:06:29 -0600 Subject: Update release notes --- release-notes.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/release-notes.md b/release-notes.md index 5ea873e..497f5e8 100644 --- a/release-notes.md +++ b/release-notes.md @@ -2,7 +2,19 @@ ## Development -[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.4...master) +[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.5...master) + +## v4.0.5 - November 19th, 2015 +- [#1132](https://github.com/wycats/handlebars.js/pull/1132) - Update uglify-js to avoid vulnerability ([@plynchnlm](https://api.github.com/users/plynchnlm)) +- [#1129](https://github.com/wycats/handlebars.js/issues/1129) - Minified lib returns an empty string ([@bricss](https://api.github.com/users/bricss)) +- Return current handlebars instance from noConflict - 685cf92 +- Add webpack to dev dependency to support npm 3 - 7a6c228 +- Further relax uglify dependency - 0a3b3c2 +- Include tests for minimized artifacts - c21118d +- Fix lint errors under latest eslint - 9f59de9 +- Add print-script helper script - 98a6717 + +[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.4...v4.0.5) ## v4.0.4 - October 29th, 2015 - [#1121](https://github.com/wycats/handlebars.js/pull/1121) - Include partial name in 'undefined partial' exception message ([@shinypb](https://api.github.com/users/shinypb)) -- cgit v1.1 From 205c61cfb1acdb599bbdfcf2d356641254e09e5c Mon Sep 17 00:00:00 2001 From: kpdecker Date: Thu, 19 Nov 2015 23:06:54 -0600 Subject: v4.0.5 --- components/bower.json | 2 +- components/handlebars.js.nuspec | 2 +- lib/handlebars/base.js | 2 +- package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/bower.json b/components/bower.json index e4aaab9..840c772 100644 --- a/components/bower.json +++ b/components/bower.json @@ -1,6 +1,6 @@ { "name": "handlebars", - "version": "4.0.4", + "version": "4.0.5", "main": "handlebars.js", "license": "MIT", "dependencies": {} diff --git a/components/handlebars.js.nuspec b/components/handlebars.js.nuspec index 326827e..9ede3d6 100644 --- a/components/handlebars.js.nuspec +++ b/components/handlebars.js.nuspec @@ -2,7 +2,7 @@ handlebars.js - 4.0.4 + 4.0.5 handlebars.js Authors https://github.com/wycats/handlebars.js/blob/master/LICENSE https://github.com/wycats/handlebars.js/ diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js index 84a8915..836422d 100644 --- a/lib/handlebars/base.js +++ b/lib/handlebars/base.js @@ -4,7 +4,7 @@ import {registerDefaultHelpers} from './helpers'; import {registerDefaultDecorators} from './decorators'; import logger from './logger'; -export const VERSION = '4.0.4'; +export const VERSION = '4.0.5'; export const COMPILER_REVISION = 7; export const REVISION_CHANGES = { diff --git a/package.json b/package.json index 3c86e73..a5b7887 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "handlebars", "barename": "handlebars", - "version": "4.0.4", + "version": "4.0.5", "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration", "homepage": "http://www.handlebarsjs.com/", "keywords": [ -- cgit v1.1 From 3f77b82ed00dc1d71976de76bd4f8dfb6e885f2a Mon Sep 17 00:00:00 2001 From: machty Date: Thu, 10 Dec 2015 12:25:20 -0500 Subject: Remove stringParams and trackIds mode Closes #1145 --- lib/handlebars/compiler/compiler.js | 46 +---- lib/handlebars/compiler/javascript-compiler.js | 106 +---------- lib/handlebars/helpers/block-helper-missing.js | 12 +- lib/handlebars/helpers/each.js | 15 +- lib/handlebars/helpers/with.js | 8 +- lib/handlebars/runtime.js | 6 - lib/handlebars/utils.js | 8 - print-script | 1 - spec/string-params.js | 176 ------------------ spec/subexpressions.js | 44 ----- spec/track-ids.js | 237 ------------------------- 11 files changed, 8 insertions(+), 651 deletions(-) delete mode 100644 spec/string-params.js delete mode 100644 spec/track-ids.js diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js index 987d0d4..9fa9dd8 100644 --- a/lib/handlebars/compiler/compiler.js +++ b/lib/handlebars/compiler/compiler.js @@ -49,8 +49,6 @@ Compiler.prototype = { this.opcodes = []; this.children = []; this.options = options; - this.stringParams = options.stringParams; - this.trackIds = options.trackIds; options.blockParams = options.blockParams || []; @@ -393,49 +391,7 @@ Compiler.prototype = { }, pushParam: function(val) { - let value = val.value != null ? val.value : val.original || ''; - - if (this.stringParams) { - if (value.replace) { - value = value - .replace(/^(\.?\.\/)*/g, '') - .replace(/\//g, '.'); - } - - if (val.depth) { - this.addDepth(val.depth); - } - this.opcode('getContext', val.depth || 0); - this.opcode('pushStringParam', value, val.type); - - if (val.type === 'SubExpression') { - // SubExpressions get evaluated and passed in - // in string params mode. - this.accept(val); - } - } else { - if (this.trackIds) { - let blockParamIndex; - if (val.parts && !AST.helpers.scopedId(val) && !val.depth) { - blockParamIndex = this.blockParamIndex(val.parts[0]); - } - if (blockParamIndex) { - let blockParamChild = val.parts.slice(1).join('.'); - this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild); - } else { - value = val.original || value; - if (value.replace) { - value = value - .replace(/^this(?:\.|$)/, '') - .replace(/^\.\//, '') - .replace(/^\.$/, ''); - } - - this.opcode('pushId', val.type, value); - } - } - this.accept(val); - } + this.accept(val); }, setupFullMustacheParams: function(sexpr, program, inverse, omitEmpty) { diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js index 97939df..1708032 100644 --- a/lib/handlebars/compiler/javascript-compiler.js +++ b/lib/handlebars/compiler/javascript-compiler.js @@ -57,8 +57,6 @@ JavaScriptCompiler.prototype = { compile: function(environment, options, context, asObject) { this.environment = environment; this.options = options; - this.stringParams = this.options.stringParams; - this.trackIds = this.options.trackIds; this.precompile = !asObject; this.name = this.environment.name; @@ -498,37 +496,7 @@ JavaScriptCompiler.prototype = { this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']); }, - // [pushStringParam] - // - // On stack, before: ... - // On stack, after: string, currentContext, ... - // - // This opcode is designed for use in string mode, which - // provides the string value of a parameter along with its - // depth rather than resolving it immediately. - pushStringParam: function(string, type) { - this.pushContext(); - this.pushString(type); - - // If it's a subexpression, the string result - // will be pushed after this opcode. - if (type !== 'SubExpression') { - if (typeof string === 'string') { - this.pushString(string); - } else { - this.pushStackLiteral(string); - } - } - }, - emptyHash: function(omitEmpty) { - if (this.trackIds) { - this.push('{}'); // hashIds - } - if (this.stringParams) { - this.push('{}'); // hashContexts - this.push('{}'); // hashTypes - } this.pushStackLiteral(omitEmpty ? 'undefined' : '{}'); }, pushHash: function() { @@ -541,14 +509,6 @@ JavaScriptCompiler.prototype = { let hash = this.hash; this.hash = this.hashes.pop(); - if (this.trackIds) { - this.push(this.objectLiteral(hash.ids)); - } - if (this.stringParams) { - this.push(this.objectLiteral(hash.contexts)); - this.push(this.objectLiteral(hash.types)); - } - this.push(this.objectLiteral(hash.values)); }, @@ -727,44 +687,7 @@ JavaScriptCompiler.prototype = { // // Pops a value off the stack and assigns it to the current hash assignToHash: function(key) { - let value = this.popStack(), - context, - type, - id; - - if (this.trackIds) { - id = this.popStack(); - } - if (this.stringParams) { - type = this.popStack(); - context = this.popStack(); - } - - let hash = this.hash; - if (context) { - hash.contexts[key] = context; - } - if (type) { - hash.types[key] = type; - } - if (id) { - hash.ids[key] = id; - } - hash.values[key] = value; - }, - - pushId: function(type, name, child) { - if (type === 'BlockParam') { - this.pushStackLiteral( - 'blockParams[' + name[0] + '].path[' + name[1] + ']' - + (child ? ' + ' + JSON.stringify('.' + child) : '')); - } else if (type === 'PathExpression') { - this.pushString(name); - } else if (type === 'SubExpression') { - this.pushStackLiteral('true'); - } else { - this.pushStackLiteral('null'); - } + this.hash.values[key] = this.popStack(); }, // HELPERS @@ -997,9 +920,6 @@ JavaScriptCompiler.prototype = { setupParams: function(helper, paramSize, params) { let options = {}, - contexts = [], - types = [], - ids = [], objectArgs = !params, param; @@ -1010,14 +930,6 @@ JavaScriptCompiler.prototype = { options.name = this.quotedString(helper); options.hash = this.popStack(); - if (this.trackIds) { - options.hashIds = this.popStack(); - } - if (this.stringParams) { - options.hashTypes = this.popStack(); - options.hashContexts = this.popStack(); - } - let inverse = this.popStack(), program = this.popStack(); @@ -1034,28 +946,12 @@ JavaScriptCompiler.prototype = { while (i--) { param = this.popStack(); params[i] = param; - - if (this.trackIds) { - ids[i] = this.popStack(); - } - if (this.stringParams) { - types[i] = this.popStack(); - contexts[i] = this.popStack(); - } } if (objectArgs) { options.args = this.source.generateArray(params); } - if (this.trackIds) { - options.ids = this.source.generateArray(ids); - } - if (this.stringParams) { - options.types = this.source.generateArray(types); - options.contexts = this.source.generateArray(contexts); - } - if (this.options.data) { options.data = 'data'; } diff --git a/lib/handlebars/helpers/block-helper-missing.js b/lib/handlebars/helpers/block-helper-missing.js index 6639ddb..e6d162f 100644 --- a/lib/handlebars/helpers/block-helper-missing.js +++ b/lib/handlebars/helpers/block-helper-missing.js @@ -1,4 +1,4 @@ -import {appendContextPath, createFrame, isArray} from '../utils'; +import {isArray} from '../utils'; export default function(instance) { instance.registerHelper('blockHelperMissing', function(context, options) { @@ -11,21 +11,11 @@ export default function(instance) { return inverse(this); } else if (isArray(context)) { if (context.length > 0) { - if (options.ids) { - options.ids = [options.name]; - } - return instance.helpers.each(context, options); } else { return inverse(this); } } else { - if (options.data && options.ids) { - let data = createFrame(options.data); - data.contextPath = appendContextPath(options.data.contextPath, options.name); - options = {data: data}; - } - return fn(context, options); } }); diff --git a/lib/handlebars/helpers/each.js b/lib/handlebars/helpers/each.js index fb11903..914928d 100644 --- a/lib/handlebars/helpers/each.js +++ b/lib/handlebars/helpers/each.js @@ -1,4 +1,4 @@ -import {appendContextPath, blockParams, createFrame, isArray, isFunction} from '../utils'; +import {createFrame, isArray, isFunction} from '../utils'; import Exception from '../exception'; export default function(instance) { @@ -11,12 +11,7 @@ export default function(instance) { inverse = options.inverse, i = 0, ret = '', - data, - contextPath; - - if (options.data && options.ids) { - contextPath = appendContextPath(options.data.contextPath, options.ids[0]) + '.'; - } + data; if (isFunction(context)) { context = context.call(this); } @@ -30,15 +25,11 @@ export default function(instance) { data.index = index; data.first = index === 0; data.last = !!last; - - if (contextPath) { - data.contextPath = contextPath + field; - } } ret = ret + fn(context[field], { data: data, - blockParams: blockParams([context[field], field], [contextPath + field, null]) + blockParams: [context[field], field] }); } diff --git a/lib/handlebars/helpers/with.js b/lib/handlebars/helpers/with.js index 7418cd0..bb352c5 100644 --- a/lib/handlebars/helpers/with.js +++ b/lib/handlebars/helpers/with.js @@ -1,4 +1,4 @@ -import {appendContextPath, blockParams, createFrame, isEmpty, isFunction} from '../utils'; +import {isEmpty, isFunction} from '../utils'; export default function(instance) { instance.registerHelper('with', function(context, options) { @@ -8,14 +8,10 @@ export default function(instance) { if (!isEmpty(context)) { let data = options.data; - if (options.data && options.ids) { - data = createFrame(options.data); - data.contextPath = appendContextPath(options.data.contextPath, options.ids[0]); - } return fn(context, { data: data, - blockParams: blockParams([context], [data && data.contextPath]) + blockParams: [context] }); } else { return options.inverse(this); diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js index b47d961..a7a9103 100644 --- a/lib/handlebars/runtime.js +++ b/lib/handlebars/runtime.js @@ -38,9 +38,6 @@ export function template(templateSpec, env) { function invokePartialWrapper(partial, context, options) { if (options.hash) { context = Utils.extend({}, context, options.hash); - if (options.ids) { - options.ids[0] = true; - } } partial = env.VM.resolvePartial.call(this, partial, context, options); @@ -224,9 +221,6 @@ export function resolvePartial(partial, context, options) { export function invokePartial(partial, context, options) { options.partial = true; - if (options.ids) { - options.data.contextPath = options.ids[0] || options.data.contextPath; - } let partialBlock; if (options.fn && options.fn !== noop) { diff --git a/lib/handlebars/utils.js b/lib/handlebars/utils.js index 2584601..9d08394 100644 --- a/lib/handlebars/utils.js +++ b/lib/handlebars/utils.js @@ -98,11 +98,3 @@ export function createFrame(object) { return frame; } -export function blockParams(params, ids) { - params.path = ids; - return params; -} - -export function appendContextPath(contextPath, id) { - return (contextPath ? contextPath + '.' : '') + id; -} diff --git a/print-script b/print-script index 046b99c..8464698 100755 --- a/print-script +++ b/print-script @@ -16,7 +16,6 @@ var template = Handlebars.precompile(script, { assumeObjects: true, compat: false, strict: true, - trackIds: true, knownHelpersOnly: false }); diff --git a/spec/string-params.js b/spec/string-params.js deleted file mode 100644 index b76f291..0000000 --- a/spec/string-params.js +++ /dev/null @@ -1,176 +0,0 @@ -describe('string params mode', function() { - it('arguments to helpers can be retrieved from options hash in string form', function() { - var template = CompilerContext.compile('{{wycats is.a slave.driver}}', {stringParams: true}); - - var helpers = { - wycats: function(passiveVoice, noun) { - return 'HELP ME MY BOSS ' + passiveVoice + ' ' + noun; - } - }; - - var result = template({}, {helpers: helpers}); - - equals(result, 'HELP ME MY BOSS is.a slave.driver', 'String parameters output'); - }); - - it('when using block form, arguments to helpers can be retrieved from options hash in string form', function() { - var template = CompilerContext.compile('{{#wycats is.a slave.driver}}help :({{/wycats}}', {stringParams: true}); - - var helpers = { - wycats: function(passiveVoice, noun, options) { - return 'HELP ME MY BOSS ' + passiveVoice + ' ' + - noun + ': ' + options.fn(this); - } - }; - - var result = template({}, {helpers: helpers}); - - equals(result, 'HELP ME MY BOSS is.a slave.driver: help :(', 'String parameters output'); - }); - - it('when inside a block in String mode, .. passes the appropriate context in the options hash', function() { - var template = CompilerContext.compile('{{#with dale}}{{tomdale ../need dad.joke}}{{/with}}', {stringParams: true}); - - var helpers = { - tomdale: function(desire, noun, options) { - return 'STOP ME FROM READING HACKER NEWS I ' + - options.contexts[0][desire] + ' ' + noun; - }, - - 'with': function(context, options) { - return options.fn(options.contexts[0][context]); - } - }; - - var result = template({ - dale: {}, - - need: 'need-a' - }, {helpers: helpers}); - - equals(result, 'STOP ME FROM READING HACKER NEWS I need-a dad.joke', 'Proper context variable output'); - }); - - it('information about the types is passed along', function() { - var template = CompilerContext.compile("{{tomdale 'need' dad.joke true false}}", { stringParams: true }); - - var helpers = { - tomdale: function(desire, noun, trueBool, falseBool, options) { - equal(options.types[0], 'StringLiteral', 'the string type is passed'); - equal(options.types[1], 'PathExpression', 'the expression type is passed'); - equal(options.types[2], 'BooleanLiteral', 'the expression type is passed'); - equal(desire, 'need', 'the string form is passed for strings'); - equal(noun, 'dad.joke', 'the string form is passed for expressions'); - equal(trueBool, true, 'raw booleans are passed through'); - equal(falseBool, false, 'raw booleans are passed through'); - return 'Helper called'; - } - }; - - var result = template({}, { helpers: helpers }); - equal(result, 'Helper called'); - }); - - it('hash parameters get type information', function() { - var template = CompilerContext.compile("{{tomdale he.says desire='need' noun=dad.joke bool=true}}", { stringParams: true }); - - var helpers = { - tomdale: function(exclamation, options) { - equal(exclamation, 'he.says'); - equal(options.types[0], 'PathExpression'); - - equal(options.hashTypes.desire, 'StringLiteral'); - equal(options.hashTypes.noun, 'PathExpression'); - equal(options.hashTypes.bool, 'BooleanLiteral'); - equal(options.hash.desire, 'need'); - equal(options.hash.noun, 'dad.joke'); - equal(options.hash.bool, true); - return 'Helper called'; - } - }; - - var result = template({}, { helpers: helpers }); - equal(result, 'Helper called'); - }); - - it('hash parameters get context information', function() { - var template = CompilerContext.compile("{{#with dale}}{{tomdale he.says desire='need' noun=../dad/joke bool=true}}{{/with}}", { stringParams: true }); - - var context = {dale: {}}; - - var helpers = { - tomdale: function(exclamation, options) { - equal(exclamation, 'he.says'); - equal(options.types[0], 'PathExpression'); - - equal(options.contexts.length, 1); - equal(options.hashContexts.noun, context); - equal(options.hash.desire, 'need'); - equal(options.hash.noun, 'dad.joke'); - equal(options.hash.bool, true); - return 'Helper called'; - }, - 'with': function(withContext, options) { - return options.fn(options.contexts[0][withContext]); - } - }; - - var result = template(context, { helpers: helpers }); - equal(result, 'Helper called'); - }); - - it('when inside a block in String mode, .. passes the appropriate context in the options hash to a block helper', function() { - var template = CompilerContext.compile('{{#with dale}}{{#tomdale ../need dad.joke}}wot{{/tomdale}}{{/with}}', {stringParams: true}); - - var helpers = { - tomdale: function(desire, noun, options) { - return 'STOP ME FROM READING HACKER NEWS I ' + - options.contexts[0][desire] + ' ' + noun + ' ' + - options.fn(this); - }, - - 'with': function(context, options) { - return options.fn(options.contexts[0][context]); - } - }; - - var result = template({ - dale: {}, - - need: 'need-a' - }, {helpers: helpers}); - - equals(result, 'STOP ME FROM READING HACKER NEWS I need-a dad.joke wot', 'Proper context variable output'); - }); - - it('with nested block ambiguous', function() { - var template = CompilerContext.compile('{{#with content}}{{#view}}{{firstName}} {{lastName}}{{/view}}{{/with}}', {stringParams: true}); - - var helpers = { - 'with': function() { - return 'WITH'; - }, - view: function() { - return 'VIEW'; - } - }; - - var result = template({}, {helpers: helpers}); - equals(result, 'WITH'); - }); - - it('should handle DATA', function() { - var template = CompilerContext.compile('{{foo @bar}}', { stringParams: true }); - - var helpers = { - foo: function(bar, options) { - equal(bar, '@bar'); - equal(options.types[0], 'PathExpression'); - return 'Foo!'; - } - }; - - var result = template({}, { helpers: helpers }); - equal(result, 'Foo!'); - }); -}); diff --git a/spec/subexpressions.js b/spec/subexpressions.js index dad741e..3810eb8 100644 --- a/spec/subexpressions.js +++ b/spec/subexpressions.js @@ -162,50 +162,6 @@ describe('subexpressions', function() { shouldCompileTo(string, [context, helpers], ''); }); - it('in string params mode,', function() { - var template = CompilerContext.compile('{{snog (blorg foo x=y) yeah a=b}}', {stringParams: true}); - - var helpers = { - snog: function(a, b, options) { - equals(a, 'foo'); - equals(options.types.length, 2, 'string params for outer helper processed correctly'); - equals(options.types[0], 'SubExpression', 'string params for outer helper processed correctly'); - equals(options.types[1], 'PathExpression', 'string params for outer helper processed correctly'); - return a + b; - }, - - blorg: function(a, options) { - equals(options.types.length, 1, 'string params for inner helper processed correctly'); - equals(options.types[0], 'PathExpression', 'string params for inner helper processed correctly'); - return a; - } - }; - - var result = template({ - foo: {}, - yeah: {} - }, {helpers: helpers}); - - equals(result, 'fooyeah'); - }); - - it('as hashes in string params mode', function() { - var template = CompilerContext.compile('{{blog fun=(bork)}}', {stringParams: true}); - - var helpers = { - blog: function(options) { - equals(options.hashTypes.fun, 'SubExpression'); - return 'val is ' + options.hash.fun; - }, - bork: function() { - return 'BORK'; - } - }; - - var result = template({}, {helpers: helpers}); - equals(result, 'val is BORK'); - }); - it('subexpression functions on the context', function() { var string = '{{foo (bar)}}!'; var context = { diff --git a/spec/track-ids.js b/spec/track-ids.js deleted file mode 100644 index 30a4661..0000000 --- a/spec/track-ids.js +++ /dev/null @@ -1,237 +0,0 @@ -describe('track ids', function() { - var context; - beforeEach(function() { - context = {is: {a: 'foo'}, slave: {driver: 'bar'}}; - }); - - it('should not include anything without the flag', function() { - var template = CompilerContext.compile('{{wycats is.a slave.driver}}'); - - var helpers = { - wycats: function(passiveVoice, noun, options) { - equal(options.ids, undefined); - equal(options.hashIds, undefined); - - return 'success'; - } - }; - - equals(template({}, {helpers: helpers}), 'success'); - }); - it('should include argument ids', function() { - var template = CompilerContext.compile('{{wycats is.a slave.driver}}', {trackIds: true}); - - var helpers = { - wycats: function(passiveVoice, noun, options) { - equal(options.ids[0], 'is.a'); - equal(options.ids[1], 'slave.driver'); - - return 'HELP ME MY BOSS ' + options.ids[0] + ':' + passiveVoice + ' ' + options.ids[1] + ':' + noun; - } - }; - - equals(template(context, {helpers: helpers}), 'HELP ME MY BOSS is.a:foo slave.driver:bar'); - }); - it('should include hash ids', function() { - var template = CompilerContext.compile('{{wycats bat=is.a baz=slave.driver}}', {trackIds: true}); - - var helpers = { - wycats: function(options) { - equal(options.hashIds.bat, 'is.a'); - equal(options.hashIds.baz, 'slave.driver'); - - return 'HELP ME MY BOSS ' + options.hashIds.bat + ':' + options.hash.bat + ' ' + options.hashIds.baz + ':' + options.hash.baz; - } - }; - - equals(template(context, {helpers: helpers}), 'HELP ME MY BOSS is.a:foo slave.driver:bar'); - }); - it('should note ../ and ./ references', function() { - var template = CompilerContext.compile('{{wycats ./is.a ../slave.driver this.is.a this}}', {trackIds: true}); - - var helpers = { - wycats: function(passiveVoice, noun, thiz, thiz2, options) { - equal(options.ids[0], 'is.a'); - equal(options.ids[1], '../slave.driver'); - equal(options.ids[2], 'is.a'); - equal(options.ids[3], ''); - - return 'HELP ME MY BOSS ' + options.ids[0] + ':' + passiveVoice + ' ' + options.ids[1] + ':' + noun; - } - }; - - equals(template(context, {helpers: helpers}), 'HELP ME MY BOSS is.a:foo ../slave.driver:undefined'); - }); - it('should note @data references', function() { - var template = CompilerContext.compile('{{wycats @is.a @slave.driver}}', {trackIds: true}); - - var helpers = { - wycats: function(passiveVoice, noun, options) { - equal(options.ids[0], '@is.a'); - equal(options.ids[1], '@slave.driver'); - - return 'HELP ME MY BOSS ' + options.ids[0] + ':' + passiveVoice + ' ' + options.ids[1] + ':' + noun; - } - }; - - equals(template({}, {helpers: helpers, data: context}), 'HELP ME MY BOSS @is.a:foo @slave.driver:bar'); - }); - - it('should return null for constants', function() { - var template = CompilerContext.compile('{{wycats 1 "foo" key=false}}', {trackIds: true}); - - var helpers = { - wycats: function(passiveVoice, noun, options) { - equal(options.ids[0], null); - equal(options.ids[1], null); - equal(options.hashIds.key, null); - - return 'HELP ME MY BOSS ' + passiveVoice + ' ' + noun + ' ' + options.hash.key; - } - }; - - equals(template(context, {helpers: helpers}), 'HELP ME MY BOSS 1 foo false'); - }); - it('should return true for subexpressions', function() { - var template = CompilerContext.compile('{{wycats (sub)}}', {trackIds: true}); - - var helpers = { - sub: function() { return 1; }, - wycats: function(passiveVoice, options) { - equal(options.ids[0], true); - - return 'HELP ME MY BOSS ' + passiveVoice; - } - }; - - equals(template(context, {helpers: helpers}), 'HELP ME MY BOSS 1'); - }); - - it('should use block param paths', function() { - var template = CompilerContext.compile('{{#doIt as |is|}}{{wycats is.a slave.driver is}}{{/doIt}}', {trackIds: true}); - - var helpers = { - doIt: function(options) { - var blockParams = [this.is]; - blockParams.path = ['zomg']; - return options.fn(this, {blockParams: blockParams}); - }, - wycats: function(passiveVoice, noun, blah, options) { - equal(options.ids[0], 'zomg.a'); - equal(options.ids[1], 'slave.driver'); - equal(options.ids[2], 'zomg'); - - return 'HELP ME MY BOSS ' + options.ids[0] + ':' + passiveVoice + ' ' + options.ids[1] + ':' + noun; - } - }; - - equals(template(context, {helpers: helpers}), 'HELP ME MY BOSS zomg.a:foo slave.driver:bar'); - }); - - describe('builtin helpers', function() { - var helpers = { - blockParams: function(name, options) { - return name + ':' + options.ids[0] + '\n'; - }, - wycats: function(name, options) { - return name + ':' + options.data.contextPath + '\n'; - } - }; - - describe('#each', function() { - it('should track contextPath for arrays', function() { - var template = CompilerContext.compile('{{#each array}}{{wycats name}}{{/each}}', {trackIds: true}); - - equals(template({array: [{name: 'foo'}, {name: 'bar'}]}, {helpers: helpers}), 'foo:array.0\nbar:array.1\n'); - }); - it('should track contextPath for keys', function() { - var template = CompilerContext.compile('{{#each object}}{{wycats name}}{{/each}}', {trackIds: true}); - - equals(template({object: {foo: {name: 'foo'}, bar: {name: 'bar'}}}, {helpers: helpers}), 'foo:object.foo\nbar:object.bar\n'); - }); - it('should handle nesting', function() { - var template = CompilerContext.compile('{{#each .}}{{#each .}}{{wycats name}}{{/each}}{{/each}}', {trackIds: true}); - - equals(template({array: [{name: 'foo'}, {name: 'bar'}]}, {helpers: helpers}), 'foo:.array..0\nbar:.array..1\n'); - }); - it('should handle block params', function() { - var template = CompilerContext.compile('{{#each array as |value|}}{{blockParams value.name}}{{/each}}', {trackIds: true}); - - equals(template({array: [{name: 'foo'}, {name: 'bar'}]}, {helpers: helpers}), 'foo:array.0.name\nbar:array.1.name\n'); - }); - }); - describe('#with', function() { - it('should track contextPath', function() { - var template = CompilerContext.compile('{{#with field}}{{wycats name}}{{/with}}', {trackIds: true}); - - equals(template({field: {name: 'foo'}}, {helpers: helpers}), 'foo:field\n'); - }); - it('should handle nesting', function() { - var template = CompilerContext.compile('{{#with bat}}{{#with field}}{{wycats name}}{{/with}}{{/with}}', {trackIds: true}); - - equals(template({bat: {field: {name: 'foo'}}}, {helpers: helpers}), 'foo:bat.field\n'); - }); - }); - describe('#blockHelperMissing', function() { - it('should track contextPath for arrays', function() { - var template = CompilerContext.compile('{{#field}}{{wycats name}}{{/field}}', {trackIds: true}); - - equals(template({field: [{name: 'foo'}]}, {helpers: helpers}), 'foo:field.0\n'); - }); - it('should track contextPath for keys', function() { - var template = CompilerContext.compile('{{#field}}{{wycats name}}{{/field}}', {trackIds: true}); - - equals(template({field: {name: 'foo'}}, {helpers: helpers}), 'foo:field\n'); - }); - it('should handle nesting', function() { - var template = CompilerContext.compile('{{#bat}}{{#field}}{{wycats name}}{{/field}}{{/bat}}', {trackIds: true}); - - equals(template({bat: {field: {name: 'foo'}}}, {helpers: helpers}), 'foo:bat.field\n'); - }); - }); - }); - - describe('partials', function() { - var helpers = { - blockParams: function(name, options) { - return name + ':' + options.ids[0] + '\n'; - }, - wycats: function(name, options) { - return name + ':' + options.data.contextPath + '\n'; - } - }; - - it('should pass track id for basic partial', function() { - var template = CompilerContext.compile('Dudes: {{#dudes}}{{> dude}}{{/dudes}}', {trackIds: true}), - hash = {dudes: [{name: 'Yehuda', url: 'http://yehuda'}, {name: 'Alan', url: 'http://alan'}]}; - - var partials = { - dude: CompilerContext.compile('{{wycats name}}', {trackIds: true}) - }; - - equals(template(hash, {helpers: helpers, partials: partials}), 'Dudes: Yehuda:dudes.0\nAlan:dudes.1\n'); - }); - - it('should pass track id for context partial', function() { - var template = CompilerContext.compile('Dudes: {{> dude dudes}}', {trackIds: true}), - hash = {dudes: [{name: 'Yehuda', url: 'http://yehuda'}, {name: 'Alan', url: 'http://alan'}]}; - - var partials = { - dude: CompilerContext.compile('{{#each this}}{{wycats name}}{{/each}}', {trackIds: true}) - }; - - equals(template(hash, {helpers: helpers, partials: partials}), 'Dudes: Yehuda:dudes..0\nAlan:dudes..1\n'); - }); - - it('should invalidate context for partials with parameters', function() { - var template = CompilerContext.compile('Dudes: {{#dudes}}{{> dude . bar="foo"}}{{/dudes}}', {trackIds: true}), - hash = {dudes: [{name: 'Yehuda', url: 'http://yehuda'}, {name: 'Alan', url: 'http://alan'}]}; - - var partials = { - dude: CompilerContext.compile('{{wycats name}}', {trackIds: true}) - }; - - equals(template(hash, {helpers: helpers, partials: partials}), 'Dudes: Yehuda:true\nAlan:true\n'); - }); - }); -}); -- cgit v1.1 From 63a08890cce3620f3af328163f4313754df76581 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Sat, 12 Dec 2015 15:27:26 -0600 Subject: Remove semi-documented _setup and _child APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These were a bad idea to begin with and without the trackIds implementation they don’t make much sense. --- lib/handlebars/compiler/compiler.js | 15 +-------------- lib/handlebars/runtime.js | 16 +++------------- spec/runtime.js | 37 ------------------------------------- 3 files changed, 4 insertions(+), 64 deletions(-) diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js index 9fa9dd8..040e99a 100644 --- a/lib/handlebars/compiler/compiler.js +++ b/lib/handlebars/compiler/compiler.js @@ -461,25 +461,12 @@ export function compile(input, options = {}, env) { } // Template is only compiled on first use and cached after that point. - function ret(context, execOptions) { + return function(context, execOptions) { if (!compiled) { compiled = compileInput(); } return compiled.call(this, context, execOptions); - } - ret._setup = function(setupOptions) { - if (!compiled) { - compiled = compileInput(); - } - return compiled._setup(setupOptions); - }; - ret._child = function(i, data, blockParams, depths) { - if (!compiled) { - compiled = compileInput(); - } - return compiled._child(i, data, blockParams, depths); }; - return ret; } function argEquals(a, b) { diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js index a7a9103..5c479a8 100644 --- a/lib/handlebars/runtime.js +++ b/lib/handlebars/runtime.js @@ -129,7 +129,7 @@ export function template(templateSpec, env) { function ret(context, options = {}) { let data = options.data; - ret._setup(options); + _setup(options); if (!options.partial && templateSpec.useData) { data = initData(context, data); } @@ -151,7 +151,7 @@ export function template(templateSpec, env) { } ret.isTop = true; - ret._setup = function(options) { + function _setup(options) { if (!options.partial) { container.helpers = container.merge(options.helpers, env.helpers); @@ -166,18 +166,8 @@ export function template(templateSpec, env) { container.partials = options.partials; container.decorators = options.decorators; } - }; - - ret._child = function(i, data, blockParams, depths) { - if (templateSpec.useBlockParams && !blockParams) { - throw new Exception('must pass block params'); - } - if (templateSpec.useDepths && !depths) { - throw new Exception('must pass parent depths'); - } + } - return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths); - }; return ret; } diff --git a/spec/runtime.js b/spec/runtime.js index a4830ad..2a85899 100644 --- a/spec/runtime.js +++ b/spec/runtime.js @@ -32,43 +32,6 @@ describe('runtime', function() { }); }); - describe('#child', function() { - if (!Handlebars.compile) { - return; - } - - it('should throw for depthed methods without depths', function() { - shouldThrow(function() { - var template = Handlebars.compile('{{#foo}}{{../bar}}{{/foo}}'); - // Calling twice to hit the non-compiled case. - template._setup({}); - template._setup({}); - template._child(1); - }, Error, 'must pass parent depths'); - }); - - it('should throw for block param methods without params', function() { - shouldThrow(function() { - var template = Handlebars.compile('{{#foo as |foo|}}{{foo}}{{/foo}}'); - // Calling twice to hit the non-compiled case. - template._setup({}); - template._setup({}); - template._child(1); - }, Error, 'must pass block params'); - }); - it('should expose child template', function() { - var template = Handlebars.compile('{{#foo}}bar{{/foo}}'); - // Calling twice to hit the non-compiled case. - equal(template._child(1)(), 'bar'); - equal(template._child(1)(), 'bar'); - }); - it('should render depthed content', function() { - var template = Handlebars.compile('{{#foo}}{{../bar}}{{/foo}}'); - // Calling twice to hit the non-compiled case. - equal(template._child(1, undefined, [], [{bar: 'baz'}])(), 'baz'); - }); - }); - describe('#noConflict', function() { if (!CompilerContext.browser) { return; -- cgit v1.1 From 25458fdc2a3ad179d1eb4c8ae401c7b9bfdfb0d2 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Sat, 12 Dec 2015 15:27:56 -0600 Subject: Relax depth check for context push Fixes #1135 --- lib/handlebars/runtime.js | 4 ++-- spec/regressions.js | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js index 5c479a8..55eb1c1 100644 --- a/lib/handlebars/runtime.js +++ b/lib/handlebars/runtime.js @@ -137,7 +137,7 @@ export function template(templateSpec, env) { blockParams = templateSpec.useBlockParams ? [] : undefined; if (templateSpec.useDepths) { if (options.depths) { - depths = context !== options.depths[0] ? [context].concat(options.depths) : options.depths; + depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; } else { depths = [context]; } @@ -174,7 +174,7 @@ export function template(templateSpec, env) { export function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) { function prog(context, options = {}) { let currentDepths = depths; - if (depths && context !== depths[0]) { + if (depths && context != depths[0]) { currentDepths = [context].concat(depths); } diff --git a/spec/regressions.js b/spec/regressions.js index 83765a2..9bd00d9 100644 --- a/spec/regressions.js +++ b/spec/regressions.js @@ -247,4 +247,27 @@ describe('Regressions', function() { }; shouldCompileToWithPartials(string, [{}, {}, partials], true, 'Outer'); }); + + it('GH-1135 : Context handling within each iteration', function() { + var obj = {array: [1], name: 'John'}; + var helpers = { + myif: function(conditional, options) { + if (conditional) { + return options.fn(this); + } else { + return options.inverse(this); + } + } + }; + + shouldCompileTo(` + {{#each array}} + 1. IF: {{#if true}}{{../name}}-{{../../name}}-{{../../../name}}{{/if}} + 2. MYIF: {{#myif true}}{{../name}}={{../../name}}={{../../../name}}{{/myif}} + {{/each}} + `, [obj, helpers], ` + 1. IF: John-- + 2. MYIF: John== + `); + }); }); -- cgit v1.1 From 8289c0bf3afff120b5fe7e90c08cac18a8166b9c Mon Sep 17 00:00:00 2001 From: kpdecker Date: Sat, 12 Dec 2015 15:34:06 -0600 Subject: Update build for modern node versions --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c6e2c84..00c8b00 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,12 +13,12 @@ env: - secure: Nm4AgSfsgNB21kgKrF9Tl7qVZU8YYREhouQunFracTcZZh2NZ2XH5aHuSiXCj88B13Cr/jGbJKsZ4T3QS3wWYtz6lkyVOx3H3iI+TMtqhD9RM3a7A4O+4vVN8IioB2YjhEu0OKjwgX5gp+0uF+pLEi7Hpj6fupD3AbbL5uYcKg8= matrix: include: - - node_js: '0.12' + - node_js: '5' env: - PUBLISH=true - secure: pLTzghtVll9yGKJI0AaB0uI8GypfWxLTaIB0ZL8//yN3nAEIKMhf/RRilYTsn/rKj2NUa7vt2edYILi3lttOUlCBOwTc9amiRms1W8Lwr/3IdWPeBLvLuH1zNJRm2lBAwU4LBSqaOwhGaxOQr6KHTnWudhNhgOucxpZfvfI/dFw= - secure: yERYCf7AwL11D9uMtacly/THGV8BlzsMmrt+iQVvGA3GaY6QMmfYqf6P6cCH98sH5etd1Y+1e6YrPeMjqI6lyRllT7FptoyOdHulazQe86VQN4sc0EpqMlH088kB7gGjTut9Z+X9ViooT5XEh9WA5jXEI9pXhQJNoIHkWPuwGuY= - - node_js: '4.0.0' + - node_js: '4' cache: directories: - node_modules -- cgit v1.1 From 2ea6119a83e6c59ce3b208f95fee604a1648670b Mon Sep 17 00:00:00 2001 From: kpdecker Date: Sat, 12 Dec 2015 16:07:52 -0600 Subject: Fix throw when creating exception object in Safari https://github.com/jquery/esprima/issues/1290 --- lib/handlebars/exception.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/handlebars/exception.js b/lib/handlebars/exception.js index 52499c0..24734d4 100644 --- a/lib/handlebars/exception.js +++ b/lib/handlebars/exception.js @@ -12,7 +12,7 @@ function Exception(message, node) { message += ' - ' + line + ':' + column; } - let tmp = Error.prototype.constructor.call(this, message); + let tmp = Error.prototype.constructor.call(this, message, loc && loc.source, line); // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. for (let idx = 0; idx < errorProps.length; idx++) { @@ -24,9 +24,19 @@ function Exception(message, node) { Error.captureStackTrace(this, Exception); } - if (loc) { - this.lineNumber = line; - this.column = column; + try { + if (loc) { + this.lineNumber = line; + + // Work around issue under safari where we can't directly set the column value + if (Object.defineProperty) { + Object.defineProperty(this, 'column', {value: column}); + } else { + this.column = column; + } + } + } catch (nop) { + /* Ignore if the browser is very particular */ } } -- cgit v1.1 From 326734b0f3ab9e7b9431579d449d344919bb6869 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Sat, 12 Dec 2015 16:14:17 -0600 Subject: Exclude coverage check in exception conditional --- lib/handlebars/exception.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/handlebars/exception.js b/lib/handlebars/exception.js index 24734d4..af675d9 100644 --- a/lib/handlebars/exception.js +++ b/lib/handlebars/exception.js @@ -29,6 +29,7 @@ function Exception(message, node) { this.lineNumber = line; // Work around issue under safari where we can't directly set the column value + /* istanbul ignore next */ if (Object.defineProperty) { Object.defineProperty(this, 'column', {value: column}); } else { -- cgit v1.1 From 871c32a6f9106137061a49e731fc267933f6b79b Mon Sep 17 00:00:00 2001 From: kpdecker Date: Sat, 12 Dec 2015 16:26:48 -0600 Subject: Update target browser test versions --- Gruntfile.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index fd76518..97cfff0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -166,11 +166,10 @@ module.exports = function(grunt) { browsers: [ {browserName: 'chrome'}, {browserName: 'firefox', platform: 'Linux'}, - {browserName: 'safari', version: 7, platform: 'OS X 10.9'}, - {browserName: 'safari', version: 6, platform: 'OS X 10.8'}, + {browserName: 'safari', version: 9, platform: 'OS X 10.11'}, + {browserName: 'safari', version: 8, platform: 'OS X 10.10'}, {browserName: 'internet explorer', version: 11, platform: 'Windows 8.1'}, - {browserName: 'internet explorer', version: 10, platform: 'Windows 8'}, - {browserName: 'internet explorer', version: 9, platform: 'Windows 7'} + {browserName: 'internet explorer', version: 10, platform: 'Windows 8'} ] } }, -- cgit v1.1 From a6121cae797161f74bdd5a25e0c56379992557d7 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Sat, 12 Dec 2015 17:09:24 -0600 Subject: Avoid error in older browsers in test The tests are run through the transpiler and just reverting the user of template literal is easier than adding transpiler to the test stack. --- spec/regressions.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/spec/regressions.js b/spec/regressions.js index 9bd00d9..a1eec2f 100644 --- a/spec/regressions.js +++ b/spec/regressions.js @@ -260,14 +260,12 @@ describe('Regressions', function() { } }; - shouldCompileTo(` - {{#each array}} - 1. IF: {{#if true}}{{../name}}-{{../../name}}-{{../../../name}}{{/if}} - 2. MYIF: {{#myif true}}{{../name}}={{../../name}}={{../../../name}}{{/myif}} - {{/each}} - `, [obj, helpers], ` - 1. IF: John-- - 2. MYIF: John== - `); + shouldCompileTo( + '{{#each array}}\n' + + ' 1. IF: {{#if true}}{{../name}}-{{../../name}}-{{../../../name}}{{/if}}\n' + + ' 2. MYIF: {{#myif true}}{{../name}}={{../../name}}={{../../../name}}{{/myif}}\n' + + '{{/each}}', [obj, helpers], + ' 1. IF: John--\n' + + ' 2. MYIF: John==\n'); }); }); -- cgit v1.1