Skip to content

Commit

Permalink
Drop AST constructors in favor of JSON
Browse files Browse the repository at this point in the history
These were little more than object literal statements that were less clear due to their use of index-based arguments.

Fixes #1077
  • Loading branch information
kpdecker committed Aug 19, 2015
1 parent 9a2d1d6 commit 95d84ba
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 299 deletions.
126 changes: 0 additions & 126 deletions lib/handlebars/compiler/ast.js
Original file line number Diff line number Diff line change
@@ -1,130 +1,4 @@
let AST = {
Program: function(statements, blockParams, strip, locInfo) {
this.loc = locInfo;
this.type = 'Program';
this.body = statements;

this.blockParams = blockParams;
this.strip = strip;
},

MustacheStatement: function(path, params, hash, escaped, strip, locInfo) {
this.loc = locInfo;
this.type = 'MustacheStatement';

this.path = path;
this.params = params || [];
this.hash = hash;
this.escaped = escaped;

this.strip = strip;
},

BlockStatement: function(path, params, hash, program, inverse, openStrip, inverseStrip, closeStrip, locInfo) {
this.loc = locInfo;
this.type = 'BlockStatement';

this.path = path;
this.params = params || [];
this.hash = hash;
this.program = program;
this.inverse = inverse;

this.openStrip = openStrip;
this.inverseStrip = inverseStrip;
this.closeStrip = closeStrip;
},

PartialStatement: function(name, params, hash, strip, locInfo) {
this.loc = locInfo;
this.type = 'PartialStatement';

this.name = name;
this.params = params || [];
this.hash = hash;

this.indent = '';
this.strip = strip;
},

ContentStatement: function(string, locInfo) {
this.loc = locInfo;
this.type = 'ContentStatement';
this.original = this.value = string;
},

CommentStatement: function(comment, strip, locInfo) {
this.loc = locInfo;
this.type = 'CommentStatement';
this.value = comment;

this.strip = strip;
},

SubExpression: function(path, params, hash, locInfo) {
this.loc = locInfo;

this.type = 'SubExpression';
this.path = path;
this.params = params || [];
this.hash = hash;
},

PathExpression: function(data, depth, parts, original, locInfo) {
this.loc = locInfo;
this.type = 'PathExpression';

this.data = data;
this.original = original;
this.parts = parts;
this.depth = depth;
},

StringLiteral: function(string, locInfo) {
this.loc = locInfo;
this.type = 'StringLiteral';
this.original =
this.value = string;
},

NumberLiteral: function(number, locInfo) {
this.loc = locInfo;
this.type = 'NumberLiteral';
this.original =
this.value = Number(number);
},

BooleanLiteral: function(bool, locInfo) {
this.loc = locInfo;
this.type = 'BooleanLiteral';
this.original =
this.value = bool === 'true';
},

UndefinedLiteral: function(locInfo) {
this.loc = locInfo;
this.type = 'UndefinedLiteral';
this.original = this.value = undefined;
},

NullLiteral: function(locInfo) {
this.loc = locInfo;
this.type = 'NullLiteral';
this.original = this.value = null;
},

Hash: function(pairs, locInfo) {
this.loc = locInfo;
this.type = 'Hash';
this.pairs = pairs;
},
HashPair: function(key, value, locInfo) {
this.loc = locInfo;
this.type = 'HashPair';
this.key = key;
this.value = value;
},

// Public API used to evaluate derived attributes regarding AST nodes
helpers: {
// a mustache is definitely a helper if:
Expand Down
3 changes: 1 addition & 2 deletions lib/handlebars/compiler/base.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import parser from './parser';
import AST from './ast';
import WhitespaceControl from './whitespace-control';
import * as Helpers from './helpers';
import { extend } from '../utils';

export { parser };

let yy = {};
extend(yy, Helpers, AST);
extend(yy, Helpers);

export function parse(input, options) {
// Just return if an already-compiled AST was passed in.
Expand Down
9 changes: 8 additions & 1 deletion lib/handlebars/compiler/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,13 @@ function transformLiteralToPath(sexpr) {
let literal = sexpr.path;
// Casting to string here to make false and 0 literal values play nicely with the rest
// of the system.
sexpr.path = new AST.PathExpression(false, 0, [literal.original + ''], literal.original + '', literal.loc);
sexpr.path = {
type: 'PathExpression',
data: false,
depth: 0,
parts: [literal.original + ''],
original: literal.original + '',
loc: literal.loc
};
}
}
72 changes: 55 additions & 17 deletions lib/handlebars/compiler/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export function stripComment(comment) {
.replace(/-?-?~?\}\}$/, '');
}

