hedera-web/js/vn/compiler.js

151 lines
3.0 KiB
JavaScript

var VnObject = require('./object');
/**
* Base class for compilers.
*/
module.exports = new Class({
Extends: VnObject
,compile() {}
,postCompile() {}
,instantiate() {}
,preLink() {}
,link() {}
,connect() {}
,postLink() {}
,setProperty() {}
,free() {}
,initialize(builder) {
this._builder = builder;
this._interpoler = builder._interpoler;
this.parent();
}
/**
* Checks if the passed attribute name it's an event.
*
* @param {String} attribute The attribute name
* @return {Boolean} %true if it's an event, otherwise %false
*/
,isEvent(attribute) {
return /^on-\w+/.test(attribute);
}
,isIdentifier(value) {
return /^[a-zA-Z_$][\w$]*$/.test(value);
}
/**
* Logs an error parsing the node.
*
* @param {String} error The error message template
* @param {...} varArgs The message template arguments
*/
,showError() {
this._builder.showError.apply(this._builder, arguments);
}
,_getMethod(value) {
// XXX: Compatibility with old methods
return this.isIdentifier(value)
? value
: this.fnExpr(value);
}
,bindMethod(handler, scope, isEvent) {
// XXX: Compatibility with old methods
if (typeof handler === 'string') {
const method = scope.thisArg[handler];
if (!method) {
this.showError(`Function '${handler}' not found`);
return undefined;
}
return method.bind(scope.thisArg);
}
return function($event) {
let handlerScope;
if (isEvent) {
handlerScope = Object.create(scope.$);
Object.assign(handlerScope, {$event});
} else
handlerScope = scope.$;
handler.call(this, handlerScope);
}.bind(scope.thisArg);
}
,matchExpr(value) {
const match = /^{{(.*)}}$/.exec(value);
if (!match) return null;
return this.fnExpr(match[1]);
}
,modelExpr(expr) {
try {
return new Function('$scope', '$value',
`"use strict"; $scope.${expr} = $value;`
);
} catch (err) {
this.showError(`${err.message}:`, expr);
}
}
,exprRegex: /^{{((?:(?!}}).)*)}}$/
,exprRegexMulti: /{{((?:(?!}}).)*)}}/g
,isExpr(expr, isMulti) {
return isMulti
? this.exprRegexMulti.test(expr)
: this.exprRegex.test(expr);
}
,compileExpr(context, property, value, isMulti) {
const exprContext = {
context,
property,
value
};
if (isMulti) {
let i = 0;
const self = this;
exprContext.exprs = [];
exprContext.template = value.replace(this.exprRegexMulti,
function(match, capture) {
exprContext.exprs.push(self.fnExpr(capture));
return `{{${i++}}}`;
});
} else {
const match = this.exprRegex.exec(value);
exprContext.expr = this.fnExpr(match[1]);
}
this._builder._exprContexts.push(exprContext);
}
,fnExpr(expr) {
try {
return new Function('$scope',
`with($scope) { return ${expr}; }`
);
} catch (err) {
this.showError(`${err.message}:`, expr);
}
}
,_translateValue(value) {
var chr = value.charAt(0);
if (chr === '_')
return _(value.substr(1));
else if (chr === '\\' && value.charAt(1) === '_')
return value.substr(1);
return value;
}
});