khufu
Version:
A template language for incremental-dom or DSL for javascript views
415 lines (358 loc) • 19.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.BUILTINS = undefined;
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
exports.compile_string = compile_string;
exports.join_key = join_key;
exports.compile_body = compile_body;
exports.compile = compile;
var _babelTypes = require("babel-types");
var T = _interopRequireWildcard(_babelTypes);
var _compile_element = require("./compile_element");
var element = _interopRequireWildcard(_compile_element);
var _compile_expression = require("./compile_expression.js");
var expression = _interopRequireWildcard(_compile_expression);
var _compile_expression2 = require("./compile_expression");
var _compile_lval = require("./compile_lval");
var lval = _interopRequireWildcard(_compile_lval);
var _compiler = require("./compiler");
var _babelUtil = require("./babel-util");
var _vars = require("./vars");
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
var DOM_FUNCTIONS = ['elementVoid', 'elementOpen', 'elementClose', 'text', 'item'];
var BUILTINS = exports.BUILTINS = DOM_FUNCTIONS.concat(['SuppressedError']);
function compile_string(item, path, opt, key) {
var _item = _slicedToArray(item, 2),
_expression = _item[0],
value = _item[1];
var expr = (0, _compile_expression2.compile)(value, path, opt);
if (value[0] == 'call') {
(0, _babelUtil.push_to_body)(path, T.expressionStatement(T.callExpression(T.identifier('item'), [expr, key])));
} else {
(0, _babelUtil.push_to_body)(path, T.expressionStatement(T.callExpression(T.identifier('text'), [expr])));
}
}
function join_key(x, y) {
// Optimizes "a" + "b" -> "ab"
if (T.isStringLiteral(x) && T.isStringLiteral(y)) {
return T.stringLiteral(x.value + y.value);
}
// Optimizes "" + "b" -> "b"
if (x.value === '') return y;
// Optimizes "a" + "" -> "a"
if (y.value === '') return x;
// Optimizes (N + "a") + "b" -> N + "ab"
if (T.isBinaryExpression(x) && T.isStringLiteral(x.right) && T.isStringLiteral(y)) {
return T.binaryExpression("+", x.left, T.stringLiteral(x.right.value + y.value));
}
return T.binaryExpression("+", x, y);
}
function compile_body(body, path, opt) {
var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : T.stringLiteral('');
var elements = 0;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = body[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var item = _step.value;
switch (item[0]) {
case 'element':
{
elements += 1;
element.compile(item, path, opt, join_key(key, T.stringLiteral('-' + elements)));
break;
}
case 'expression':
{
elements += 1;
compile_string(item, path, opt, join_key(key, T.stringLiteral('-' + elements)));
break;
}
case 'block_call':
{
elements += 1;
var subkey = join_key(key, T.stringLiteral('-' + elements));
var _item2 = _slicedToArray(item, 3),
_block_call = _item2[0],
_expression2 = _item2[1],
kwargs = _item2[2];
var expr = (0, _compile_expression2.compile)(_expression2, path, opt);
var kwarg_items = [];
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = kwargs[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var _step2$value = _slicedToArray(_step2.value, 2),
name = _step2$value[0],
block = _step2$value[1];
kwarg_items.push(T.objectProperty(T.identifier(name), T.functionExpression(null, [], T.blockStatement([T.returnStatement(T.functionExpression(null, [T.identifier('key')], T.blockStatement([]), false, false))]))));
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
var callpath = (0, _babelUtil.push_to_body)(path, T.expressionStatement(T.callExpression(expr, [subkey, T.objectExpression(kwarg_items)])));
var argpath = callpath.get('expression.arguments')[1].get('properties');
for (var i = 0; i < kwargs.length; ++i) {
compile_body(kwargs[i][1], argpath[i].get('value.body.body')[0].get('argument.body'), opt, T.identifier('key'));
}
break;
}
case 'assign':
{
var _item3 = _slicedToArray(item, 3),
_assign = _item3[0],
target = _item3[1],
value = _item3[2];
var _expr = (0, _compile_expression2.compile)(value, path, opt);
var decl = lval.compile(target, path, opt);
path.scope.push({ id: decl, init: _expr, kind: 'let' });
break;
}
case 'for':
{
elements += 1;
var _item4 = _slicedToArray(item, 5),
_for = _item4[0],
assign = _item4[1],
source = _item4[2],
loopkey = _item4[3],
block = _item4[4];
var stmt = T.forOfStatement(T.variableDeclaration("let", []), (0, _compile_expression2.compile)(source, path, opt), T.blockStatement([]));
var npath = (0, _babelUtil.push_to_body)(path, stmt);
var _decl = lval.compile(assign, npath, opt);
npath.get('left').replaceWith(T.variableDeclaration("let", [T.variableDeclarator(_decl)]));
compile_body(block, npath.get('body'), opt, join_key(join_key(key, T.stringLiteral('-' + elements)), (0, _compile_expression2.compile)(loopkey, npath, opt)));
break;
}
case 'if':
{
elements += 1;
var _item5 = _slicedToArray(item, 4),
_if = _item5[0],
_item5$ = _slicedToArray(_item5[1], 2),
condition = _item5$[0],
_block = _item5$[1],
elifblocks = _item5[2],
elseblk = _item5[3];
var ifblock = void 0;
if (condition[0] == 'let') {
var _decl2 = path.scope.generateUidIdentifier('if_let_cond');
var _expr2 = (0, _compile_expression2.compile)(condition[2], path, opt);
path.scope.push({ id: _decl2, kind: 'let' });
var _cond = T.assignmentExpression('=', _decl2, _expr2);
var con = T.ifStatement(_cond, T.blockStatement([]), null);
ifblock = (0, _babelUtil.push_to_body)(path, con);
var inner_path = ifblock.get('consequent');
var in_decl = lval.compile(condition[1], inner_path, opt);
inner_path.scope.push({ id: in_decl, init: _decl2, kind: 'let' });
} else {
var _con = T.ifStatement((0, _compile_expression2.compile)(condition, path, opt), T.blockStatement([]), null);
ifblock = (0, _babelUtil.push_to_body)(path, _con);
}
compile_body(_block, ifblock.get('consequent'), opt, join_key(key, T.stringLiteral("-" + elements + "if0")));
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = elifblocks.entries()[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var _step3$value = _slicedToArray(_step3.value, 2),
idx = _step3$value[0],
_step3$value$ = _slicedToArray(_step3$value[1], 2),
cond = _step3$value$[0],
blk = _step3$value$[1];
if (cond[0] == 'let') {
var _decl3 = path.scope.generateUidIdentifier('if_let_cond');
var _expr3 = (0, _compile_expression2.compile)(cond[2], path, opt);
path.scope.push({ id: _decl3, kind: 'let' });
var _stmt = T.ifStatement(T.assignmentExpression('=', _decl3, _expr3), T.blockStatement([]), null);
ifblock = ifblock.get('alternate');
ifblock.replaceWith(_stmt);
var _inner_path = ifblock.get('consequent');
var _in_decl = lval.compile(cond[1], _inner_path, opt);
_inner_path.scope.push({ id: _in_decl, init: _decl3, kind: 'let' });
} else {
ifblock = ifblock.get('alternate');
ifblock.replaceWith(T.ifStatement((0, _compile_expression2.compile)(cond, path, opt), T.blockStatement([]), null));
}
compile_body(blk, ifblock.get('consequent'), opt, join_key(key, T.stringLiteral("-" + elements + "if" + (idx + 1))));
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
if (elseblk) {
var elseblock = ifblock.get('alternate');
elseblock.replaceWith(T.blockStatement([]));
compile_body(elseblk, elseblock, opt, join_key(key, T.StringLiteral("-" + elements + "els")));
}
break;
}
case 'catch':
{
elements += 1;
var _item6 = _slicedToArray(item, 5),
_catch = _item6[0],
pattern = _item6[1],
action = _item6[2],
_target = _item6[3],
_block2 = _item6[4];
var name = path.scope.generateUidIdentifier('error');
var _stmt2 = (0, _babelUtil.push_to_body)(path, T.tryStatement(T.blockStatement([]), T.catchClause(name, T.blockStatement([]))));
var handler = _stmt2.get("handler").get("body");
var if_stmt = (0, _babelUtil.push_to_body)(handler, T.ifStatement(T.unaryExpression('!', T.binaryExpression('instanceof', name, T.identifier("SuppressedError")), true), T.blockStatement([]))).get("consequent");
var store = (0, _vars.get_var)(path, _target[1], _target);
(0, _vars.set_var)(if_stmt, 'this', T.identifier('this'));
(0, _vars.set_var)(if_stmt, 'error', name);
(0, _babelUtil.push_to_body)(if_stmt, T.callExpression(T.memberExpression(store, T.identifier('dispatch')), [expression.compile(action, if_stmt, opt)]));
(0, _babelUtil.push_to_body)(if_stmt, T.throwStatement(T.newExpression(T.identifier("SuppressedError"), [name])));
(0, _babelUtil.push_to_body)(handler, T.throwStatement(name));
compile_body(_block2, _stmt2.get("block"), opt, join_key(key, T.StringLiteral("-" + elements + "catch")));
break;
}
default:
throw (0, _compiler.parse_tree_error)("Bad element", item);
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
function compile(view, path, opt) {
var _view2 = _slicedToArray(view, 5),
_view = _view2[0],
name = _view2[1],
params = _view2[2],
kwargs = _view2[3],
body = _view2[4];
if (!path.scope.getData('khufu:dom-imported')) {
path.unshiftContainer("body", T.importDeclaration(BUILTINS.map(function (x) {
return T.importSpecifier(T.identifier(x), T.identifier(x));
}), T.stringLiteral('khufu-runtime')));
path.scope.setData('khufu:dom-imported', true);
}
var kwarg_nodes = [];
if (kwargs.length) {
kwarg_nodes.push(T.objectPattern(kwargs.map(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
_name = _ref2[0],
name = _ref2[1];
return T.objectProperty(T.identifier(name), T.identifier(name));
})));
}
var ident = name.replace(/\./g, '_');
var block_node = T.blockStatement([T.returnStatement(T.functionExpression(T.identifier(ident + '$'), [T.identifier('key')].concat(kwarg_nodes), T.blockStatement([]), false, false))]);
var ext_fun = void 0;
if (name.indexOf('.') >= 0) {
var _name$split = name.split('.'),
_name$split2 = _slicedToArray(_name$split, 2),
varname = _name$split2[0],
key = _name$split2[1];
var binding = (0, _vars.get_var)(path, varname);
if (!binding) {
binding = path.scope.generateUidIdentifier(varname);
(0, _vars.set_var)(path, varname, binding);
path.scope.push({
id: binding,
init: T.objectExpression([]),
kind: 'let'
});
if (varname[0] != '_') {
(0, _babelUtil.push_to_body)(path, T.exportNamedDeclaration(null, [T.exportSpecifier(binding, T.identifier(varname))], null));
}
}
var assign = T.assignmentExpression('=', T.memberExpression(binding, T.identifier(key), false), T.functionExpression(T.identifier(ident), [], block_node, false, false));
var ext_node = T.expressionStatement(assign);
ext_fun = (0, _babelUtil.push_to_body)(path, ext_node).get('expression.right');
} else if (name[0] != '_') {
var func_decl = T.functionDeclaration(T.identifier(ident), [], block_node, false, false);
var _ext_node = T.exportNamedDeclaration(func_decl, []);
ext_fun = (0, _babelUtil.push_to_body)(path, _ext_node).get('declaration');
} else {
var _ext_node2 = T.functionDeclaration(T.identifier(ident), [], block_node, false, false);
ext_fun = (0, _babelUtil.push_to_body)(path, _ext_node2);
}
var child_path = ext_fun.get('body.body')[0].get('argument.body');
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = params[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var param = _step4.value;
ext_fun.node.params.push(lval.compile(param, child_path, opt));
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4.return) {
_iterator4.return();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
var _iteratorNormalCompletion5 = true;
var _didIteratorError5 = false;
var _iteratorError5 = undefined;
try {
for (var _iterator5 = kwargs[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
var _step5$value = _slicedToArray(_step5.value, 2),
_name = _step5$value[0],
kwarg = _step5$value[1];
(0, _vars.set_var)(child_path, kwarg, T.identifier(kwarg));
}
} catch (err) {
_didIteratorError5 = true;
_iteratorError5 = err;
} finally {
try {
if (!_iteratorNormalCompletion5 && _iterator5.return) {
_iterator5.return();
}
} finally {
if (_didIteratorError5) {
throw _iteratorError5;
}
}
}
compile_body(body, child_path, opt, T.identifier('key'));
}