ember-legacy-class-transform
Version:
The default blueprint for ember-cli addons.
1,331 lines (1,109 loc) • 48.3 kB
JavaScript
define('@glimmer/compiler', ['exports', '@glimmer/syntax', '@glimmer/util', '@glimmer/wire-format'], function (exports, _glimmer_syntax, _glimmer_util, _glimmer_wireFormat) { 'use strict';
var _createClass$1 = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); }
function _classCallCheck$1(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var SymbolTable = function () {
function SymbolTable() {
_classCallCheck$1(this, SymbolTable);
}
SymbolTable.top = function top() {
return new ProgramSymbolTable();
};
SymbolTable.prototype.child = function child(locals) {
var _this = this;
var symbols = locals.map(function (name) {
return _this.allocate(name);
});
return new BlockSymbolTable(this, locals, symbols);
};
return SymbolTable;
}();
var ProgramSymbolTable = function (_SymbolTable) {
_inherits(ProgramSymbolTable, _SymbolTable);
function ProgramSymbolTable() {
_classCallCheck$1(this, ProgramSymbolTable);
var _this2 = _possibleConstructorReturn(this, _SymbolTable.apply(this, arguments));
_this2.symbols = [];
_this2.size = 1;
_this2.named = _glimmer_util.dict();
_this2.blocks = _glimmer_util.dict();
return _this2;
}
ProgramSymbolTable.prototype.has = function has(_name) {
return false;
};
ProgramSymbolTable.prototype.get = function get(_name) {
throw _glimmer_util.unreachable();
};
ProgramSymbolTable.prototype.getLocalsMap = function getLocalsMap() {
return {};
};
ProgramSymbolTable.prototype.getEvalInfo = function getEvalInfo() {
return [];
};
ProgramSymbolTable.prototype.allocateNamed = function allocateNamed(name) {
var named = this.named[name];
if (!named) {
named = this.named[name] = this.allocate('@' + name);
}
return named;
};
ProgramSymbolTable.prototype.allocateBlock = function allocateBlock(name) {
var block = this.blocks[name];
if (!block) {
block = this.blocks[name] = this.allocate('&' + name);
}
return block;
};
ProgramSymbolTable.prototype.allocate = function allocate(identifier) {
this.symbols.push(identifier);
return this.size++;
};
return ProgramSymbolTable;
}(SymbolTable);
var BlockSymbolTable = function (_SymbolTable2) {
_inherits(BlockSymbolTable, _SymbolTable2);
function BlockSymbolTable(parent, symbols, slots) {
_classCallCheck$1(this, BlockSymbolTable);
var _this3 = _possibleConstructorReturn(this, _SymbolTable2.call(this));
_this3.parent = parent;
_this3.symbols = symbols;
_this3.slots = slots;
return _this3;
}
BlockSymbolTable.prototype.has = function has(name) {
return this.symbols.indexOf(name) !== -1 || this.parent.has(name);
};
BlockSymbolTable.prototype.get = function get(name) {
var slot = this.symbols.indexOf(name);
return slot === -1 ? this.parent.get(name) : this.slots[slot];
};
BlockSymbolTable.prototype.getLocalsMap = function getLocalsMap() {
var _this4 = this;
var dict$$1 = this.parent.getLocalsMap();
this.symbols.forEach(function (symbol) {
return dict$$1[symbol] = _this4.get(symbol);
});
return dict$$1;
};
BlockSymbolTable.prototype.getEvalInfo = function getEvalInfo() {
var locals = this.getLocalsMap();
return Object.keys(locals).map(function (symbol) {
return locals[symbol];
});
};
BlockSymbolTable.prototype.allocateNamed = function allocateNamed(name) {
return this.parent.allocateNamed(name);
};
BlockSymbolTable.prototype.allocateBlock = function allocateBlock(name) {
return this.parent.allocateBlock(name);
};
BlockSymbolTable.prototype.allocate = function allocate(identifier) {
return this.parent.allocate(identifier);
};
return BlockSymbolTable;
}(SymbolTable);
/**
* Takes in an AST and outputs a list of actions to be consumed
* by a compiler. For example, the template
*
* foo{{bar}}<div>baz</div>
*
* produces the actions
*
* [['startProgram', [programNode, 0]],
* ['text', [textNode, 0, 3]],
* ['mustache', [mustacheNode, 1, 3]],
* ['openElement', [elementNode, 2, 3, 0]],
* ['text', [textNode, 0, 1]],
* ['closeElement', [elementNode, 2, 3],
* ['endProgram', [programNode]]]
*
* This visitor walks the AST depth first and backwards. As
* a result the bottom-most child template will appear at the
* top of the actions list whereas the root template will appear
* at the bottom of the list. For example,
*
* <div>{{#if}}foo{{else}}bar<b></b>{{/if}}</div>
*
* produces the actions
*
* [['startProgram', [programNode, 0]],
* ['text', [textNode, 0, 2, 0]],
* ['openElement', [elementNode, 1, 2, 0]],
* ['closeElement', [elementNode, 1, 2]],
* ['endProgram', [programNode]],
* ['startProgram', [programNode, 0]],
* ['text', [textNode, 0, 1]],
* ['endProgram', [programNode]],
* ['startProgram', [programNode, 2]],
* ['openElement', [elementNode, 0, 1, 1]],
* ['block', [blockNode, 0, 1]],
* ['closeElement', [elementNode, 0, 1]],
* ['endProgram', [programNode]]]
*
* The state of the traversal is maintained by a stack of frames.
* Whenever a node with children is entered (either a ProgramNode
* or an ElementNode) a frame is pushed onto the stack. The frame
* contains information about the state of the traversal of that
* node. For example,
*
* - index of the current child node being visited
* - the number of mustaches contained within its child nodes
* - the list of actions generated by its child nodes
*/
var Frame = function Frame() {
_classCallCheck$1(this, Frame);
this.parentNode = null;
this.children = null;
this.childIndex = null;
this.childCount = null;
this.childTemplateCount = 0;
this.mustacheCount = 0;
this.actions = [];
this.blankChildTextNodes = null;
this.symbols = null;
};
var TemplateVisitor = function () {
function TemplateVisitor() {
_classCallCheck$1(this, TemplateVisitor);
this.frameStack = [];
this.actions = [];
this.programDepth = -1;
}
TemplateVisitor.prototype.visit = function visit(node) {
this[node.type](node);
};
// Traversal methods
TemplateVisitor.prototype.Program = function Program(program) {
var _actions;
this.programDepth++;
var parentFrame = this.getCurrentFrame();
var programFrame = this.pushFrame();
if (!parentFrame) {
program['symbols'] = SymbolTable.top();
} else {
program['symbols'] = parentFrame.symbols.child(program.blockParams);
}
var startType = void 0,
endType = void 0;
if (this.programDepth === 0) {
startType = 'startProgram';
endType = 'endProgram';
} else {
startType = 'startBlock';
endType = 'endBlock';
}
programFrame.parentNode = program;
programFrame.children = program.body;
programFrame.childCount = program.body.length;
programFrame.blankChildTextNodes = [];
programFrame.actions.push([endType, [program, this.programDepth]]);
programFrame.symbols = program['symbols'];
for (var i = program.body.length - 1; i >= 0; i--) {
programFrame.childIndex = i;
this.visit(program.body[i]);
}
programFrame.actions.push([startType, [program, programFrame.childTemplateCount, programFrame.blankChildTextNodes.reverse()]]);
this.popFrame();
this.programDepth--;
// Push the completed template into the global actions list
if (parentFrame) {
parentFrame.childTemplateCount++;
}
(_actions = this.actions).push.apply(_actions, programFrame.actions.reverse());
};
TemplateVisitor.prototype.ElementNode = function ElementNode(element) {
var _parentFrame$actions;
var parentFrame = this.currentFrame;
var elementFrame = this.pushFrame();
elementFrame.parentNode = element;
elementFrame.children = element.children;
elementFrame.childCount = element.children.length;
elementFrame.mustacheCount += element.modifiers.length;
elementFrame.blankChildTextNodes = [];
elementFrame.symbols = element['symbols'] = parentFrame.symbols.child(element.blockParams);
var actionArgs = [element, parentFrame.childIndex, parentFrame.childCount];
elementFrame.actions.push(['closeElement', actionArgs]);
for (var i = element.attributes.length - 1; i >= 0; i--) {
this.visit(element.attributes[i]);
}
for (var _i = element.children.length - 1; _i >= 0; _i--) {
elementFrame.childIndex = _i;
this.visit(element.children[_i]);
}
var open = ['openElement', [].concat(actionArgs, [elementFrame.mustacheCount, elementFrame.blankChildTextNodes.reverse()])];
elementFrame.actions.push(open);
this.popFrame();
// Propagate the element's frame state to the parent frame
if (elementFrame.mustacheCount > 0) {
parentFrame.mustacheCount++;
}
parentFrame.childTemplateCount += elementFrame.childTemplateCount;
(_parentFrame$actions = parentFrame.actions).push.apply(_parentFrame$actions, elementFrame.actions);
};
TemplateVisitor.prototype.AttrNode = function AttrNode(attr) {
if (attr.value.type !== 'TextNode') {
this.currentFrame.mustacheCount++;
}
};
TemplateVisitor.prototype.TextNode = function TextNode(text) {
var frame = this.currentFrame;
if (text.chars === '') {
frame.blankChildTextNodes.push(domIndexOf(frame.children, text));
}
frame.actions.push(['text', [text, frame.childIndex, frame.childCount]]);
};
TemplateVisitor.prototype.BlockStatement = function BlockStatement(node) {
var frame = this.currentFrame;
frame.mustacheCount++;
frame.actions.push(['block', [node, frame.childIndex, frame.childCount]]);
if (node.inverse) {
this.visit(node.inverse);
}
if (node.program) {
this.visit(node.program);
}
};
TemplateVisitor.prototype.PartialStatement = function PartialStatement(node) {
var frame = this.currentFrame;
frame.mustacheCount++;
frame.actions.push(['mustache', [node, frame.childIndex, frame.childCount]]);
};
TemplateVisitor.prototype.CommentStatement = function CommentStatement(text) {
var frame = this.currentFrame;
frame.actions.push(['comment', [text, frame.childIndex, frame.childCount]]);
};
TemplateVisitor.prototype.MustacheCommentStatement = function MustacheCommentStatement() {
// Intentional empty: Handlebars comments should not affect output.
};
TemplateVisitor.prototype.MustacheStatement = function MustacheStatement(mustache) {
var frame = this.currentFrame;
frame.mustacheCount++;
frame.actions.push(['mustache', [mustache, frame.childIndex, frame.childCount]]);
};
// Frame helpers
TemplateVisitor.prototype.getCurrentFrame = function getCurrentFrame() {
return this.frameStack[this.frameStack.length - 1];
};
TemplateVisitor.prototype.pushFrame = function pushFrame() {
var frame = new Frame();
this.frameStack.push(frame);
return frame;
};
TemplateVisitor.prototype.popFrame = function popFrame() {
return this.frameStack.pop();
};
_createClass$1(TemplateVisitor, [{
key: 'currentFrame',
get: function () {
return this.getCurrentFrame();
}
}]);
return TemplateVisitor;
}();
function domIndexOf(nodes, domNode) {
var index = -1;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
if (node.type !== 'TextNode' && node.type !== 'ElementNode') {
continue;
} else {
index++;
}
if (node === domNode) {
return index;
}
}
return -1;
}
var _createClass$2 = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _defaults$1(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
function _possibleConstructorReturn$1(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits$1(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults$1(subClass, superClass); }
function _classCallCheck$2(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Block = function () {
function Block() {
_classCallCheck$2(this, Block);
this.statements = [];
}
Block.prototype.push = function push(statement) {
this.statements.push(statement);
};
return Block;
}();
var InlineBlock = function (_Block) {
_inherits$1(InlineBlock, _Block);
function InlineBlock(table) {
_classCallCheck$2(this, InlineBlock);
var _this = _possibleConstructorReturn$1(this, _Block.call(this));
_this.table = table;
return _this;
}
InlineBlock.prototype.toJSON = function toJSON() {
return {
statements: this.statements,
parameters: this.table.slots
};
};
return InlineBlock;
}(Block);
var TemplateBlock = function (_Block2) {
_inherits$1(TemplateBlock, _Block2);
function TemplateBlock(symbolTable) {
_classCallCheck$2(this, TemplateBlock);
var _this2 = _possibleConstructorReturn$1(this, _Block2.call(this));
_this2.symbolTable = symbolTable;
_this2.type = "template";
_this2.yields = new _glimmer_util.DictSet();
_this2.named = new _glimmer_util.DictSet();
_this2.blocks = [];
_this2.hasEval = false;
return _this2;
}
TemplateBlock.prototype.push = function push(statement) {
this.statements.push(statement);
};
TemplateBlock.prototype.toJSON = function toJSON() {
return {
symbols: this.symbolTable.symbols,
statements: this.statements,
hasEval: this.hasEval
};
};
return TemplateBlock;
}(Block);
var ComponentBlock = function (_Block3) {
_inherits$1(ComponentBlock, _Block3);
function ComponentBlock(table) {
_classCallCheck$2(this, ComponentBlock);
var _this3 = _possibleConstructorReturn$1(this, _Block3.call(this));
_this3.table = table;
_this3.attributes = [];
_this3.arguments = [];
_this3.inParams = true;
_this3.positionals = [];
return _this3;
}
ComponentBlock.prototype.push = function push(statement) {
if (this.inParams) {
if (_glimmer_wireFormat.Statements.isFlushElement(statement)) {
this.inParams = false;
} else if (_glimmer_wireFormat.Statements.isArgument(statement)) {
this.arguments.push(statement);
} else if (_glimmer_wireFormat.Statements.isAttribute(statement)) {
this.attributes.push(statement);
} else if (_glimmer_wireFormat.Statements.isModifier(statement)) {
throw new Error('Compile Error: Element modifiers are not allowed in components');
} else {
throw new Error('Compile Error: only parameters allowed before flush-element');
}
} else {
this.statements.push(statement);
}
};
ComponentBlock.prototype.toJSON = function toJSON() {
var args = this.arguments;
var keys = args.map(function (arg) {
return arg[1];
});
var values = args.map(function (arg) {
return arg[2];
});
return [this.attributes, [keys, values], {
statements: this.statements,
parameters: this.table.slots
}];
};
return ComponentBlock;
}(Block);
var Template = function () {
function Template(symbols, meta) {
_classCallCheck$2(this, Template);
this.meta = meta;
this.block = new TemplateBlock(symbols);
}
Template.prototype.toJSON = function toJSON() {
return {
block: this.block.toJSON(),
meta: this.meta
};
};
return Template;
}();
var JavaScriptCompiler = function () {
function JavaScriptCompiler(opcodes, symbols, meta) {
_classCallCheck$2(this, JavaScriptCompiler);
this.blocks = new _glimmer_util.Stack();
this.values = [];
this.opcodes = opcodes;
this.template = new Template(symbols, meta);
}
JavaScriptCompiler.process = function process(opcodes, symbols, meta) {
var compiler = new JavaScriptCompiler(opcodes, symbols, meta);
return compiler.process();
};
JavaScriptCompiler.prototype.process = function process() {
var _this4 = this;
this.opcodes.forEach(function (_ref) {
var opcode = _ref[0],
args = _ref.slice(1);
if (!_this4[opcode]) {
throw new Error("unimplemented " + opcode + " on JavaScriptCompiler");
}
_this4[opcode].apply(_this4, args);
});
return this.template;
};
/// Nesting
JavaScriptCompiler.prototype.startBlock = function startBlock(_ref2) {
var program = _ref2[0];
var block = new InlineBlock(program['symbols']);
this.blocks.push(block);
};
JavaScriptCompiler.prototype.endBlock = function endBlock() {
var template = this.template,
blocks = this.blocks;
var block = blocks.pop();
template.block.blocks.push(block.toJSON());
};
JavaScriptCompiler.prototype.startProgram = function startProgram() {
this.blocks.push(this.template.block);
};
JavaScriptCompiler.prototype.endProgram = function endProgram() {};
/// Statements
JavaScriptCompiler.prototype.text = function text(content) {
this.push([_glimmer_wireFormat.Ops.Text, content]);
};
JavaScriptCompiler.prototype.append = function append(trusted) {
this.push([_glimmer_wireFormat.Ops.Append, this.popValue(), trusted]);
};
JavaScriptCompiler.prototype.comment = function comment(value) {
this.push([_glimmer_wireFormat.Ops.Comment, value]);
};
JavaScriptCompiler.prototype.modifier = function modifier(name) {
var params = this.popValue();
var hash = this.popValue();
this.push([_glimmer_wireFormat.Ops.Modifier, name, params, hash]);
};
JavaScriptCompiler.prototype.block = function block(name, template, inverse) {
var params = this.popValue();
var hash = this.popValue();
var blocks = this.template.block.blocks;
_glimmer_util.assert(typeof template !== 'number' || blocks[template] !== null, 'missing block in the compiler');
_glimmer_util.assert(typeof inverse !== 'number' || blocks[inverse] !== null, 'missing block in the compiler');
this.push([_glimmer_wireFormat.Ops.Block, name, params, hash, blocks[template], blocks[inverse]]);
};
JavaScriptCompiler.prototype.openElement = function openElement(element) {
var tag = element.tag;
if (tag.indexOf('-') !== -1) {
this.startComponent(element);
} else if (element.blockParams.length > 0) {
throw new Error("Compile Error: <" + element.tag + "> is not a component and doesn't support block parameters");
} else {
this.push([_glimmer_wireFormat.Ops.OpenElement, tag]);
}
};
JavaScriptCompiler.prototype.flushElement = function flushElement() {
this.push([_glimmer_wireFormat.Ops.FlushElement]);
};
JavaScriptCompiler.prototype.closeElement = function closeElement(element) {
var tag = element.tag;
if (tag.indexOf('-') !== -1) {
var _endComponent = this.endComponent(),
attrs = _endComponent[0],
args = _endComponent[1],
block = _endComponent[2];
this.push([_glimmer_wireFormat.Ops.Component, tag, attrs, args, block]);
} else {
this.push([_glimmer_wireFormat.Ops.CloseElement]);
}
};
JavaScriptCompiler.prototype.staticAttr = function staticAttr(name, namespace) {
var value = this.popValue();
this.push([_glimmer_wireFormat.Ops.StaticAttr, name, value, namespace]);
};
JavaScriptCompiler.prototype.dynamicAttr = function dynamicAttr(name, namespace) {
var value = this.popValue();
this.push([_glimmer_wireFormat.Ops.DynamicAttr, name, value, namespace]);
};
JavaScriptCompiler.prototype.trustingAttr = function trustingAttr(name, namespace) {
var value = this.popValue();
this.push([_glimmer_wireFormat.Ops.TrustingAttr, name, value, namespace]);
};
JavaScriptCompiler.prototype.staticArg = function staticArg(name) {
var value = this.popValue();
this.push([_glimmer_wireFormat.Ops.StaticArg, name, value]);
};
JavaScriptCompiler.prototype.dynamicArg = function dynamicArg(name) {
var value = this.popValue();
this.push([_glimmer_wireFormat.Ops.DynamicArg, name, value]);
};
JavaScriptCompiler.prototype.yield = function _yield(to) {
var params = this.popValue();
this.push([_glimmer_wireFormat.Ops.Yield, to, params]);
};
JavaScriptCompiler.prototype.debugger = function _debugger(evalInfo) {
this.push([_glimmer_wireFormat.Ops.Debugger, evalInfo]);
this.template.block.hasEval = true;
};
JavaScriptCompiler.prototype.hasBlock = function hasBlock(name) {
this.pushValue([_glimmer_wireFormat.Ops.HasBlock, name]);
};
JavaScriptCompiler.prototype.hasBlockParams = function hasBlockParams(name) {
this.pushValue([_glimmer_wireFormat.Ops.HasBlockParams, name]);
};
JavaScriptCompiler.prototype.partial = function partial(evalInfo) {
var params = this.popValue();
this.push([_glimmer_wireFormat.Ops.Partial, params[0], evalInfo]);
this.template.block.hasEval = true;
};
/// Expressions
JavaScriptCompiler.prototype.literal = function literal(value) {
if (value === undefined) {
this.pushValue([_glimmer_wireFormat.Ops.Undefined]);
} else {
this.pushValue(value);
}
};
JavaScriptCompiler.prototype.unknown = function unknown(name) {
this.pushValue([_glimmer_wireFormat.Ops.Unknown, name]);
};
JavaScriptCompiler.prototype.get = function get(head, path) {
this.pushValue([_glimmer_wireFormat.Ops.Get, head, path]);
};
JavaScriptCompiler.prototype.maybeLocal = function maybeLocal(path) {
this.pushValue([_glimmer_wireFormat.Ops.MaybeLocal, path]);
};
JavaScriptCompiler.prototype.concat = function concat() {
this.pushValue([_glimmer_wireFormat.Ops.Concat, this.popValue()]);
};
JavaScriptCompiler.prototype.helper = function helper(name) {
var params = this.popValue();
var hash = this.popValue();
this.pushValue([_glimmer_wireFormat.Ops.Helper, name, params, hash]);
};
/// Stack Management Opcodes
JavaScriptCompiler.prototype.startComponent = function startComponent(element) {
var component = new ComponentBlock(element['symbols']);
this.blocks.push(component);
};
JavaScriptCompiler.prototype.endComponent = function endComponent() {
var component = this.blocks.pop();
_glimmer_util.assert(component instanceof ComponentBlock, "Compiler bug: endComponent() should end a component");
return component.toJSON();
};
JavaScriptCompiler.prototype.prepareArray = function prepareArray(size) {
var values = [];
for (var i = 0; i < size; i++) {
values.push(this.popValue());
}
this.pushValue(values);
};
JavaScriptCompiler.prototype.prepareObject = function prepareObject(size) {
_glimmer_util.assert(this.values.length >= size, "Expected " + size + " values on the stack, found " + this.values.length);
var keys = new Array(size);
var values = new Array(size);
for (var i = 0; i < size; i++) {
keys[i] = this.popValue();
values[i] = this.popValue();
}
this.pushValue([keys, values]);
};
/// Utilities
JavaScriptCompiler.prototype.push = function push(args) {
while (args[args.length - 1] === null) {
args.pop();
}
this.currentBlock.push(args);
};
JavaScriptCompiler.prototype.pushValue = function pushValue(val) {
this.values.push(val);
};
JavaScriptCompiler.prototype.popValue = function popValue() {
_glimmer_util.assert(this.values.length, "No expression found on stack");
return this.values.pop();
};
_createClass$2(JavaScriptCompiler, [{
key: "currentBlock",
get: function () {
return this.blocks.current;
}
}]);
return JavaScriptCompiler;
}();
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function isTrustedValue(value) {
return value.escaped !== undefined && !value.escaped;
}
var TemplateCompiler = function () {
function TemplateCompiler(options) {
_classCallCheck(this, TemplateCompiler);
this.templateId = 0;
this.templateIds = [];
this.symbolStack = new _glimmer_util.Stack();
this.opcodes = [];
this.includeMeta = false;
this.options = options || {};
}
TemplateCompiler.compile = function compile(options, ast) {
var templateVisitor = new TemplateVisitor();
templateVisitor.visit(ast);
var compiler = new TemplateCompiler(options);
var opcodes = compiler.process(templateVisitor.actions);
return JavaScriptCompiler.process(opcodes, ast['symbols'], options.meta);
};
TemplateCompiler.prototype.process = function process(actions) {
var _this = this;
actions.forEach(function (_ref) {
var name = _ref[0],
args = _ref.slice(1);
if (!_this[name]) {
throw new Error("Unimplemented " + name + " on TemplateCompiler");
}
_this[name].apply(_this, args);
});
return this.opcodes;
};
TemplateCompiler.prototype.startProgram = function startProgram(program) {
this.symbolStack.push(program[0]['symbols']);
this.opcode('startProgram', program, program);
};
TemplateCompiler.prototype.endProgram = function endProgram() {
this.symbolStack.pop();
this.opcode('endProgram', null);
};
TemplateCompiler.prototype.startBlock = function startBlock(program) {
this.symbolStack.push(program[0]['symbols']);
this.templateId++;
this.opcode('startBlock', program, program);
};
TemplateCompiler.prototype.endBlock = function endBlock() {
this.symbolStack.pop();
this.templateIds.push(this.templateId - 1);
this.opcode('endBlock', null);
};
TemplateCompiler.prototype.text = function text(_ref2) {
var action = _ref2[0];
this.opcode('text', action, action.chars);
};
TemplateCompiler.prototype.comment = function comment(_ref3) {
var action = _ref3[0];
this.opcode('comment', action, action.value);
};
TemplateCompiler.prototype.openElement = function openElement(_ref4) {
var action = _ref4[0];
this.opcode('openElement', action, action);
for (var i = 0; i < action.attributes.length; i++) {
this.attribute([action.attributes[i]]);
}
for (var _i = 0; _i < action.modifiers.length; _i++) {
this.modifier([action.modifiers[_i]]);
}
this.opcode('flushElement', null);
this.symbolStack.push(action['symbols']);
};
TemplateCompiler.prototype.closeElement = function closeElement(_ref5) {
var action = _ref5[0];
this.symbolStack.pop();
this.opcode('closeElement', null, action);
};
TemplateCompiler.prototype.attribute = function attribute(_ref6) {
var action = _ref6[0];
var name = action.name,
value = action.value;
var namespace = _glimmer_util.getAttrNamespace(name);
var isStatic = this.prepareAttributeValue(value);
if (name.charAt(0) === '@') {
// Arguments
if (isStatic) {
this.opcode('staticArg', action, name);
} else if (action.value.type === 'MustacheStatement') {
this.opcode('dynamicArg', action, name);
} else {
this.opcode('dynamicArg', action, name);
}
} else {
var isTrusting = isTrustedValue(value);
if (isStatic) {
this.opcode('staticAttr', action, name, namespace);
} else if (isTrusting) {
this.opcode('trustingAttr', action, name, namespace);
} else if (action.value.type === 'MustacheStatement') {
this.opcode('dynamicAttr', action, name);
} else {
this.opcode('dynamicAttr', action, name, namespace);
}
}
};
TemplateCompiler.prototype.modifier = function modifier(_ref7) {
var action = _ref7[0];
assertIsSimplePath(action.path, action.loc, 'modifier');
var parts = action.path.parts;
this.prepareHelper(action);
this.opcode('modifier', action, parts[0]);
};
TemplateCompiler.prototype.mustache = function mustache(_ref8) {
var action = _ref8[0];
var path = action.path;
if (_glimmer_syntax.isLiteral(path)) {
this.mustacheExpression(action);
this.opcode('append', action, !action.escaped);
} else if (isYield(path)) {
var to = assertValidYield(action);
this.yield(to, action);
} else if (isPartial(path)) {
var params = assertValidPartial(action);
this.partial(params, action);
} else if (isDebugger(path)) {
assertValidDebuggerUsage(action);
this.debugger('debugger', action);
} else {
this.mustacheExpression(action);
this.opcode('append', action, !action.escaped);
}
};
TemplateCompiler.prototype.block = function block(_ref9) {
var action /*, index, count*/ = _ref9[0];
this.prepareHelper(action);
var templateId = this.templateIds.pop();
var inverseId = action.inverse === null ? null : this.templateIds.pop();
this.opcode('block', action, action.path.parts[0], templateId, inverseId);
};
/// Internal actions, not found in the original processed actions
TemplateCompiler.prototype.arg = function arg(_ref10) {
var path = _ref10[0];
var _path$parts = path.parts,
head = _path$parts[0],
rest = _path$parts.slice(1);
var symbol = this.symbols.allocateNamed(head);
this.opcode('get', path, symbol, rest);
};
TemplateCompiler.prototype.mustacheExpression = function mustacheExpression(expr) {
var path = expr.path;
if (_glimmer_syntax.isLiteral(path)) {
this.opcode('literal', expr, path.value);
} else if (isBuiltInHelper(path)) {
this.builtInHelper(expr);
} else if (isArg(path)) {
this.arg([path]);
} else if (isHelperInvocation(expr)) {
this.prepareHelper(expr);
this.opcode('helper', expr, path.parts[0]);
} else if (path.this) {
this.opcode('get', expr, 0, path.parts);
} else if (isLocal(path, this.symbols)) {
var _path$parts2 = path.parts,
head = _path$parts2[0],
parts = _path$parts2.slice(1);
this.opcode('get', expr, this.symbols.get(head), parts);
} else if (isSimplePath(path)) {
this.opcode('unknown', expr, path.parts[0]);
} else {
this.opcode('maybeLocal', expr, path.parts);
}
};
/// Internal Syntax
TemplateCompiler.prototype.yield = function _yield(to, action) {
this.prepareParams(action.params);
this.opcode('yield', action, this.symbols.allocateBlock(to));
};
TemplateCompiler.prototype.debugger = function _debugger(_name, action) {
this.opcode('debugger', action, this.symbols.getEvalInfo());
};
TemplateCompiler.prototype.hasBlock = function hasBlock(name, action) {
this.opcode('hasBlock', action, this.symbols.allocateBlock(name));
};
TemplateCompiler.prototype.hasBlockParams = function hasBlockParams(name, action) {
this.opcode('hasBlockParams', action, this.symbols.allocateBlock(name));
};
TemplateCompiler.prototype.partial = function partial(_params, action) {
this.prepareParams(action.params);
this.opcode('partial', action, this.symbols.getEvalInfo());
};
TemplateCompiler.prototype.builtInHelper = function builtInHelper(expr) {
var path = expr.path;
if (isHasBlock(path)) {
var name = assertValidHasBlockUsage(expr.path.original, expr);
this.hasBlock(name, expr);
} else if (isHasBlockParams(path)) {
var _name2 = assertValidHasBlockUsage(expr.path.original, expr);
this.hasBlockParams(_name2, expr);
}
};
/// Expressions, invoked recursively from prepareParams and prepareHash
TemplateCompiler.prototype.SubExpression = function SubExpression(expr) {
if (isBuiltInHelper(expr.path)) {
this.builtInHelper(expr);
} else {
this.prepareHelper(expr);
this.opcode('helper', expr, expr.path.parts[0]);
}
};
TemplateCompiler.prototype.PathExpression = function PathExpression(expr) {
if (expr.data) {
this.arg([expr]);
} else {
var symbols = this.symbols;
var _expr$parts = expr.parts,
head = _expr$parts[0];
if (expr.this) {
this.opcode('get', expr, 0, expr.parts);
} else if (symbols.has(head)) {
this.opcode('get', expr, symbols.get(head), expr.parts.slice(1));
} else {
this.opcode('get', expr, 0, expr.parts);
}
}
};
TemplateCompiler.prototype.StringLiteral = function StringLiteral(action) {
this.opcode('literal', null, action.value);
};
TemplateCompiler.prototype.BooleanLiteral = function BooleanLiteral(action) {
this.opcode('literal', null, action.value);
};
TemplateCompiler.prototype.NumberLiteral = function NumberLiteral(action) {
this.opcode('literal', null, action.value);
};
TemplateCompiler.prototype.NullLiteral = function NullLiteral(action) {
this.opcode('literal', null, action.value);
};
TemplateCompiler.prototype.UndefinedLiteral = function UndefinedLiteral(action) {
this.opcode('literal', null, action.value);
};
/// Utilities
TemplateCompiler.prototype.opcode = function opcode(name, action) {
for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
args[_key - 2] = arguments[_key];
}
var opcode = [name].concat(args);
if (this.includeMeta && action) {
opcode.push(this.meta(action));
}
this.opcodes.push(opcode);
};
TemplateCompiler.prototype.prepareHelper = function prepareHelper(expr) {
assertIsSimplePath(expr.path, expr.loc, 'helper');
var params = expr.params,
hash = expr.hash;
this.prepareHash(hash);
this.prepareParams(params);
};
TemplateCompiler.prototype.prepareParams = function prepareParams(params) {
if (!params.length) {
this.opcode('literal', null, null);
return;
}
for (var i = params.length - 1; i >= 0; i--) {
var param = params[i];
_glimmer_util.assert(this[param.type], "Unimplemented " + param.type + " on TemplateCompiler");
this[param.type](param);
}
this.opcode('prepareArray', null, params.length);
};
TemplateCompiler.prototype.prepareHash = function prepareHash(hash) {
var pairs = hash.pairs;
if (!pairs.length) {
this.opcode('literal', null, null);
return;
}
for (var i = pairs.length - 1; i >= 0; i--) {
var _pairs$i = pairs[i],
key = _pairs$i.key,
value = _pairs$i.value;
_glimmer_util.assert(this[value.type], "Unimplemented " + value.type + " on TemplateCompiler");
this[value.type](value);
this.opcode('literal', null, key);
}
this.opcode('prepareObject', null, pairs.length);
};
TemplateCompiler.prototype.prepareAttributeValue = function prepareAttributeValue(value) {
// returns the static value if the value is static
switch (value.type) {
case 'TextNode':
this.opcode('literal', value, value.chars);
return true;
case 'MustacheStatement':
this.attributeMustache([value]);
return false;
case 'ConcatStatement':
this.prepareConcatParts(value.parts);
this.opcode('concat', value);
return false;
}
};
TemplateCompiler.prototype.prepareConcatParts = function prepareConcatParts(parts) {
for (var i = parts.length - 1; i >= 0; i--) {
var part = parts[i];
if (part.type === 'MustacheStatement') {
this.attributeMustache([part]);
} else if (part.type === 'TextNode') {
this.opcode('literal', null, part.chars);
}
}
this.opcode('prepareArray', null, parts.length);
};
TemplateCompiler.prototype.attributeMustache = function attributeMustache(_ref11) {
var action = _ref11[0];
this.mustacheExpression(action);
};
TemplateCompiler.prototype.meta = function meta(node) {
var loc = node.loc;
if (!loc) {
return [];
}
var source = loc.source,
start = loc.start,
end = loc.end;
return ['loc', [source || null, [start.line, start.column], [end.line, end.column]]];
};
_createClass(TemplateCompiler, [{
key: "symbols",
get: function () {
return this.symbolStack.current;
}
}]);
return TemplateCompiler;
}();
function isHelperInvocation(mustache) {
return mustache.params && mustache.params.length > 0 || mustache.hash && mustache.hash.pairs.length > 0;
}
function isSimplePath(_ref12) {
var parts = _ref12.parts;
return parts.length === 1;
}
function isLocal(_ref13, symbols) {
var parts = _ref13.parts;
return symbols && symbols.has(parts[0]);
}
function isYield(path) {
return path.original === 'yield';
}
function isPartial(path) {
return path.original === 'partial';
}
function isDebugger(path) {
return path.original === 'debugger';
}
function isHasBlock(path) {
return path.original === 'has-block';
}
function isHasBlockParams(path) {
return path.original === 'has-block-params';
}
function isBuiltInHelper(path) {
return isHasBlock(path) || isHasBlockParams(path);
}
function isArg(path) {
return !!path['data'];
}
function assertIsSimplePath(path, loc, context) {
if (!isSimplePath(path)) {
throw new _glimmer_syntax.SyntaxError("`" + path.original + "` is not a valid name for a " + context + " on line " + loc.start.line + ".", path.loc);
}
}
function assertValidYield(statement) {
var pairs = statement.hash.pairs;
if (pairs.length === 1 && pairs[0].key !== 'to' || pairs.length > 1) {
throw new _glimmer_syntax.SyntaxError("yield only takes a single named argument: 'to'", statement.loc);
} else if (pairs.length === 1 && pairs[0].value.type !== 'StringLiteral') {
throw new _glimmer_syntax.SyntaxError("you can only yield to a literal value", statement.loc);
} else if (pairs.length === 0) {
return 'default';
} else {
return pairs[0].value.value;
}
}
function assertValidPartial(statement) {
var params = statement.params,
hash = statement.hash,
escaped = statement.escaped,
loc = statement.loc;
if (params && params.length !== 1) {
throw new _glimmer_syntax.SyntaxError("Partial found with no arguments. You must specify a template name. (on line " + loc.start.line + ")", statement.loc);
} else if (hash && hash.pairs.length > 0) {
throw new _glimmer_syntax.SyntaxError("partial does not take any named arguments (on line " + loc.start.line + ")", statement.loc);
} else if (!escaped) {
throw new _glimmer_syntax.SyntaxError("{{{partial ...}}} is not supported, please use {{partial ...}} instead (on line " + loc.start.line + ")", statement.loc);
}
return params;
}
function assertValidHasBlockUsage(type, call) {
var params = call.params,
hash = call.hash,
loc = call.loc;
if (hash && hash.pairs.length > 0) {
throw new _glimmer_syntax.SyntaxError(type + " does not take any named arguments", call.loc);
}
if (params.length === 0) {
return 'default';
} else if (params.length === 1) {
var param = params[0];
if (param.type === 'StringLiteral') {
return param.value;
} else {
throw new _glimmer_syntax.SyntaxError("you can only yield to a literal value (on line " + loc.start.line + ")", call.loc);
}
} else {
throw new _glimmer_syntax.SyntaxError(type + " only takes a single positional argument (on line " + loc.start.line + ")", call.loc);
}
}
function assertValidDebuggerUsage(statement) {
var params = statement.params,
hash = statement.hash;
if (hash && hash.pairs.length > 0) {
throw new _glimmer_syntax.SyntaxError("debugger does not take any named arguments", statement.loc);
}
if (params.length === 0) {
return 'default';
} else {
throw new _glimmer_syntax.SyntaxError("debugger does not take any positional arguments", statement.loc);
}
}
var defaultId = function () {
if (typeof require === 'function') {
try {
/* tslint:disable:no-require-imports */
var crypto = require('crypto');
/* tslint:enable:no-require-imports */
var idFn = function (src) {
var hash = crypto.createHash('sha1');
hash.update(src, 'utf8');
// trim to 6 bytes of data (2^48 - 1)
return hash.digest('base64').substring(0, 8);
};
idFn("test");
return idFn;
} catch (e) {}
}
return function idFn() {
return null;
};
}();
var defaultOptions = {
id: defaultId,
meta: {}
};
function precompile(string) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultOptions;
var ast = _glimmer_syntax.preprocess(string, options);
var _TemplateCompiler$com = TemplateCompiler.compile(options, ast),
block = _TemplateCompiler$com.block,
meta = _TemplateCompiler$com.meta;
var idFn = options.id || defaultId;
var blockJSON = JSON.stringify(block.toJSON());
var templateJSONObject = {
id: idFn(JSON.stringify(meta) + blockJSON),
block: blockJSON,
meta: meta
};
// JSON is javascript
return JSON.stringify(templateJSONObject);
}
exports.precompile = precompile;
exports.TemplateVisitor = TemplateVisitor;
Object.defineProperty(exports, '__esModule', { value: true });
});