123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449 |
- 'use strict';
-
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
-
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
-
- var parser = require('./parser');
-
- var transformer = require('./transformer');
-
- var nodes = require('./nodes');
-
- var _require = require('./lib'),
- TemplateError = _require.TemplateError;
-
- var _require2 = require('./runtime'),
- Frame = _require2.Frame;
-
- var _require3 = require('./object'),
- Obj = _require3.Obj; // These are all the same for now, but shouldn't be passed straight
- // through
-
-
- var compareOps = {
- '==': '==',
- '===': '===',
- '!=': '!=',
- '!==': '!==',
- '<': '<',
- '>': '>',
- '<=': '<=',
- '>=': '>='
- };
-
- var Compiler = /*#__PURE__*/function (_Obj) {
- _inheritsLoose(Compiler, _Obj);
-
- function Compiler() {
- return _Obj.apply(this, arguments) || this;
- }
-
- var _proto = Compiler.prototype;
-
- _proto.init = function init(templateName, throwOnUndefined) {
- this.templateName = templateName;
- this.codebuf = [];
- this.lastId = 0;
- this.buffer = null;
- this.bufferStack = [];
- this._scopeClosers = '';
- this.inBlock = false;
- this.throwOnUndefined = throwOnUndefined;
- };
-
- _proto.fail = function fail(msg, lineno, colno) {
- if (lineno !== undefined) {
- lineno += 1;
- }
-
- if (colno !== undefined) {
- colno += 1;
- }
-
- throw new TemplateError(msg, lineno, colno);
- };
-
- _proto._pushBuffer = function _pushBuffer() {
- var id = this._tmpid();
-
- this.bufferStack.push(this.buffer);
- this.buffer = id;
-
- this._emit("var " + this.buffer + " = \"\";");
-
- return id;
- };
-
- _proto._popBuffer = function _popBuffer() {
- this.buffer = this.bufferStack.pop();
- };
-
- _proto._emit = function _emit(code) {
- this.codebuf.push(code);
- };
-
- _proto._emitLine = function _emitLine(code) {
- this._emit(code + '\n');
- };
-
- _proto._emitLines = function _emitLines() {
- var _this = this;
-
- for (var _len = arguments.length, lines = new Array(_len), _key = 0; _key < _len; _key++) {
- lines[_key] = arguments[_key];
- }
-
- lines.forEach(function (line) {
- return _this._emitLine(line);
- });
- };
-
- _proto._emitFuncBegin = function _emitFuncBegin(node, name) {
- this.buffer = 'output';
- this._scopeClosers = '';
-
- this._emitLine("function " + name + "(env, context, frame, runtime, cb) {");
-
- this._emitLine("var lineno = " + node.lineno + ";");
-
- this._emitLine("var colno = " + node.colno + ";");
-
- this._emitLine("var " + this.buffer + " = \"\";");
-
- this._emitLine('try {');
- };
-
- _proto._emitFuncEnd = function _emitFuncEnd(noReturn) {
- if (!noReturn) {
- this._emitLine('cb(null, ' + this.buffer + ');');
- }
-
- this._closeScopeLevels();
-
- this._emitLine('} catch (e) {');
-
- this._emitLine(' cb(runtime.handleError(e, lineno, colno));');
-
- this._emitLine('}');
-
- this._emitLine('}');
-
- this.buffer = null;
- };
-
- _proto._addScopeLevel = function _addScopeLevel() {
- this._scopeClosers += '})';
- };
-
- _proto._closeScopeLevels = function _closeScopeLevels() {
- this._emitLine(this._scopeClosers + ';');
-
- this._scopeClosers = '';
- };
-
- _proto._withScopedSyntax = function _withScopedSyntax(func) {
- var _scopeClosers = this._scopeClosers;
- this._scopeClosers = '';
- func.call(this);
-
- this._closeScopeLevels();
-
- this._scopeClosers = _scopeClosers;
- };
-
- _proto._makeCallback = function _makeCallback(res) {
- var err = this._tmpid();
-
- return 'function(' + err + (res ? ',' + res : '') + ') {\n' + 'if(' + err + ') { cb(' + err + '); return; }';
- };
-
- _proto._tmpid = function _tmpid() {
- this.lastId++;
- return 't_' + this.lastId;
- };
-
- _proto._templateName = function _templateName() {
- return this.templateName == null ? 'undefined' : JSON.stringify(this.templateName);
- };
-
- _proto._compileChildren = function _compileChildren(node, frame) {
- var _this2 = this;
-
- node.children.forEach(function (child) {
- _this2.compile(child, frame);
- });
- };
-
- _proto._compileAggregate = function _compileAggregate(node, frame, startChar, endChar) {
- var _this3 = this;
-
- if (startChar) {
- this._emit(startChar);
- }
-
- node.children.forEach(function (child, i) {
- if (i > 0) {
- _this3._emit(',');
- }
-
- _this3.compile(child, frame);
- });
-
- if (endChar) {
- this._emit(endChar);
- }
- };
-
- _proto._compileExpression = function _compileExpression(node, frame) {
- // TODO: I'm not really sure if this type check is worth it or
- // not.
- this.assertType(node, nodes.Literal, nodes.Symbol, nodes.Group, nodes.Array, nodes.Dict, nodes.FunCall, nodes.Caller, nodes.Filter, nodes.LookupVal, nodes.Compare, nodes.InlineIf, nodes.In, nodes.Is, nodes.And, nodes.Or, nodes.Not, nodes.Add, nodes.Concat, nodes.Sub, nodes.Mul, nodes.Div, nodes.FloorDiv, nodes.Mod, nodes.Pow, nodes.Neg, nodes.Pos, nodes.Compare, nodes.NodeList);
- this.compile(node, frame);
- };
-
- _proto.assertType = function assertType(node) {
- for (var _len2 = arguments.length, types = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
- types[_key2 - 1] = arguments[_key2];
- }
-
- if (!types.some(function (t) {
- return node instanceof t;
- })) {
- this.fail("assertType: invalid type: " + node.typename, node.lineno, node.colno);
- }
- };
-
- _proto.compileCallExtension = function compileCallExtension(node, frame, async) {
- var _this4 = this;
-
- var args = node.args;
- var contentArgs = node.contentArgs;
- var autoescape = typeof node.autoescape === 'boolean' ? node.autoescape : true;
-
- if (!async) {
- this._emit(this.buffer + " += runtime.suppressValue(");
- }
-
- this._emit("env.getExtension(\"" + node.extName + "\")[\"" + node.prop + "\"](");
-
- this._emit('context');
-
- if (args || contentArgs) {
- this._emit(',');
- }
-
- if (args) {
- if (!(args instanceof nodes.NodeList)) {
- this.fail('compileCallExtension: arguments must be a NodeList, ' + 'use `parser.parseSignature`');
- }
-
- args.children.forEach(function (arg, i) {
- // Tag arguments are passed normally to the call. Note
- // that keyword arguments are turned into a single js
- // object as the last argument, if they exist.
- _this4._compileExpression(arg, frame);
-
- if (i !== args.children.length - 1 || contentArgs.length) {
- _this4._emit(',');
- }
- });
- }
-
- if (contentArgs.length) {
- contentArgs.forEach(function (arg, i) {
- if (i > 0) {
- _this4._emit(',');
- }
-
- if (arg) {
- _this4._emitLine('function(cb) {');
-
- _this4._emitLine('if(!cb) { cb = function(err) { if(err) { throw err; }}}');
-
- var id = _this4._pushBuffer();
-
- _this4._withScopedSyntax(function () {
- _this4.compile(arg, frame);
-
- _this4._emitLine("cb(null, " + id + ");");
- });
-
- _this4._popBuffer();
-
- _this4._emitLine("return " + id + ";");
-
- _this4._emitLine('}');
- } else {
- _this4._emit('null');
- }
- });
- }
-
- if (async) {
- var res = this._tmpid();
-
- this._emitLine(', ' + this._makeCallback(res));
-
- this._emitLine(this.buffer + " += runtime.suppressValue(" + res + ", " + autoescape + " && env.opts.autoescape);");
-
- this._addScopeLevel();
- } else {
- this._emit(')');
-
- this._emit(", " + autoescape + " && env.opts.autoescape);\n");
- }
- };
-
- _proto.compileCallExtensionAsync = function compileCallExtensionAsync(node, frame) {
- this.compileCallExtension(node, frame, true);
- };
-
- _proto.compileNodeList = function compileNodeList(node, frame) {
- this._compileChildren(node, frame);
- };
-
- _proto.compileLiteral = function compileLiteral(node) {
- if (typeof node.value === 'string') {
- var val = node.value.replace(/\\/g, '\\\\');
- val = val.replace(/"/g, '\\"');
- val = val.replace(/\n/g, '\\n');
- val = val.replace(/\r/g, '\\r');
- val = val.replace(/\t/g, '\\t');
- val = val.replace(/\u2028/g, "\\u2028");
-
- this._emit("\"" + val + "\"");
- } else if (node.value === null) {
- this._emit('null');
- } else {
- this._emit(node.value.toString());
- }
- };
-
- _proto.compileSymbol = function compileSymbol(node, frame) {
- var name = node.value;
- var v = frame.lookup(name);
-
- if (v) {
- this._emit(v);
- } else {
- this._emit('runtime.contextOrFrameLookup(' + 'context, frame, "' + name + '")');
- }
- };
-
- _proto.compileGroup = function compileGroup(node, frame) {
- this._compileAggregate(node, frame, '(', ')');
- };
-
- _proto.compileArray = function compileArray(node, frame) {
- this._compileAggregate(node, frame, '[', ']');
- };
-
- _proto.compileDict = function compileDict(node, frame) {
- this._compileAggregate(node, frame, '{', '}');
- };
-
- _proto.compilePair = function compilePair(node, frame) {
- var key = node.key;
- var val = node.value;
-
- if (key instanceof nodes.Symbol) {
- key = new nodes.Literal(key.lineno, key.colno, key.value);
- } else if (!(key instanceof nodes.Literal && typeof key.value === 'string')) {
- this.fail('compilePair: Dict keys must be strings or names', key.lineno, key.colno);
- }
-
- this.compile(key, frame);
-
- this._emit(': ');
-
- this._compileExpression(val, frame);
- };
-
- _proto.compileInlineIf = function compileInlineIf(node, frame) {
- this._emit('(');
-
- this.compile(node.cond, frame);
-
- this._emit('?');
-
- this.compile(node.body, frame);
-
- this._emit(':');
-
- if (node.else_ !== null) {
- this.compile(node.else_, frame);
- } else {
- this._emit('""');
- }
-
- this._emit(')');
- };
-
- _proto.compileIn = function compileIn(node, frame) {
- this._emit('runtime.inOperator(');
-
- this.compile(node.left, frame);
-
- this._emit(',');
-
- this.compile(node.right, frame);
-
- this._emit(')');
- };
-
- _proto.compileIs = function compileIs(node, frame) {
- // first, we need to try to get the name of the test function, if it's a
- // callable (i.e., has args) and not a symbol.
- var right = node.right.name ? node.right.name.value // otherwise go with the symbol value
- : node.right.value;
-
- this._emit('env.getTest("' + right + '").call(context, ');
-
- this.compile(node.left, frame); // compile the arguments for the callable if they exist
-
- if (node.right.args) {
- this._emit(',');
-
- this.compile(node.right.args, frame);
- }
-
- this._emit(') === true');
- };
-
- _proto._binOpEmitter = function _binOpEmitter(node, frame, str) {
- this.compile(node.left, frame);
-
- this._emit(str);
-
- this.compile(node.right, frame);
- } // ensure concatenation instead of addition
- // by adding empty string in between
- ;
-
- _proto.compileOr = function compileOr(node, frame) {
- return this._binOpEmitter(node, frame, ' || ');
- };
-
- _proto.compileAnd = function compileAnd(node, frame) {
- return this._binOpEmitter(node, frame, ' && ');
- };
-
- _proto.compileAdd = function compileAdd(node, frame) {
- return this._binOpEmitter(node, frame, ' + ');
- };
-
- _proto.compileConcat = function compileConcat(node, frame) {
- return this._binOpEmitter(node, frame, ' + "" + ');
- };
-
- _proto.compileSub = function compileSub(node, frame) {
- return this._binOpEmitter(node, frame, ' - ');
- };
-
- _proto.compileMul = function compileMul(node, frame) {
- return this._binOpEmitter(node, frame, ' * ');
- };
-
- _proto.compileDiv = function compileDiv(node, frame) {
- return this._binOpEmitter(node, frame, ' / ');
- };
-
- _proto.compileMod = function compileMod(node, frame) {
- return this._binOpEmitter(node, frame, ' % ');
- };
-
- _proto.compileNot = function compileNot(node, frame) {
- this._emit('!');
-
- this.compile(node.target, frame);
- };
-
- _proto.compileFloorDiv = function compileFloorDiv(node, frame) {
- this._emit('Math.floor(');
-
- this.compile(node.left, frame);
-
- this._emit(' / ');
-
- this.compile(node.right, frame);
-
- this._emit(')');
- };
-
- _proto.compilePow = function compilePow(node, frame) {
- this._emit('Math.pow(');
-
- this.compile(node.left, frame);
-
- this._emit(', ');
-
- this.compile(node.right, frame);
-
- this._emit(')');
- };
-
- _proto.compileNeg = function compileNeg(node, frame) {
- this._emit('-');
-
- this.compile(node.target, frame);
- };
-
- _proto.compilePos = function compilePos(node, frame) {
- this._emit('+');
-
- this.compile(node.target, frame);
- };
-
- _proto.compileCompare = function compileCompare(node, frame) {
- var _this5 = this;
-
- this.compile(node.expr, frame);
- node.ops.forEach(function (op) {
- _this5._emit(" " + compareOps[op.type] + " ");
-
- _this5.compile(op.expr, frame);
- });
- };
-
- _proto.compileLookupVal = function compileLookupVal(node, frame) {
- this._emit('runtime.memberLookup((');
-
- this._compileExpression(node.target, frame);
-
- this._emit('),');
-
- this._compileExpression(node.val, frame);
-
- this._emit(')');
- };
-
- _proto._getNodeName = function _getNodeName(node) {
- switch (node.typename) {
- case 'Symbol':
- return node.value;
-
- case 'FunCall':
- return 'the return value of (' + this._getNodeName(node.name) + ')';
-
- case 'LookupVal':
- return this._getNodeName(node.target) + '["' + this._getNodeName(node.val) + '"]';
-
- case 'Literal':
- return node.value.toString();
-
- default:
- return '--expression--';
- }
- };
-
- _proto.compileFunCall = function compileFunCall(node, frame) {
- // Keep track of line/col info at runtime by settings
- // variables within an expression. An expression in javascript
- // like (x, y, z) returns the last value, and x and y can be
- // anything
- this._emit('(lineno = ' + node.lineno + ', colno = ' + node.colno + ', ');
-
- this._emit('runtime.callWrap('); // Compile it as normal.
-
-
- this._compileExpression(node.name, frame); // Output the name of what we're calling so we can get friendly errors
- // if the lookup fails.
-
-
- this._emit(', "' + this._getNodeName(node.name).replace(/"/g, '\\"') + '", context, ');
-
- this._compileAggregate(node.args, frame, '[', '])');
-
- this._emit(')');
- };
-
- _proto.compileFilter = function compileFilter(node, frame) {
- var name = node.name;
- this.assertType(name, nodes.Symbol);
-
- this._emit('env.getFilter("' + name.value + '").call(context, ');
-
- this._compileAggregate(node.args, frame);
-
- this._emit(')');
- };
-
- _proto.compileFilterAsync = function compileFilterAsync(node, frame) {
- var name = node.name;
- var symbol = node.symbol.value;
- this.assertType(name, nodes.Symbol);
- frame.set(symbol, symbol);
-
- this._emit('env.getFilter("' + name.value + '").call(context, ');
-
- this._compileAggregate(node.args, frame);
-
- this._emitLine(', ' + this._makeCallback(symbol));
-
- this._addScopeLevel();
- };
-
- _proto.compileKeywordArgs = function compileKeywordArgs(node, frame) {
- this._emit('runtime.makeKeywordArgs(');
-
- this.compileDict(node, frame);
-
- this._emit(')');
- };
-
- _proto.compileSet = function compileSet(node, frame) {
- var _this6 = this;
-
- var ids = []; // Lookup the variable names for each identifier and create
- // new ones if necessary
-
- node.targets.forEach(function (target) {
- var name = target.value;
- var id = frame.lookup(name);
-
- if (id === null || id === undefined) {
- id = _this6._tmpid(); // Note: This relies on js allowing scope across
- // blocks, in case this is created inside an `if`
-
- _this6._emitLine('var ' + id + ';');
- }
-
- ids.push(id);
- });
-
- if (node.value) {
- this._emit(ids.join(' = ') + ' = ');
-
- this._compileExpression(node.value, frame);
-
- this._emitLine(';');
- } else {
- this._emit(ids.join(' = ') + ' = ');
-
- this.compile(node.body, frame);
-
- this._emitLine(';');
- }
-
- node.targets.forEach(function (target, i) {
- var id = ids[i];
- var name = target.value; // We are running this for every var, but it's very
- // uncommon to assign to multiple vars anyway
-
- _this6._emitLine("frame.set(\"" + name + "\", " + id + ", true);");
-
- _this6._emitLine('if(frame.topLevel) {');
-
- _this6._emitLine("context.setVariable(\"" + name + "\", " + id + ");");
-
- _this6._emitLine('}');
-
- if (name.charAt(0) !== '_') {
- _this6._emitLine('if(frame.topLevel) {');
-
- _this6._emitLine("context.addExport(\"" + name + "\", " + id + ");");
-
- _this6._emitLine('}');
- }
- });
- };
-
- _proto.compileSwitch = function compileSwitch(node, frame) {
- var _this7 = this;
-
- this._emit('switch (');
-
- this.compile(node.expr, frame);
-
- this._emit(') {');
-
- node.cases.forEach(function (c, i) {
- _this7._emit('case ');
-
- _this7.compile(c.cond, frame);
-
- _this7._emit(': ');
-
- _this7.compile(c.body, frame); // preserve fall-throughs
-
-
- if (c.body.children.length) {
- _this7._emitLine('break;');
- }
- });
-
- if (node.default) {
- this._emit('default:');
-
- this.compile(node.default, frame);
- }
-
- this._emit('}');
- };
-
- _proto.compileIf = function compileIf(node, frame, async) {
- var _this8 = this;
-
- this._emit('if(');
-
- this._compileExpression(node.cond, frame);
-
- this._emitLine(') {');
-
- this._withScopedSyntax(function () {
- _this8.compile(node.body, frame);
-
- if (async) {
- _this8._emit('cb()');
- }
- });
-
- if (node.else_) {
- this._emitLine('}\nelse {');
-
- this._withScopedSyntax(function () {
- _this8.compile(node.else_, frame);
-
- if (async) {
- _this8._emit('cb()');
- }
- });
- } else if (async) {
- this._emitLine('}\nelse {');
-
- this._emit('cb()');
- }
-
- this._emitLine('}');
- };
-
- _proto.compileIfAsync = function compileIfAsync(node, frame) {
- this._emit('(function(cb) {');
-
- this.compileIf(node, frame, true);
-
- this._emit('})(' + this._makeCallback());
-
- this._addScopeLevel();
- };
-
- _proto._emitLoopBindings = function _emitLoopBindings(node, arr, i, len) {
- var _this9 = this;
-
- var bindings = [{
- name: 'index',
- val: i + " + 1"
- }, {
- name: 'index0',
- val: i
- }, {
- name: 'revindex',
- val: len + " - " + i
- }, {
- name: 'revindex0',
- val: len + " - " + i + " - 1"
- }, {
- name: 'first',
- val: i + " === 0"
- }, {
- name: 'last',
- val: i + " === " + len + " - 1"
- }, {
- name: 'length',
- val: len
- }];
- bindings.forEach(function (b) {
- _this9._emitLine("frame.set(\"loop." + b.name + "\", " + b.val + ");");
- });
- };
-
- _proto.compileFor = function compileFor(node, frame) {
- var _this10 = this;
-
- // Some of this code is ugly, but it keeps the generated code
- // as fast as possible. ForAsync also shares some of this, but
- // not much.
- var i = this._tmpid();
-
- var len = this._tmpid();
-
- var arr = this._tmpid();
-
- frame = frame.push();
-
- this._emitLine('frame = frame.push();');
-
- this._emit("var " + arr + " = ");
-
- this._compileExpression(node.arr, frame);
-
- this._emitLine(';');
-
- this._emit("if(" + arr + ") {");
-
- this._emitLine(arr + ' = runtime.fromIterator(' + arr + ');'); // If multiple names are passed, we need to bind them
- // appropriately
-
-
- if (node.name instanceof nodes.Array) {
- this._emitLine("var " + i + ";"); // The object could be an arroy or object. Note that the
- // body of the loop is duplicated for each condition, but
- // we are optimizing for speed over size.
-
-
- this._emitLine("if(runtime.isArray(" + arr + ")) {");
-
- this._emitLine("var " + len + " = " + arr + ".length;");
-
- this._emitLine("for(" + i + "=0; " + i + " < " + arr + ".length; " + i + "++) {"); // Bind each declared var
-
-
- node.name.children.forEach(function (child, u) {
- var tid = _this10._tmpid();
-
- _this10._emitLine("var " + tid + " = " + arr + "[" + i + "][" + u + "];");
-
- _this10._emitLine("frame.set(\"" + child + "\", " + arr + "[" + i + "][" + u + "]);");
-
- frame.set(node.name.children[u].value, tid);
- });
-
- this._emitLoopBindings(node, arr, i, len);
-
- this._withScopedSyntax(function () {
- _this10.compile(node.body, frame);
- });
-
- this._emitLine('}');
-
- this._emitLine('} else {'); // Iterate over the key/values of an object
-
-
- var _node$name$children = node.name.children,
- key = _node$name$children[0],
- val = _node$name$children[1];
-
- var k = this._tmpid();
-
- var v = this._tmpid();
-
- frame.set(key.value, k);
- frame.set(val.value, v);
-
- this._emitLine(i + " = -1;");
-
- this._emitLine("var " + len + " = runtime.keys(" + arr + ").length;");
-
- this._emitLine("for(var " + k + " in " + arr + ") {");
-
- this._emitLine(i + "++;");
-
- this._emitLine("var " + v + " = " + arr + "[" + k + "];");
-
- this._emitLine("frame.set(\"" + key.value + "\", " + k + ");");
-
- this._emitLine("frame.set(\"" + val.value + "\", " + v + ");");
-
- this._emitLoopBindings(node, arr, i, len);
-
- this._withScopedSyntax(function () {
- _this10.compile(node.body, frame);
- });
-
- this._emitLine('}');
-
- this._emitLine('}');
- } else {
- // Generate a typical array iteration
- var _v = this._tmpid();
-
- frame.set(node.name.value, _v);
-
- this._emitLine("var " + len + " = " + arr + ".length;");
-
- this._emitLine("for(var " + i + "=0; " + i + " < " + arr + ".length; " + i + "++) {");
-
- this._emitLine("var " + _v + " = " + arr + "[" + i + "];");
-
- this._emitLine("frame.set(\"" + node.name.value + "\", " + _v + ");");
-
- this._emitLoopBindings(node, arr, i, len);
-
- this._withScopedSyntax(function () {
- _this10.compile(node.body, frame);
- });
-
- this._emitLine('}');
- }
-
- this._emitLine('}');
-
- if (node.else_) {
- this._emitLine('if (!' + len + ') {');
-
- this.compile(node.else_, frame);
-
- this._emitLine('}');
- }
-
- this._emitLine('frame = frame.pop();');
- };
-
- _proto._compileAsyncLoop = function _compileAsyncLoop(node, frame, parallel) {
- var _this11 = this;
-
- // This shares some code with the For tag, but not enough to
- // worry about. This iterates across an object asynchronously,
- // but not in parallel.
- var i = this._tmpid();
-
- var len = this._tmpid();
-
- var arr = this._tmpid();
-
- var asyncMethod = parallel ? 'asyncAll' : 'asyncEach';
- frame = frame.push();
-
- this._emitLine('frame = frame.push();');
-
- this._emit('var ' + arr + ' = runtime.fromIterator(');
-
- this._compileExpression(node.arr, frame);
-
- this._emitLine(');');
-
- if (node.name instanceof nodes.Array) {
- var arrayLen = node.name.children.length;
-
- this._emit("runtime." + asyncMethod + "(" + arr + ", " + arrayLen + ", function(");
-
- node.name.children.forEach(function (name) {
- _this11._emit(name.value + ",");
- });
-
- this._emit(i + ',' + len + ',next) {');
-
- node.name.children.forEach(function (name) {
- var id = name.value;
- frame.set(id, id);
-
- _this11._emitLine("frame.set(\"" + id + "\", " + id + ");");
- });
- } else {
- var id = node.name.value;
-
- this._emitLine("runtime." + asyncMethod + "(" + arr + ", 1, function(" + id + ", " + i + ", " + len + ",next) {");
-
- this._emitLine('frame.set("' + id + '", ' + id + ');');
-
- frame.set(id, id);
- }
-
- this._emitLoopBindings(node, arr, i, len);
-
- this._withScopedSyntax(function () {
- var buf;
-
- if (parallel) {
- buf = _this11._pushBuffer();
- }
-
- _this11.compile(node.body, frame);
-
- _this11._emitLine('next(' + i + (buf ? ',' + buf : '') + ');');
-
- if (parallel) {
- _this11._popBuffer();
- }
- });
-
- var output = this._tmpid();
-
- this._emitLine('}, ' + this._makeCallback(output));
-
- this._addScopeLevel();
-
- if (parallel) {
- this._emitLine(this.buffer + ' += ' + output + ';');
- }
-
- if (node.else_) {
- this._emitLine('if (!' + arr + '.length) {');
-
- this.compile(node.else_, frame);
-
- this._emitLine('}');
- }
-
- this._emitLine('frame = frame.pop();');
- };
-
- _proto.compileAsyncEach = function compileAsyncEach(node, frame) {
- this._compileAsyncLoop(node, frame);
- };
-
- _proto.compileAsyncAll = function compileAsyncAll(node, frame) {
- this._compileAsyncLoop(node, frame, true);
- };
-
- _proto._compileMacro = function _compileMacro(node, frame) {
- var _this12 = this;
-
- var args = [];
- var kwargs = null;
-
- var funcId = 'macro_' + this._tmpid();
-
- var keepFrame = frame !== undefined; // Type check the definition of the args
-
- node.args.children.forEach(function (arg, i) {
- if (i === node.args.children.length - 1 && arg instanceof nodes.Dict) {
- kwargs = arg;
- } else {
- _this12.assertType(arg, nodes.Symbol);
-
- args.push(arg);
- }
- });
- var realNames = [].concat(args.map(function (n) {
- return "l_" + n.value;
- }), ['kwargs']); // Quoted argument names
-
- var argNames = args.map(function (n) {
- return "\"" + n.value + "\"";
- });
- var kwargNames = (kwargs && kwargs.children || []).map(function (n) {
- return "\"" + n.key.value + "\"";
- }); // We pass a function to makeMacro which destructures the
- // arguments so support setting positional args with keywords
- // args and passing keyword args as positional args
- // (essentially default values). See runtime.js.
-
- var currFrame;
-
- if (keepFrame) {
- currFrame = frame.push(true);
- } else {
- currFrame = new Frame();
- }
-
- this._emitLines("var " + funcId + " = runtime.makeMacro(", "[" + argNames.join(', ') + "], ", "[" + kwargNames.join(', ') + "], ", "function (" + realNames.join(', ') + ") {", 'var callerFrame = frame;', 'frame = ' + (keepFrame ? 'frame.push(true);' : 'new runtime.Frame();'), 'kwargs = kwargs || {};', 'if (Object.prototype.hasOwnProperty.call(kwargs, "caller")) {', 'frame.set("caller", kwargs.caller); }'); // Expose the arguments to the template. Don't need to use
- // random names because the function
- // will create a new run-time scope for us
-
-
- args.forEach(function (arg) {
- _this12._emitLine("frame.set(\"" + arg.value + "\", l_" + arg.value + ");");
-
- currFrame.set(arg.value, "l_" + arg.value);
- }); // Expose the keyword arguments
-
- if (kwargs) {
- kwargs.children.forEach(function (pair) {
- var name = pair.key.value;
-
- _this12._emit("frame.set(\"" + name + "\", ");
-
- _this12._emit("Object.prototype.hasOwnProperty.call(kwargs, \"" + name + "\")");
-
- _this12._emit(" ? kwargs[\"" + name + "\"] : ");
-
- _this12._compileExpression(pair.value, currFrame);
-
- _this12._emit(');');
- });
- }
-
- var bufferId = this._pushBuffer();
-
- this._withScopedSyntax(function () {
- _this12.compile(node.body, currFrame);
- });
-
- this._emitLine('frame = ' + (keepFrame ? 'frame.pop();' : 'callerFrame;'));
-
- this._emitLine("return new runtime.SafeString(" + bufferId + ");");
-
- this._emitLine('});');
-
- this._popBuffer();
-
- return funcId;
- };
-
- _proto.compileMacro = function compileMacro(node, frame) {
- var funcId = this._compileMacro(node); // Expose the macro to the templates
-
-
- var name = node.name.value;
- frame.set(name, funcId);
-
- if (frame.parent) {
- this._emitLine("frame.set(\"" + name + "\", " + funcId + ");");
- } else {
- if (node.name.value.charAt(0) !== '_') {
- this._emitLine("context.addExport(\"" + name + "\");");
- }
-
- this._emitLine("context.setVariable(\"" + name + "\", " + funcId + ");");
- }
- };
-
- _proto.compileCaller = function compileCaller(node, frame) {
- // basically an anonymous "macro expression"
- this._emit('(function (){');
-
- var funcId = this._compileMacro(node, frame);
-
- this._emit("return " + funcId + ";})()");
- };
-
- _proto._compileGetTemplate = function _compileGetTemplate(node, frame, eagerCompile, ignoreMissing) {
- var parentTemplateId = this._tmpid();
-
- var parentName = this._templateName();
-
- var cb = this._makeCallback(parentTemplateId);
-
- var eagerCompileArg = eagerCompile ? 'true' : 'false';
- var ignoreMissingArg = ignoreMissing ? 'true' : 'false';
-
- this._emit('env.getTemplate(');
-
- this._compileExpression(node.template, frame);
-
- this._emitLine(", " + eagerCompileArg + ", " + parentName + ", " + ignoreMissingArg + ", " + cb);
-
- return parentTemplateId;
- };
-
- _proto.compileImport = function compileImport(node, frame) {
- var target = node.target.value;
-
- var id = this._compileGetTemplate(node, frame, false, false);
-
- this._addScopeLevel();
-
- this._emitLine(id + '.getExported(' + (node.withContext ? 'context.getVariables(), frame, ' : '') + this._makeCallback(id));
-
- this._addScopeLevel();
-
- frame.set(target, id);
-
- if (frame.parent) {
- this._emitLine("frame.set(\"" + target + "\", " + id + ");");
- } else {
- this._emitLine("context.setVariable(\"" + target + "\", " + id + ");");
- }
- };
-
- _proto.compileFromImport = function compileFromImport(node, frame) {
- var _this13 = this;
-
- var importedId = this._compileGetTemplate(node, frame, false, false);
-
- this._addScopeLevel();
-
- this._emitLine(importedId + '.getExported(' + (node.withContext ? 'context.getVariables(), frame, ' : '') + this._makeCallback(importedId));
-
- this._addScopeLevel();
-
- node.names.children.forEach(function (nameNode) {
- var name;
- var alias;
-
- var id = _this13._tmpid();
-
- if (nameNode instanceof nodes.Pair) {
- name = nameNode.key.value;
- alias = nameNode.value.value;
- } else {
- name = nameNode.value;
- alias = name;
- }
-
- _this13._emitLine("if(Object.prototype.hasOwnProperty.call(" + importedId + ", \"" + name + "\")) {");
-
- _this13._emitLine("var " + id + " = " + importedId + "." + name + ";");
-
- _this13._emitLine('} else {');
-
- _this13._emitLine("cb(new Error(\"cannot import '" + name + "'\")); return;");
-
- _this13._emitLine('}');
-
- frame.set(alias, id);
-
- if (frame.parent) {
- _this13._emitLine("frame.set(\"" + alias + "\", " + id + ");");
- } else {
- _this13._emitLine("context.setVariable(\"" + alias + "\", " + id + ");");
- }
- });
- };
-
- _proto.compileBlock = function compileBlock(node) {
- var id = this._tmpid(); // If we are executing outside a block (creating a top-level
- // block), we really don't want to execute its code because it
- // will execute twice: once when the child template runs and
- // again when the parent template runs. Note that blocks
- // within blocks will *always* execute immediately *and*
- // wherever else they are invoked (like used in a parent
- // template). This may have behavioral differences from jinja
- // because blocks can have side effects, but it seems like a
- // waste of performance to always execute huge top-level
- // blocks twice
-
-
- if (!this.inBlock) {
- this._emit('(parentTemplate ? function(e, c, f, r, cb) { cb(""); } : ');
- }
-
- this._emit("context.getBlock(\"" + node.name.value + "\")");
-
- if (!this.inBlock) {
- this._emit(')');
- }
-
- this._emitLine('(env, context, frame, runtime, ' + this._makeCallback(id));
-
- this._emitLine(this.buffer + " += " + id + ";");
-
- this._addScopeLevel();
- };
-
- _proto.compileSuper = function compileSuper(node, frame) {
- var name = node.blockName.value;
- var id = node.symbol.value;
-
- var cb = this._makeCallback(id);
-
- this._emitLine("context.getSuper(env, \"" + name + "\", b_" + name + ", frame, runtime, " + cb);
-
- this._emitLine(id + " = runtime.markSafe(" + id + ");");
-
- this._addScopeLevel();
-
- frame.set(id, id);
- };
-
- _proto.compileExtends = function compileExtends(node, frame) {
- var k = this._tmpid();
-
- var parentTemplateId = this._compileGetTemplate(node, frame, true, false); // extends is a dynamic tag and can occur within a block like
- // `if`, so if this happens we need to capture the parent
- // template in the top-level scope
-
-
- this._emitLine("parentTemplate = " + parentTemplateId);
-
- this._emitLine("for(var " + k + " in parentTemplate.blocks) {");
-
- this._emitLine("context.addBlock(" + k + ", parentTemplate.blocks[" + k + "]);");
-
- this._emitLine('}');
-
- this._addScopeLevel();
- };
-
- _proto.compileInclude = function compileInclude(node, frame) {
- this._emitLine('var tasks = [];');
-
- this._emitLine('tasks.push(');
-
- this._emitLine('function(callback) {');
-
- var id = this._compileGetTemplate(node, frame, false, node.ignoreMissing);
-
- this._emitLine("callback(null," + id + ");});");
-
- this._emitLine('});');
-
- var id2 = this._tmpid();
-
- this._emitLine('tasks.push(');
-
- this._emitLine('function(template, callback){');
-
- this._emitLine('template.render(context.getVariables(), frame, ' + this._makeCallback(id2));
-
- this._emitLine('callback(null,' + id2 + ');});');
-
- this._emitLine('});');
-
- this._emitLine('tasks.push(');
-
- this._emitLine('function(result, callback){');
-
- this._emitLine(this.buffer + " += result;");
-
- this._emitLine('callback(null);');
-
- this._emitLine('});');
-
- this._emitLine('env.waterfall(tasks, function(){');
-
- this._addScopeLevel();
- };
-
- _proto.compileTemplateData = function compileTemplateData(node, frame) {
- this.compileLiteral(node, frame);
- };
-
- _proto.compileCapture = function compileCapture(node, frame) {
- var _this14 = this;
-
- // we need to temporarily override the current buffer id as 'output'
- // so the set block writes to the capture output instead of the buffer
- var buffer = this.buffer;
- this.buffer = 'output';
-
- this._emitLine('(function() {');
-
- this._emitLine('var output = "";');
-
- this._withScopedSyntax(function () {
- _this14.compile(node.body, frame);
- });
-
- this._emitLine('return output;');
-
- this._emitLine('})()'); // and of course, revert back to the old buffer id
-
-
- this.buffer = buffer;
- };
-
- _proto.compileOutput = function compileOutput(node, frame) {
- var _this15 = this;
-
- var children = node.children;
- children.forEach(function (child) {
- // TemplateData is a special case because it is never
- // autoescaped, so simply output it for optimization
- if (child instanceof nodes.TemplateData) {
- if (child.value) {
- _this15._emit(_this15.buffer + " += ");
-
- _this15.compileLiteral(child, frame);
-
- _this15._emitLine(';');
- }
- } else {
- _this15._emit(_this15.buffer + " += runtime.suppressValue(");
-
- if (_this15.throwOnUndefined) {
- _this15._emit('runtime.ensureDefined(');
- }
-
- _this15.compile(child, frame);
-
- if (_this15.throwOnUndefined) {
- _this15._emit("," + node.lineno + "," + node.colno + ")");
- }
-
- _this15._emit(', env.opts.autoescape);\n');
- }
- });
- };
-
- _proto.compileRoot = function compileRoot(node, frame) {
- var _this16 = this;
-
- if (frame) {
- this.fail('compileRoot: root node can\'t have frame');
- }
-
- frame = new Frame();
-
- this._emitFuncBegin(node, 'root');
-
- this._emitLine('var parentTemplate = null;');
-
- this._compileChildren(node, frame);
-
- this._emitLine('if(parentTemplate) {');
-
- this._emitLine('parentTemplate.rootRenderFunc(env, context, frame, runtime, cb);');
-
- this._emitLine('} else {');
-
- this._emitLine("cb(null, " + this.buffer + ");");
-
- this._emitLine('}');
-
- this._emitFuncEnd(true);
-
- this.inBlock = true;
- var blockNames = [];
- var blocks = node.findAll(nodes.Block);
- blocks.forEach(function (block, i) {
- var name = block.name.value;
-
- if (blockNames.indexOf(name) !== -1) {
- throw new Error("Block \"" + name + "\" defined more than once.");
- }
-
- blockNames.push(name);
-
- _this16._emitFuncBegin(block, "b_" + name);
-
- var tmpFrame = new Frame();
-
- _this16._emitLine('var frame = frame.push(true);');
-
- _this16.compile(block.body, tmpFrame);
-
- _this16._emitFuncEnd();
- });
-
- this._emitLine('return {');
-
- blocks.forEach(function (block, i) {
- var blockName = "b_" + block.name.value;
-
- _this16._emitLine(blockName + ": " + blockName + ",");
- });
-
- this._emitLine('root: root\n};');
- };
-
- _proto.compile = function compile(node, frame) {
- var _compile = this['compile' + node.typename];
-
- if (_compile) {
- _compile.call(this, node, frame);
- } else {
- this.fail("compile: Cannot compile node: " + node.typename, node.lineno, node.colno);
- }
- };
-
- _proto.getCode = function getCode() {
- return this.codebuf.join('');
- };
-
- return Compiler;
- }(Obj);
-
- module.exports = {
- compile: function compile(src, asyncFilters, extensions, name, opts) {
- if (opts === void 0) {
- opts = {};
- }
-
- var c = new Compiler(name, opts.throwOnUndefined); // Run the extension preprocessors against the source.
-
- var preprocessors = (extensions || []).map(function (ext) {
- return ext.preprocess;
- }).filter(function (f) {
- return !!f;
- });
- var processedSrc = preprocessors.reduce(function (s, processor) {
- return processor(s);
- }, src);
- c.compile(transformer.transform(parser.parse(processedSrc, extensions, opts), asyncFilters, name));
- return c.getCode();
- },
- Compiler: Compiler
- };
|