Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ab261eab7 | |||
| 143ac806da | |||
| f1752fe66f | |||
| 0b593bfe5d | |||
| 2e53fba68f | |||
| ba570c42cf | |||
| 0440af2147 | |||
| b793350fec | |||
| 26d0f7a80d | |||
| b7eada0149 | |||
| b8e769fcb6 | |||
| 9cb31653a4 | |||
| c53f340374 | |||
| 059b330579 | |||
| 8f6047cdfd | |||
| cf7545ef5a | |||
| c958cc8955 | |||
| b250b2d53a | |||
| ff4d827c09 | |||
| e4738491b3 | |||
| 54f7e11b28 | |||
| 8742bde701 | |||
| 2357140c68 | |||
| c5cbeac039 | |||
| 213c0bbe3c |
+2
-1
@@ -90,6 +90,7 @@ Handlebars utilizes the [release yeoman generator][generator-release] to perform
|
||||
A full release may be completed with the following:
|
||||
|
||||
```
|
||||
npm ci
|
||||
yo release
|
||||
npm publish
|
||||
yo release:publish components handlebars.js dist/components/
|
||||
@@ -104,7 +105,7 @@ in those places still point to the latest version
|
||||
|
||||
* [The npm-package](https://www.npmjs.com/package/handlebars) (check latest-tag)
|
||||
* [The bower package](https://github.com/components/handlebars.js) (check the package.json)
|
||||
* [The AWS S3 Bucket](http://builds.handlebarsjs.com.s3.amazonaws.com/) (check latest-tag)
|
||||
* [The AWS S3 Bucket](https://s3.amazonaws.com/builds.handlebarsjs.com) (check latest-tag)
|
||||
* [RubyGems](https://rubygems.org/gems/handlebars-source)
|
||||
|
||||
When everything is OK, the handlebars site needs to be updated to point to the new version numbers. The jsfiddle link should be updated to point to the most recent distribution for all instances in our documentation.
|
||||
|
||||
+1
-1
@@ -239,7 +239,7 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-babel');
|
||||
grunt.loadNpmTasks('grunt-bg-shell');
|
||||
grunt.loadNpmTasks('grunt-eslint');
|
||||
grunt.loadNpmTasks('grunt-saucelabs');
|
||||
grunt.loadNpmTasks('@knappi/grunt-saucelabs');
|
||||
grunt.loadNpmTasks('grunt-webpack');
|
||||
|
||||
grunt.task.loadTasks('tasks');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "handlebars",
|
||||
"version": "4.3.1",
|
||||
"version": "4.4.4",
|
||||
"main": "handlebars.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>handlebars.js</id>
|
||||
<version>4.3.1</version>
|
||||
<version>4.4.4</version>
|
||||
<authors>handlebars.js Authors</authors>
|
||||
<licenseUrl>https://github.com/wycats/handlebars.js/blob/master/LICENSE</licenseUrl>
|
||||
<projectUrl>https://github.com/wycats/handlebars.js/</projectUrl>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "handlebars",
|
||||
"version": "4.3.1",
|
||||
"version": "4.4.4",
|
||||
"license": "MIT",
|
||||
"jspm": {
|
||||
"main": "handlebars",
|
||||
|
||||
@@ -4,7 +4,7 @@ import {registerDefaultHelpers} from './helpers';
|
||||
import {registerDefaultDecorators} from './decorators';
|
||||
import logger from './logger';
|
||||
|
||||
export const VERSION = '4.3.1';
|
||||
export const VERSION = '4.4.4';
|
||||
export const COMPILER_REVISION = 8;
|
||||
export const LAST_COMPATIBLE_COMPILER_REVISION = 7;
|
||||
|
||||
|
||||
@@ -13,13 +13,19 @@ JavaScriptCompiler.prototype = {
|
||||
// PUBLIC API: You can override these methods in a subclass to provide
|
||||
// alternative compiled forms for name lookup and buffering semantics
|
||||
nameLookup: function(parent, name/* , type*/) {
|
||||
const isEnumerable = [ this.aliasable('container.propertyIsEnumerable'), '.call(', parent, ',"constructor")'];
|
||||
|
||||
if (name === 'constructor') {
|
||||
return ['(', parent, '.propertyIsEnumerable(\'constructor\') ? ', parent, '.constructor : undefined', ')'];
|
||||
return ['(', isEnumerable, '?', _actualLookup(), ' : undefined)'];
|
||||
}
|
||||
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
||||
return [parent, '.', name];
|
||||
} else {
|
||||
return [parent, '[', JSON.stringify(name), ']'];
|
||||
return _actualLookup();
|
||||
|
||||
function _actualLookup() {
|
||||
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
||||
return [parent, '.', name];
|
||||
} else {
|
||||
return [parent, '[', JSON.stringify(name), ']'];
|
||||
}
|
||||
}
|
||||
},
|
||||
depthedLookup: function(name) {
|
||||
@@ -214,7 +220,6 @@ JavaScriptCompiler.prototype = {
|
||||
let aliasCount = 0;
|
||||
for (let alias in this.aliases) { // eslint-disable-line guard-for-in
|
||||
let node = this.aliases[alias];
|
||||
|
||||
if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) {
|
||||
varDeclarations += ', alias' + (++aliasCount) + '=' + alias;
|
||||
node.children[0] = 'alias' + aliasCount;
|
||||
@@ -339,9 +344,9 @@ JavaScriptCompiler.prototype = {
|
||||
params.splice(1, 0, current);
|
||||
|
||||
this.pushSource([
|
||||
'if (!', this.lastHelper, ') { ',
|
||||
current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params),
|
||||
'}']);
|
||||
'if (!', this.lastHelper, ') { ',
|
||||
current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params),
|
||||
'}']);
|
||||
},
|
||||
|
||||
// [appendContent]
|
||||
@@ -686,16 +691,16 @@ JavaScriptCompiler.prototype = {
|
||||
if (!this.options.strict) {
|
||||
lookup[0] = '(helper = ';
|
||||
lookup.push(
|
||||
' != null ? helper : ',
|
||||
this.aliasable('container.hooks.helperMissing')
|
||||
' != null ? helper : ',
|
||||
this.aliasable('container.hooks.helperMissing')
|
||||
);
|
||||
}
|
||||
|
||||
this.push([
|
||||
'(', lookup,
|
||||
(helper.paramsInit ? ['),(', helper.paramsInit] : []), '),',
|
||||
'(typeof helper === ', this.aliasable('"function"'), ' ? ',
|
||||
this.source.functionCall('helper', 'call', helper.callParams), ' : helper))'
|
||||
'(', lookup,
|
||||
(helper.paramsInit ? ['),(', helper.paramsInit] : []), '),',
|
||||
'(typeof helper === ', this.aliasable('"function"'), ' ? ',
|
||||
this.source.functionCall('helper', 'call', helper.callParams), ' : helper))'
|
||||
]);
|
||||
},
|
||||
|
||||
|
||||
@@ -49,6 +49,16 @@ export default function(instance) {
|
||||
execIteration(i, i, i === context.length - 1);
|
||||
}
|
||||
}
|
||||
} else if (global.Symbol && context[global.Symbol.iterator]) {
|
||||
const newContext = [];
|
||||
const iterator = context[global.Symbol.iterator]();
|
||||
for (let it = iterator.next(); !it.done; it = iterator.next()) {
|
||||
newContext.push(it.value);
|
||||
}
|
||||
context = newContext;
|
||||
for (let j = context.length; i < j; i++) {
|
||||
execIteration(i, i, i === context.length - 1);
|
||||
}
|
||||
} else {
|
||||
let priorKey;
|
||||
|
||||
|
||||
Generated
+71
-69
@@ -1,9 +1,79 @@
|
||||
{
|
||||
"name": "handlebars",
|
||||
"version": "4.1.2-0",
|
||||
"version": "4.4.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@knappi/grunt-saucelabs": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@knappi/grunt-saucelabs/-/grunt-saucelabs-9.0.2.tgz",
|
||||
"integrity": "sha512-PHnusXA+begWFgZS084ZAC8kT7FNRvvJIWg5FOqusRjr4LSe++RIk2HRULAQ8Dx+6HiKJiQXzrAsDagKh3k1pw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@knappi/sauce-tunnel": "^2.5.0",
|
||||
"colors": "~1.1.2",
|
||||
"lodash": "^4.17.11",
|
||||
"q": "~1.4.1",
|
||||
"requestretry": "~1.9.0",
|
||||
"saucelabs": "^1.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"dev": true
|
||||
},
|
||||
"q": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
|
||||
"integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@knappi/sauce-tunnel": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@knappi/sauce-tunnel/-/sauce-tunnel-2.5.0.tgz",
|
||||
"integrity": "sha512-8f60HrHH4SRHOspcVLbN0gpDiBYLQjmZCXwmqibhzJDHGaD/fflPpdUD2kJJyeioydcf1T0xfpbMcJW0dLjpnw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.2",
|
||||
"request": "^2.88.0",
|
||||
"split": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/parsimmon": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/parsimmon/-/parsimmon-1.10.0.tgz",
|
||||
@@ -3703,33 +3773,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"grunt-saucelabs": {
|
||||
"version": "github:nknapp/grunt-saucelabs#5b9b7150e66051dbf68e9212fbb89561e447e855",
|
||||
"from": "github:nknapp/grunt-saucelabs",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colors": "~1.1.2",
|
||||
"lodash": "^4.17.11",
|
||||
"q": "~1.4.1",
|
||||
"requestretry": "~1.9.0",
|
||||
"sauce-tunnel": "github:nknapp/sauce-tunnel",
|
||||
"saucelabs": "^1.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"dev": true
|
||||
},
|
||||
"q": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
|
||||
"integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"grunt-webpack": {
|
||||
"version": "1.0.18",
|
||||
"resolved": "https://registry.npmjs.org/grunt-webpack/-/grunt-webpack-1.0.18.tgz",
|
||||
@@ -7020,47 +7063,6 @@
|
||||
"integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=",
|
||||
"dev": true
|
||||
},
|
||||
"sauce-tunnel": {
|
||||
"version": "github:nknapp/sauce-tunnel#746744c71b9bec69ca612e751e7121f61a37d489",
|
||||
"from": "github:nknapp/sauce-tunnel",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.2",
|
||||
"request": "^2.88.0",
|
||||
"split": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"saucelabs": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz",
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "handlebars",
|
||||
"barename": "handlebars",
|
||||
"version": "4.3.1",
|
||||
"version": "4.4.4",
|
||||
"description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration",
|
||||
"homepage": "http://www.handlebarsjs.com/",
|
||||
"keywords": [
|
||||
@@ -29,6 +29,7 @@
|
||||
"uglify-js": "^3.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@knappi/grunt-saucelabs": "^9.0.2",
|
||||
"aws-sdk": "^2.1.49",
|
||||
"babel-loader": "^5.0.0",
|
||||
"babel-runtime": "^5.1.10",
|
||||
@@ -48,7 +49,6 @@
|
||||
"grunt-contrib-uglify": "^1",
|
||||
"grunt-contrib-watch": "^1.1.0",
|
||||
"grunt-eslint": "^20.1.0",
|
||||
"grunt-saucelabs": "github:nknapp/grunt-saucelabs",
|
||||
"grunt-webpack": "^1.0.8",
|
||||
"istanbul": "^0.3.0",
|
||||
"jison": "~0.3.0",
|
||||
|
||||
+64
-1
@@ -2,7 +2,70 @@
|
||||
|
||||
## Development
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.1...master)
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.4...master)
|
||||
|
||||
## v4.4.4 - October 20th, 2019
|
||||
Bugfixes:
|
||||
- fix: prevent zero length tokens in raw-blocks (#1577, #1578) - f1752fe
|
||||
|
||||
Chore:
|
||||
- chore: link to s3 bucket with https, add "npm ci" to build instructions - 0b593bf
|
||||
|
||||
Compatibility notes:
|
||||
- no compatibility issues are expected
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.3...v4.4.4)
|
||||
|
||||
## v4.4.3 - October 8th, 2019
|
||||
Bugfixes
|
||||
|
||||
Typings:
|
||||
- add missing type fields to AST typings and add tests for them - 0440af2
|
||||
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.2...v4.4.3)
|
||||
|
||||
## v4.4.2 - October 2nd, 2019
|
||||
- chore: fix grunt-saucelabs dependency - b7eada0
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.1...v4.4.2)
|
||||
|
||||
## v4.4.1 - October 2nd, 2019
|
||||
- [#1562](https://github.com/wycats/handlebars.js/issues/1562) - Error message for syntax error missing location in 4.2.1+
|
||||
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.0...v4.4.1)
|
||||
|
||||
## v4.4.0 - September 29th, 2019
|
||||
- Added support for iterable objects in {{#each}} helper (#1557) - cf7545e
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.4...v4.4.0)
|
||||
|
||||
## v4.3.4 - September 28th, 2019
|
||||
- fix: harden "propertyIsEnumerable"-check - ff4d827
|
||||
|
||||
Compatibility notes:
|
||||
- No incompatibilities are known.
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.3...v4.3.4)
|
||||
|
||||
## v4.3.3 - September 27th, 2019
|
||||
- fix test case for browsers that do not support __defineGetter__ - 8742bde
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.2...v4.3.3)
|
||||
|
||||
## v4.3.2 - September 26th, 2019
|
||||
- Use Object.prototype.propertyIsEnumerable to check for constructors - 213c0bb, #1563
|
||||
|
||||
Compatibility notes:
|
||||
- There are no breaking changes
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.1...v4.3.2)
|
||||
|
||||
## v4.3.1 - September 25th, 2019
|
||||
Fixes:
|
||||
|
||||
@@ -254,6 +254,37 @@ describe('builtin helpers', function() {
|
||||
template({});
|
||||
}, handlebarsEnv.Exception, 'Must pass iterator to #each');
|
||||
});
|
||||
|
||||
if (global.Symbol && global.Symbol.iterator) {
|
||||
it('each on iterable', function() {
|
||||
function Iterator(arr) {
|
||||
this.arr = arr;
|
||||
this.index = 0;
|
||||
}
|
||||
Iterator.prototype.next = function() {
|
||||
var value = this.arr[this.index];
|
||||
var done = this.index === this.arr.length;
|
||||
if (!done) {
|
||||
this.index++;
|
||||
}
|
||||
return { value: value, done: done };
|
||||
};
|
||||
function Iterable(arr) {
|
||||
this.arr = arr;
|
||||
}
|
||||
Iterable.prototype[global.Symbol.iterator] = function() {
|
||||
return new Iterator(this.arr);
|
||||
};
|
||||
var string = '{{#each goodbyes}}{{text}}! {{/each}}cruel {{world}}!';
|
||||
var goodbyes = new Iterable([{text: 'goodbye'}, {text: 'Goodbye'}, {text: 'GOODBYE'}]);
|
||||
var goodbyesEmpty = new Iterable([]);
|
||||
var hash = {goodbyes: goodbyes, world: 'world'};
|
||||
shouldCompileTo(string, hash, 'goodbye! Goodbye! GOODBYE! cruel world!',
|
||||
'each with array argument iterates over the contents when not empty');
|
||||
shouldCompileTo(string, {goodbyes: goodbyesEmpty, world: 'world'}, 'cruel world!',
|
||||
'each with array argument ignores the contents when empty');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('#log', function() {
|
||||
|
||||
+28
-7
@@ -28,14 +28,35 @@ describe('helpers', function() {
|
||||
'raw block helper gets raw content');
|
||||
});
|
||||
|
||||
it('helper for nested raw block gets raw content', function() {
|
||||
var string = '{{{{a}}}} {{{{b}}}} {{{{/b}}}} {{{{/a}}}}';
|
||||
var helpers = {
|
||||
a: function(options) {
|
||||
describe('raw block parsing (with identity helper-function)', function() {
|
||||
|
||||
function runWithIdentityHelper(template, expected) {
|
||||
var helpers = {
|
||||
identity: function(options) {
|
||||
return options.fn();
|
||||
}
|
||||
};
|
||||
shouldCompileTo(string, [{}, helpers], ' {{{{b}}}} {{{{/b}}}} ', 'raw block helper should get nested raw block as raw content');
|
||||
}
|
||||
};
|
||||
shouldCompileTo(template, [{}, helpers], expected);
|
||||
}
|
||||
|
||||
it('helper for nested raw block gets raw content', function() {
|
||||
runWithIdentityHelper('{{{{identity}}}} {{{{b}}}} {{{{/b}}}} {{{{/identity}}}}', ' {{{{b}}}} {{{{/b}}}} ');
|
||||
});
|
||||
|
||||
it('helper for nested raw block works with empty content', function() {
|
||||
runWithIdentityHelper('{{{{identity}}}}{{{{/identity}}}}', '');
|
||||
});
|
||||
|
||||
it('helper for nested raw block works if nested raw blocks are broken', function() {
|
||||
runWithIdentityHelper('{{{{identity}}}} {{{{a}}}} {{{{ {{{{/ }}}} }}}} {{{{/identity}}}}', ' {{{{a}}}} {{{{ {{{{/ }}}} }}}} ');
|
||||
});
|
||||
|
||||
it('helper for nested raw block throw exception when with missing closing braces', function() {
|
||||
var string = '{{{{a}}}} {{{{/a';
|
||||
shouldThrow(function() {
|
||||
Handlebars.compile(string)();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('helper block with identical context', function() {
|
||||
|
||||
+14
-1
@@ -33,7 +33,7 @@ describe('security issues', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('GH-xxxx: Prevent explicit call of helperMissing-helpers', function() {
|
||||
describe('GH-1558: Prevent explicit call of helperMissing-helpers', function() {
|
||||
if (!Handlebars.compile) {
|
||||
return;
|
||||
}
|
||||
@@ -88,4 +88,17 @@ describe('security issues', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GH-1563', function() {
|
||||
it('should not allow to access constructor after overriding via __defineGetter__', function() {
|
||||
if (({}).__defineGetter__ == null || ({}).__lookupGetter__ == null) {
|
||||
return; // Browser does not support this exploit anyway
|
||||
}
|
||||
shouldCompileTo('{{__defineGetter__ "undefined" valueOf }}' +
|
||||
'{{#with __lookupGetter__ }}' +
|
||||
'{{__defineGetter__ "propertyIsEnumerable" (this.bind (this.bind 1)) }}' +
|
||||
'{{constructor.name}}' +
|
||||
'{{/with}}', {}, '');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD}
|
||||
return 'END_RAW_BLOCK';
|
||||
}
|
||||
}
|
||||
<raw>[^\x00]*?/("{{{{") { return 'CONTENT'; }
|
||||
<raw>[^\x00]+/("{{{{") { return 'CONTENT'; }
|
||||
|
||||
<com>[\s\S]*?"--"{RIGHT_STRIP}?"}}" {
|
||||
this.popState();
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ content
|
||||
};
|
||||
|
||||
rawBlock
|
||||
: openRawBlock content+ END_RAW_BLOCK -> yy.prepareRawBlock($1, $2, $3, @$)
|
||||
: openRawBlock content* END_RAW_BLOCK -> yy.prepareRawBlock($1, $2, $3, @$)
|
||||
;
|
||||
|
||||
openRawBlock
|
||||
|
||||
Vendored
+19
-2
@@ -270,6 +270,7 @@ declare namespace hbs {
|
||||
interface Statement extends Node {}
|
||||
|
||||
interface MustacheStatement extends Statement {
|
||||
type: 'MustacheStatement';
|
||||
path: PathExpression | Literal;
|
||||
params: Expression[];
|
||||
hash: Hash;
|
||||
@@ -280,6 +281,7 @@ declare namespace hbs {
|
||||
interface Decorator extends MustacheStatement { }
|
||||
|
||||
interface BlockStatement extends Statement {
|
||||
type: 'BlockStatement';
|
||||
path: PathExpression;
|
||||
params: Expression[];
|
||||
hash: Hash;
|
||||
@@ -293,6 +295,7 @@ declare namespace hbs {
|
||||
interface DecoratorBlock extends BlockStatement { }
|
||||
|
||||
interface PartialStatement extends Statement {
|
||||
type: 'PartialStatement';
|
||||
name: PathExpression | SubExpression;
|
||||
params: Expression[];
|
||||
hash: Hash;
|
||||
@@ -301,6 +304,7 @@ declare namespace hbs {
|
||||
}
|
||||
|
||||
interface PartialBlockStatement extends Statement {
|
||||
type: 'PartialBlockStatement';
|
||||
name: PathExpression | SubExpression;
|
||||
params: Expression[];
|
||||
hash: Hash;
|
||||
@@ -310,11 +314,13 @@ declare namespace hbs {
|
||||
}
|
||||
|
||||
interface ContentStatement extends Statement {
|
||||
type: 'ContentStatement';
|
||||
value: string;
|
||||
original: StripFlags;
|
||||
}
|
||||
|
||||
interface CommentStatement extends Statement {
|
||||
type: 'CommentStatement';
|
||||
value: string;
|
||||
strip: StripFlags;
|
||||
}
|
||||
@@ -322,12 +328,14 @@ declare namespace hbs {
|
||||
interface Expression extends Node {}
|
||||
|
||||
interface SubExpression extends Expression {
|
||||
type: 'SubExpression';
|
||||
path: PathExpression;
|
||||
params: Expression[];
|
||||
hash: Hash;
|
||||
}
|
||||
|
||||
interface PathExpression extends Expression {
|
||||
type: 'PathExpression';
|
||||
data: boolean;
|
||||
depth: number;
|
||||
parts: string[];
|
||||
@@ -336,29 +344,38 @@ declare namespace hbs {
|
||||
|
||||
interface Literal extends Expression {}
|
||||
interface StringLiteral extends Literal {
|
||||
type: 'StringLiteral';
|
||||
value: string;
|
||||
original: string;
|
||||
}
|
||||
|
||||
interface BooleanLiteral extends Literal {
|
||||
type: 'BooleanLiteral';
|
||||
value: boolean;
|
||||
original: boolean;
|
||||
}
|
||||
|
||||
interface NumberLiteral extends Literal {
|
||||
type: 'NumberLiteral';
|
||||
value: number;
|
||||
original: number;
|
||||
}
|
||||
|
||||
interface UndefinedLiteral extends Literal {}
|
||||
interface UndefinedLiteral extends Literal {
|
||||
type: 'UndefinedLiteral';
|
||||
}
|
||||
|
||||
interface NullLiteral extends Literal {}
|
||||
interface NullLiteral extends Literal {
|
||||
type: 'NullLiteral';
|
||||
}
|
||||
|
||||
interface Hash extends Node {
|
||||
type: 'Hash';
|
||||
pairs: HashPair[];
|
||||
}
|
||||
|
||||
interface HashPair extends Node {
|
||||
type: 'HashPair';
|
||||
key: string;
|
||||
value: Expression;
|
||||
}
|
||||
|
||||
+83
-1
@@ -110,4 +110,86 @@ Handlebars.compile('test', {
|
||||
|
||||
Handlebars.compile('test')({},{allowCallsToHelperMissing: true});
|
||||
|
||||
Handlebars.compile('test')({},{});
|
||||
Handlebars.compile('test')({},{});
|
||||
|
||||
|
||||
const allthings = {} as hbs.AST.MustacheStatement |
|
||||
hbs.AST.BlockStatement |
|
||||
hbs.AST.PartialStatement |
|
||||
hbs.AST.PartialBlockStatement |
|
||||
hbs.AST.ContentStatement |
|
||||
hbs.AST.CommentStatement |
|
||||
hbs.AST.SubExpression |
|
||||
hbs.AST.PathExpression |
|
||||
hbs.AST.StringLiteral |
|
||||
hbs.AST.BooleanLiteral |
|
||||
hbs.AST.NumberLiteral |
|
||||
hbs.AST.UndefinedLiteral |
|
||||
hbs.AST.NullLiteral |
|
||||
hbs.AST.Hash |
|
||||
hbs.AST.HashPair;
|
||||
|
||||
switch(allthings.type) {
|
||||
case "MustacheStatement":
|
||||
let mustacheStatement: hbs.AST.MustacheStatement;
|
||||
mustacheStatement = allthings;
|
||||
break;
|
||||
case "BlockStatement":
|
||||
let blockStatement: hbs.AST.BlockStatement;
|
||||
blockStatement = allthings;
|
||||
break;
|
||||
case "PartialStatement":
|
||||
let partialStatement: hbs.AST.PartialStatement;
|
||||
partialStatement = allthings;
|
||||
break;
|
||||
case "PartialBlockStatement":
|
||||
let partialBlockStatement: hbs.AST.PartialBlockStatement;
|
||||
partialBlockStatement = allthings;
|
||||
break;
|
||||
case "ContentStatement":
|
||||
let ContentStatement: hbs.AST.ContentStatement;
|
||||
ContentStatement = allthings;
|
||||
break;
|
||||
case "CommentStatement":
|
||||
let CommentStatement: hbs.AST.CommentStatement;
|
||||
CommentStatement = allthings;
|
||||
break;
|
||||
case "SubExpression":
|
||||
let SubExpression: hbs.AST.SubExpression;
|
||||
SubExpression = allthings;
|
||||
break;
|
||||
case "PathExpression":
|
||||
let PathExpression: hbs.AST.PathExpression;
|
||||
PathExpression = allthings;
|
||||
break;
|
||||
case "StringLiteral":
|
||||
let StringLiteral: hbs.AST.StringLiteral;
|
||||
StringLiteral = allthings;
|
||||
break;
|
||||
case "BooleanLiteral":
|
||||
let BooleanLiteral: hbs.AST.BooleanLiteral;
|
||||
BooleanLiteral = allthings;
|
||||
break;
|
||||
case "NumberLiteral":
|
||||
let NumberLiteral: hbs.AST.NumberLiteral;
|
||||
NumberLiteral = allthings;
|
||||
break;
|
||||
case "UndefinedLiteral":
|
||||
let UndefinedLiteral: hbs.AST.UndefinedLiteral;
|
||||
UndefinedLiteral = allthings;
|
||||
break;
|
||||
case "NullLiteral":
|
||||
let NullLiteral: hbs.AST.NullLiteral;
|
||||
NullLiteral = allthings;
|
||||
break;
|
||||
case "Hash":
|
||||
let Hash: hbs.AST.Hash;
|
||||
Hash = allthings;
|
||||
break;
|
||||
case "HashPair":
|
||||
let HashPair: hbs.AST.HashPair;
|
||||
HashPair = allthings;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Reference in New Issue
Block a user