ember-introjs
Version:
An Ember Component for intro.js
1,425 lines (1,171 loc) • 634 kB
JavaScript
(function() {
/*!
* @overview Ember - JavaScript Application Framework
* @copyright Copyright 2011-2018 Tilde Inc. and contributors
* Portions Copyright 2006-2011 Strobe Inc.
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
* @license Licensed under MIT license
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
* @version 3.0.0
*/
/*globals process */
var enifed, requireModule, Ember;
// Used in ember-environment/lib/global.js
mainContext = this; // eslint-disable-line no-undef
(function() {
function missingModule(name, referrerName) {
if (referrerName) {
throw new Error('Could not find module ' + name + ' required by: ' + referrerName);
} else {
throw new Error('Could not find module ' + name);
}
}
function internalRequire(_name, referrerName) {
var name = _name;
var mod = registry[name];
if (!mod) {
name = name + '/index';
mod = registry[name];
}
var exports = seen[name];
if (exports !== undefined) {
return exports;
}
exports = seen[name] = {};
if (!mod) {
missingModule(_name, referrerName);
}
var deps = mod.deps;
var callback = mod.callback;
var reified = new Array(deps.length);
for (var i = 0; i < deps.length; i++) {
if (deps[i] === 'exports') {
reified[i] = exports;
} else if (deps[i] === 'require') {
reified[i] = requireModule;
} else {
reified[i] = internalRequire(deps[i], name);
}
}
callback.apply(this, reified);
return exports;
}
var isNode = typeof window === 'undefined' &&
typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
if (!isNode) {
Ember = this.Ember = this.Ember || {};
}
if (typeof Ember === 'undefined') { Ember = {}; }
if (typeof Ember.__loader === 'undefined') {
var registry = {};
var seen = {};
enifed = function(name, deps, callback) {
var value = { };
if (!callback) {
value.deps = [];
value.callback = deps;
} else {
value.deps = deps;
value.callback = callback;
}
registry[name] = value;
};
requireModule = function(name) {
return internalRequire(name, null);
};
// setup `require` module
requireModule['default'] = requireModule;
requireModule.has = function registryHas(moduleName) {
return !!registry[moduleName] || !!registry[moduleName + '/index'];
};
requireModule._eak_seen = registry;
Ember.__loader = {
define: enifed,
require: requireModule,
registry: registry
};
} else {
enifed = Ember.__loader.define;
requireModule = Ember.__loader.require;
}
})();
enifed('@glimmer/compiler', ['exports', 'node-module', '@glimmer/syntax', '@glimmer/util', '@glimmer/wire-format'], function (exports, _nodeModule, _syntax, _util, _wireFormat) {
'use strict';
exports.TemplateVisitor = exports.precompile = undefined;
var _createClass$1 = function () {
function defineProperties(target, props) {
var i, descriptor;
for (i = 0; i < props.length; i++) {
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),
i,
key,
value;for (i = 0; i < keys.length; i++) {
key = keys[i];
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 () {
return new ProgramSymbolTable();
};
SymbolTable.prototype.child = function (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 = (0, _util.dict)();
_this2.blocks = (0, _util.dict)();
return _this2;
}
ProgramSymbolTable.prototype.has = function () {
return false;
};
ProgramSymbolTable.prototype.get = function () {
throw (0, _util.unreachable)();
};
ProgramSymbolTable.prototype.getLocalsMap = function () {
return {};
};
ProgramSymbolTable.prototype.getEvalInfo = function () {
return [];
};
ProgramSymbolTable.prototype.allocateNamed = function (name) {
var named = this.named[name];
if (!named) {
named = this.named[name] = this.allocate('@' + name);
}
return named;
};
ProgramSymbolTable.prototype.allocateBlock = function (name) {
var block = this.blocks[name];
if (!block) {
block = this.blocks[name] = this.allocate('&' + name);
}
return block;
};
ProgramSymbolTable.prototype.allocate = function (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 (name) {
return this.symbols.indexOf(name) !== -1 || this.parent.has(name);
};
BlockSymbolTable.prototype.get = function (name) {
var slot = this.symbols.indexOf(name);
return slot === -1 ? this.parent.get(name) : this.slots[slot];
};
BlockSymbolTable.prototype.getLocalsMap = function () {
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 () {
var locals = this.getLocalsMap();
return Object.keys(locals).map(function (symbol) {
return locals[symbol];
});
};
BlockSymbolTable.prototype.allocateNamed = function (name) {
return this.parent.allocateNamed(name);
};
BlockSymbolTable.prototype.allocateBlock = function (name) {
return this.parent.allocateBlock(name);
};
BlockSymbolTable.prototype.allocate = function (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 (node) {
this[node.type](node);
};
// Traversal methods
TemplateVisitor.prototype.Program = function (program) {
var _actions, i;
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 (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 (element) {
var _parentFrame$actions, i, _i;
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 (i = element.attributes.length - 1; i >= 0; i--) {
this.visit(element.attributes[i]);
}
for (_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 (attr) {
if (attr.value.type !== 'TextNode') {
this.currentFrame.mustacheCount++;
}
};
TemplateVisitor.prototype.TextNode = function (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 (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 (node) {
var frame = this.currentFrame;
frame.mustacheCount++;
frame.actions.push(['mustache', [node, frame.childIndex, frame.childCount]]);
};
TemplateVisitor.prototype.CommentStatement = function (text) {
var frame = this.currentFrame;
frame.actions.push(['comment', [text, frame.childIndex, frame.childCount]]);
};
TemplateVisitor.prototype.MustacheCommentStatement = function () {
// Intentional empty: Handlebars comments should not affect output.
};
TemplateVisitor.prototype.MustacheStatement = function (mustache) {
var frame = this.currentFrame;
frame.mustacheCount++;
frame.actions.push(['mustache', [mustache, frame.childIndex, frame.childCount]]);
};
// Frame helpers
TemplateVisitor.prototype.getCurrentFrame = function () {
return this.frameStack[this.frameStack.length - 1];
};
TemplateVisitor.prototype.pushFrame = function () {
var frame = new Frame();
this.frameStack.push(frame);
return frame;
};
TemplateVisitor.prototype.popFrame = function () {
return this.frameStack.pop();
};
_createClass$1(TemplateVisitor, [{
key: 'currentFrame',
get: function () {
return this.getCurrentFrame();
}
}]);
return TemplateVisitor;
}();
function domIndexOf(nodes, domNode) {
var index = -1,
i,
node;
for (i = 0; i < nodes.length; i++) {
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) {
var i, descriptor;
for (i = 0; i < props.length; i++) {
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),
i,
key,
value;for (i = 0; i < keys.length; i++) {
key = keys[i];
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 (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 () {
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 _util.DictSet();
_this2.named = new _util.DictSet();
_this2.blocks = [];
_this2.hasEval = false;
return _this2;
}
TemplateBlock.prototype.push = function (statement) {
this.statements.push(statement);
};
TemplateBlock.prototype.toJSON = function () {
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 (statement) {
if (this.inParams) {
if (_wireFormat.Statements.isFlushElement(statement)) {
this.inParams = false;
} else if (_wireFormat.Statements.isArgument(statement)) {
this.arguments.push(statement);
} else if (_wireFormat.Statements.isAttribute(statement)) {
this.attributes.push(statement);
} else if (_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 () {
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 () {
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 _util.Stack();
this.values = [];
this.opcodes = opcodes;
this.template = new Template(symbols, meta);
}
JavaScriptCompiler.process = function (opcodes, symbols, meta) {
var compiler = new JavaScriptCompiler(opcodes, symbols, meta);
return compiler.process();
};
JavaScriptCompiler.prototype.process = function () {
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 (_ref2) {
var program = _ref2[0];
var block = new InlineBlock(program['symbols']);
this.blocks.push(block);
};
JavaScriptCompiler.prototype.endBlock = function () {
var template = this.template,
blocks = this.blocks;
var block = blocks.pop();
template.block.blocks.push(block.toJSON());
};
JavaScriptCompiler.prototype.startProgram = function () {
this.blocks.push(this.template.block);
};
JavaScriptCompiler.prototype.endProgram = function () {};
/// Statements
JavaScriptCompiler.prototype.text = function (content) {
this.push([_wireFormat.Ops.Text, content]);
};
JavaScriptCompiler.prototype.append = function (trusted) {
this.push([_wireFormat.Ops.Append, this.popValue(), trusted]);
};
JavaScriptCompiler.prototype.comment = function (value) {
this.push([_wireFormat.Ops.Comment, value]);
};
JavaScriptCompiler.prototype.modifier = function (name) {
var params = this.popValue();
var hash = this.popValue();
this.push([_wireFormat.Ops.Modifier, name, params, hash]);
};
JavaScriptCompiler.prototype.block = function (name, template, inverse) {
var params = this.popValue();
var hash = this.popValue();
var blocks = this.template.block.blocks;
(0, _util.assert)(typeof template !== 'number' || blocks[template] !== null, 'missing block in the compiler');
(0, _util.assert)(typeof inverse !== 'number' || blocks[inverse] !== null, 'missing block in the compiler');
this.push([_wireFormat.Ops.Block, name, params, hash, blocks[template], blocks[inverse]]);
};
JavaScriptCompiler.prototype.openElement = function (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([_wireFormat.Ops.OpenElement, tag]);
}
};
JavaScriptCompiler.prototype.flushElement = function () {
this.push([_wireFormat.Ops.FlushElement]);
};
JavaScriptCompiler.prototype.closeElement = function (element) {
var tag = element.tag,
_endComponent,
attrs,
args,
block;
if (tag.indexOf('-') !== -1) {
_endComponent = this.endComponent(), attrs = _endComponent[0], args = _endComponent[1], block = _endComponent[2];
this.push([_wireFormat.Ops.Component, tag, attrs, args, block]);
} else {
this.push([_wireFormat.Ops.CloseElement]);
}
};
JavaScriptCompiler.prototype.staticAttr = function (name, namespace) {
var value = this.popValue();
this.push([_wireFormat.Ops.StaticAttr, name, value, namespace]);
};
JavaScriptCompiler.prototype.dynamicAttr = function (name, namespace) {
var value = this.popValue();
this.push([_wireFormat.Ops.DynamicAttr, name, value, namespace]);
};
JavaScriptCompiler.prototype.trustingAttr = function (name, namespace) {
var value = this.popValue();
this.push([_wireFormat.Ops.TrustingAttr, name, value, namespace]);
};
JavaScriptCompiler.prototype.staticArg = function (name) {
var value = this.popValue();
this.push([_wireFormat.Ops.StaticArg, name, value]);
};
JavaScriptCompiler.prototype.dynamicArg = function (name) {
var value = this.popValue();
this.push([_wireFormat.Ops.DynamicArg, name, value]);
};
JavaScriptCompiler.prototype.yield = function (to) {
var params = this.popValue();
this.push([_wireFormat.Ops.Yield, to, params]);
};
JavaScriptCompiler.prototype.debugger = function (evalInfo) {
this.push([_wireFormat.Ops.Debugger, evalInfo]);
this.template.block.hasEval = true;
};
JavaScriptCompiler.prototype.hasBlock = function (name) {
this.pushValue([_wireFormat.Ops.HasBlock, name]);
};
JavaScriptCompiler.prototype.hasBlockParams = function (name) {
this.pushValue([_wireFormat.Ops.HasBlockParams, name]);
};
JavaScriptCompiler.prototype.partial = function (evalInfo) {
var params = this.popValue();
this.push([_wireFormat.Ops.Partial, params[0], evalInfo]);
this.template.block.hasEval = true;
};
/// Expressions
JavaScriptCompiler.prototype.literal = function (value) {
if (value === undefined) {
this.pushValue([_wireFormat.Ops.Undefined]);
} else {
this.pushValue(value);
}
};
JavaScriptCompiler.prototype.unknown = function (name) {
this.pushValue([_wireFormat.Ops.Unknown, name]);
};
JavaScriptCompiler.prototype.get = function (head, path) {
this.pushValue([_wireFormat.Ops.Get, head, path]);
};
JavaScriptCompiler.prototype.maybeLocal = function (path) {
this.pushValue([_wireFormat.Ops.MaybeLocal, path]);
};
JavaScriptCompiler.prototype.concat = function () {
this.pushValue([_wireFormat.Ops.Concat, this.popValue()]);
};
JavaScriptCompiler.prototype.helper = function (name) {
var params = this.popValue();
var hash = this.popValue();
this.pushValue([_wireFormat.Ops.Helper, name, params, hash]);
};
/// Stack Management Opcodes
JavaScriptCompiler.prototype.startComponent = function (element) {
var component = new ComponentBlock(element['symbols']);
this.blocks.push(component);
};
JavaScriptCompiler.prototype.endComponent = function () {
var component = this.blocks.pop();
(0, _util.assert)(component instanceof ComponentBlock, "Compiler bug: endComponent() should end a component");
return component.toJSON();
};
JavaScriptCompiler.prototype.prepareArray = function (size) {
var values = [],
i;
for (i = 0; i < size; i++) {
values.push(this.popValue());
}
this.pushValue(values);
};
JavaScriptCompiler.prototype.prepareObject = function (size) {
(0, _util.assert)(this.values.length >= size, "Expected " + size + " values on the stack, found " + this.values.length);
var keys = new Array(size),
i;
var values = new Array(size);
for (i = 0; i < size; i++) {
keys[i] = this.popValue();
values[i] = this.popValue();
}
this.pushValue([keys, values]);
};
/// Utilities
JavaScriptCompiler.prototype.push = function (args) {
while (args[args.length - 1] === null) {
args.pop();
}
this.currentBlock.push(args);
};
JavaScriptCompiler.prototype.pushValue = function (val) {
this.values.push(val);
};
JavaScriptCompiler.prototype.popValue = function () {
(0, _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) {
var i, descriptor;
for (i = 0; i < props.length; i++) {
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 _util.Stack();
this.opcodes = [];
this.includeMeta = false;
this.options = options || {};
}
TemplateCompiler.compile = function (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 (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 (program) {
this.symbolStack.push(program[0]['symbols']);
this.opcode('startProgram', program, program);
};
TemplateCompiler.prototype.endProgram = function () {
this.symbolStack.pop();
this.opcode('endProgram', null);
};
TemplateCompiler.prototype.startBlock = function (program) {
this.symbolStack.push(program[0]['symbols']);
this.templateId++;
this.opcode('startBlock', program, program);
};
TemplateCompiler.prototype.endBlock = function () {
this.symbolStack.pop();
this.templateIds.push(this.templateId - 1);
this.opcode('endBlock', null);
};
TemplateCompiler.prototype.text = function (_ref2) {
var action = _ref2[0];
this.opcode('text', action, action.chars);
};
TemplateCompiler.prototype.comment = function (_ref3) {
var action = _ref3[0];
this.opcode('comment', action, action.value);
};
TemplateCompiler.prototype.openElement = function (_ref4) {
var action = _ref4[0],
i,
_i;
this.opcode('openElement', action, action);
for (i = 0; i < action.attributes.length; i++) {
this.attribute([action.attributes[i]]);
}
for (_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 (_ref5) {
var action = _ref5[0];
this.symbolStack.pop();
this.opcode('closeElement', null, action);
};
TemplateCompiler.prototype.attribute = function (_ref6) {
var action = _ref6[0],
isTrusting;
var name = action.name,
value = action.value;
var namespace = (0, _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 {
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 (_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 (_ref8) {
var action = _ref8[0],
to,
params;
var path = action.path;
if ((0, _syntax.isLiteral)(path)) {
this.mustacheExpression(action);
this.opcode('append', action, !action.escaped);
} else if (isYield(path)) {
to = assertValidYield(action);
this.yield(to, action);
} else if (isPartial(path)) {
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 (_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 (_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 (expr) {
var path = expr.path,
_path$parts2,
head,
parts;
if ((0, _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)) {
_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 (to, action) {
this.prepareParams(action.params);
this.opcode('yield', action, this.symbols.allocateBlock(to));
};
TemplateCompiler.prototype.debugger = function (_name, action) {
this.opcode('debugger', action, this.symbols.getEvalInfo());
};
TemplateCompiler.prototype.hasBlock = function (name, action) {
this.opcode('hasBlock', action, this.symbols.allocateBlock(name));
};
TemplateCompiler.prototype.hasBlockParams = function (name, action) {
this.opcode('hasBlockParams', action, this.symbols.allocateBlock(name));
};
TemplateCompiler.prototype.partial = function (_params, action) {
this.prepareParams(action.params);
this.opcode('partial', action, this.symbols.getEvalInfo());
};
TemplateCompiler.prototype.builtInHelper = function (expr) {
var path = expr.path,
name,
_name2;
if (isHasBlock(path)) {
name = assertValidHasBlockUsage(expr.path.original, expr);
this.hasBlock(name, expr);
} else if (isHasBlockParams(path)) {
_name2 = assertValidHasBlockUsage(expr.path.original, expr);
this.hasBlockParams(_name2, expr);
}
};
/// Expressions, invoked recursively from prepareParams and prepareHash
TemplateCompiler.prototype.SubExpression = function (expr) {
if (isBuiltInHelper(expr.path)) {
this.builtInHelper(expr);
} else {
this.prepareHelper(expr);
this.opcode('helper', expr, expr.path.parts[0]);
}
};
TemplateCompiler.prototype.PathExpression = function (expr) {
var symbols, _expr$parts, head;
if (expr.data) {
this.arg([expr]);
} else {
symbols = this.symbols;
_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('maybeLocal', expr, expr.parts);
}
}
};
TemplateCompiler.prototype.StringLiteral = function (action) {
this.opcode('literal', null, action.value);
};
TemplateCompiler.prototype.BooleanLiteral = function (action) {
this.opcode('literal', null, action.value);
};
TemplateCompiler.prototype.NumberLiteral = function (action) {
this.opcode('literal', null, action.value);
};
TemplateCompiler.prototype.NullLiteral = function (action) {
this.opcode('literal', null, action.value);
};
TemplateCompiler.prototype.UndefinedLiteral = function (action) {
this.opcode('literal', null, action.value);
};
/// Utilities
TemplateCompiler.prototype.opcode = function (name, action) {
for (_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),
_len,
args,
_key;
if (this.includeMeta && action) {
opcode.push(this.meta(action));
}
this.opcodes.push(opcode);
};
TemplateCompiler.prototype.prepareHelper = function (expr) {
assertIsSimplePath(expr.path, expr.loc, 'helper');
var params = expr.params,
hash = expr.hash;
this.prepareHash(hash);
this.prepareParams(params);
};
TemplateCompiler.prototype.prepareParams = function (params) {
var i, param;
if (!params.length) {
this.opcode('literal', null, null);
return;
}
for (i = params.length - 1; i >= 0; i--) {
param = params[i];
(0, _util.assert)(this[param.type], "Unimplemented " + param.type + " on TemplateCompiler");
this[param.type](param);
}
this.opcode('prepareArray', null, params.length);
};
TemplateCompiler.prototype.prepareHash = function (hash) {
var pairs = hash.pairs,
i,
_pairs$i,
key,
value;
if (!pairs.length) {
this.opcode('literal', null, null);
return;
}
for (i = pairs.length - 1; i >= 0; i--) {
_pairs$i = pairs[i], key = _pairs$i.key, value = _pairs$i.value;
(0, _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 (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 (parts) {
var i, part;
for (i = parts.length - 1; i >= 0; i--) {
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 (_ref11) {
var action = _ref11[0];
this.mustacheExpression(action);
};
TemplateCompiler.prototype.meta = function (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 isLoc