Merge branch '4.x'

# Conflicts:
#	components/bower.json
#	components/handlebars.js.nuspec
#	components/package.json
#	package-lock.json
#	package.json
This commit is contained in:
Nils Knappmeier
2019-10-08 22:22:01 +02:00
15 changed files with 371 additions and 108 deletions
+2 -1
View File
@@ -95,6 +95,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/
@@ -109,7 +110,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
View File
@@ -194,7 +194,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');
+2 -1
View File
@@ -4,8 +4,9 @@ import {registerDefaultHelpers} from './helpers';
import {registerDefaultDecorators} from './decorators';
import logger from './logger';
export const VERSION = '4.3.0';
export const VERSION = '4.4.3';
export const COMPILER_REVISION = 8;
export const LAST_COMPATIBLE_COMPILER_REVISION = 7;
export const REVISION_CHANGES = {
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
+20 -15
View File
@@ -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) {
@@ -212,7 +218,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;
@@ -337,9 +342,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]
@@ -646,16 +651,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))'
]);
},
+10
View File
@@ -40,6 +40,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;
+21 -15
View File
@@ -1,23 +1,25 @@
import * as Utils from './utils';
import Exception from './exception';
import {COMPILER_REVISION, createFrame, REVISION_CHANGES} from './base';
import {COMPILER_REVISION, createFrame, LAST_COMPATIBLE_COMPILER_REVISION, REVISION_CHANGES} from './base';
import {moveHelperToHooks} from './helpers';
export function checkRevision(compilerInfo) {
const compilerRevision = compilerInfo && compilerInfo[0] || 1,
currentRevision = COMPILER_REVISION;
if (compilerRevision !== currentRevision) {
if (compilerRevision < currentRevision) {
const runtimeVersions = REVISION_CHANGES[currentRevision],
compilerVersions = REVISION_CHANGES[compilerRevision];
throw new Exception('Template was precompiled with an older version of Handlebars than the current runtime. ' +
'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
} else {
// Use the embedded version info since the runtime doesn't know about this revision yet
throw new Exception('Template was precompiled with a newer version of Handlebars than the current runtime. ' +
'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
}
if (compilerRevision >= LAST_COMPATIBLE_COMPILER_REVISION && compilerRevision <= COMPILER_REVISION) {
return;
}
if (compilerRevision < LAST_COMPATIBLE_COMPILER_REVISION) {
const runtimeVersions = REVISION_CHANGES[currentRevision],
compilerVersions = REVISION_CHANGES[compilerRevision];
throw new Exception('Template was precompiled with an older version of Handlebars than the current runtime. ' +
'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
} else {
// Use the embedded version info since the runtime doesn't know about this revision yet
throw new Exception('Template was precompiled with a newer version of Handlebars than the current runtime. ' +
'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
}
}
@@ -37,6 +39,9 @@ export function template(templateSpec, env) {
// for external users to override these as pseudo-supported APIs.
env.VM.checkRevision(templateSpec.compiler);
// backwards compatibility for precompiled templates with compiler-version 7 (<4.3.0)
const templateWasPrecompiledWithCompilerV7 = templateSpec.compiler && templateSpec.compiler[0] === 7;
function invokePartialWrapper(partial, context, options) {
if (options.hash) {
context = Utils.extend({}, context, options.hash);
@@ -160,9 +165,10 @@ export function template(templateSpec, env) {
}
container.hooks = {};
let keepHelper = options.allowCallsToHelperMissing;
moveHelperToHooks(container, 'helperMissing', keepHelper);
moveHelperToHooks(container, 'blockHelperMissing', keepHelper);
let keepHelperInHelpers = options.allowCallsToHelperMissing || templateWasPrecompiledWithCompilerV7;
moveHelperToHooks(container, 'helperMissing', keepHelperInHelpers);
moveHelperToHooks(container, 'blockHelperMissing', keepHelperInHelpers);
} else {
container.helpers = options.helpers;
+70 -68
View File
@@ -4,6 +4,76 @@
"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",
@@ -3737,33 +3807,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",
@@ -7148,47 +7191,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",
+1 -1
View File
@@ -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": "kpdecker/istanbul",
"jison": "0.4.16",
+62 -1
View File
@@ -2,7 +2,68 @@
## Development
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.0...master)
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.3...master)
## 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:
- do not break on precompiled templates from Handlebars >=4.0.0 <4.3.0 - 1266838, #1561
- Ensure allowCallsToHelperMissing runtime option is optional in typings - 93444c5, 64ecb9e, #1560
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.0...v4.3.1)
## v4.3.0 - September 24th, 2019
Fixes:
+31
View File
@@ -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() {
+32
View File
@@ -302,4 +302,36 @@ describe('Regressions', function() {
};
shouldCompileToWithPartials(string, [{}, {}, partials], true, 'template block partial block template');
});
describe('GH-1561: 4.3.x should still work with precompiled templates from 4.0.0 <= x < 4.3.0', function() {
it('should compile and execute templates', function() {
var newHandlebarsInstance = Handlebars.create();
registerTemplate(newHandlebarsInstance);
newHandlebarsInstance.registerHelper('loud', function(value) {
return value.toUpperCase();
});
var result = newHandlebarsInstance.templates['test.hbs']({name: 'yehuda'});
equals(result.trim(), 'YEHUDA');
});
it('should call "helperMissing" if a helper is missing', function() {
var newHandlebarsInstance = Handlebars.create();
shouldThrow(function() {
registerTemplate(newHandlebarsInstance);
newHandlebarsInstance.templates['test.hbs']({});
}, Handlebars.Exception, 'Missing helper: "loud"');
});
// This is a only slightly modified precompiled templated from compiled with 4.2.1
function registerTemplate(Handlebars) {
var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
templates['test.hbs'] = template({'compiler': [7, '>= 4.0.0'], 'main': function(container, depth0, helpers, partials, data) {
return container.escapeExpression((helpers.loud || (depth0 && depth0.loud) || helpers.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}), (depth0 != null ? depth0.name : depth0), {'name': 'loud', 'hash': {}, 'data': data}))
+ '\n\n';
}, 'useData': true});
}
});
});
+1 -1
View File
@@ -21,7 +21,7 @@ describe('runtime', function() {
shouldThrow(function() {
Handlebars.template({
main: {},
compiler: [Handlebars.COMPILER_REVISION - 1]
compiler: [Handlebars.LAST_COMPATIBLE_COMPILER_REVISION - 1]
});
}, Error, /Template was precompiled with an older version of Handlebars than the current runtime/);
shouldThrow(function() {
+14 -1
View File
@@ -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}}', {}, '');
});
});
});
+20 -3
View File
@@ -29,7 +29,7 @@ declare namespace Handlebars {
decorators?: { [name: string]: Function };
data?: any;
blockParams?: any[];
allowCallsToHelperMissing: boolean;
allowCallsToHelperMissing?: boolean;
}
export interface HelperOptions {
@@ -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;
}
+84
View File
@@ -109,3 +109,87 @@ Handlebars.compile('test', {
});
Handlebars.compile('test')({},{allowCallsToHelperMissing: true});
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;
}