export function preparePath(data, parts, locInfo) {
locInfo = this.locInfo(locInfo);
export function preparePath(data, parts, loc) {
loc = this.locInfo(loc);

let original = data ? '@' : '',
dig = [],
Expand All @@ -49,7 +49,7 @@ export function preparePath(data, parts, locInfo) {

if (!isLiteral && (part === '..' || part === '.' || part === 'this')) {
if (dig.length > 0) {
throw new Exception('Invalid path: ' + original, {loc: locInfo});
throw new Exception('Invalid path: ' + original, {loc});
} else if (part === '..') {
depth++;
depthString += '../';
Expand All @@ -59,15 +59,30 @@ export function preparePath(data, parts, locInfo) {
}
}

return new this.PathExpression(data, depth, dig, original, locInfo);
return {
type: 'PathExpression',
data,
depth,
parts: dig,
original,
loc
};
}

export function prepareMustache(path, params, hash, open, strip, locInfo) {
// Must use charAt to support IE pre-10
let escapeFlag = open.charAt(3) || open.charAt(2),
escaped = escapeFlag !== '{' && escapeFlag !== '&';

return new this.MustacheStatement(path, params, hash, escaped, strip, this.locInfo(locInfo));
return {
type: 'MustacheStatement',
path,
params,
hash,
escaped,
strip,
loc: this.locInfo(locInfo)
};
}

export function prepareRawBlock(openRawBlock, contents, close, locInfo) {
Expand All @@ -78,13 +93,24 @@ export function prepareRawBlock(openRawBlock, contents, close, locInfo) {
}

locInfo = this.locInfo(locInfo);
let program = new this.Program(contents, null, {}, locInfo);
let program = {
type: 'Program',
body: contents,
strip: {},
loc: locInfo
};

return new this.BlockStatement(
openRawBlock.path, openRawBlock.params, openRawBlock.hash,
program, undefined,
{}, {}, {},
locInfo);
return {
type: 'BlockStatement',
path: openRawBlock.path,
params: openRawBlock.params,
hash: openRawBlock.hash,
program,
openStrip: {},
inverseStrip: {},
closeStrip: {},
loc: locInfo
};
}

export function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
Expand Down Expand Up @@ -115,11 +141,18 @@ export function prepareBlock(openBlock, program, inverseAndProgram, close, inver
program = inverted;
}

return new this.BlockStatement(
openBlock.path, openBlock.params, openBlock.hash,
program, inverse,
openBlock.strip, inverseStrip, close && close.strip,
this.locInfo(locInfo));
return {
type: 'BlockStatement',
path: openBlock.path,
params: openBlock.params,
hash: openBlock.hash,
program,
inverse,
openStrip: openBlock.strip,
inverseStrip,
closeStrip: close && close.strip,
loc: this.locInfo(locInfo)
};
}

export function prepareProgram(statements, loc) {
Expand All @@ -143,7 +176,12 @@ export function prepareProgram(statements, loc) {
}
}

return new this.Program(statements, null, {}, loc);
return {
type: 'Program',
body: statements,
strip: {},
loc: loc
};
}


3 changes: 1 addition & 2 deletions lib/handlebars/compiler/visitor.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Exception from '../exception';
import AST from './ast';

function Visitor() {
this.parents = [];
Expand All @@ -14,7 +13,7 @@ Visitor.prototype = {
let value = this.accept(node[name]);
if (this.mutating) {
// Hacky sanity check:
if (value && (!value.type || !AST[value.type])) {
if (value && typeof value.type !== 'string') {
throw new Exception('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
}
node[name] = value;
Expand Down
Loading

0 comments on commit 95d84ba

Please sign in to comment.