mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
115 lines
3.3 KiB
JavaScript
115 lines
3.3 KiB
JavaScript
'use strict';
|
|
|
|
var Node = require('./Node');
|
|
var ok = require('assert').ok;
|
|
var splitJavaScriptArgs = require('../util/splitJavaScriptArgs');
|
|
|
|
function removeTrailingUndefineds(args) {
|
|
var i;
|
|
var last = args.length-1;
|
|
|
|
for (i=last; i>=0; i--) {
|
|
if (args[i].type !== 'Literal' || args[i].value !== undefined) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i !== last) {
|
|
args = args.slice(0, i+1);
|
|
}
|
|
|
|
return args;
|
|
}
|
|
|
|
|
|
class InvokeMacro extends Node {
|
|
constructor(def) {
|
|
super('InvokeMacro');
|
|
this.el = def.el;
|
|
this.name = def.name;
|
|
this.args = def.args;
|
|
this.body = this.makeContainer(def.body);
|
|
|
|
if (this.name != null) {
|
|
ok(typeof this.name === 'string', 'Invalid macro name: ' + this.name);
|
|
}
|
|
}
|
|
|
|
generateCode(codegen) {
|
|
var el = this.el;
|
|
var name = this.name;
|
|
var args = this.args;
|
|
var body = this.body;
|
|
|
|
var builder = codegen.builder;
|
|
|
|
var macroDef;
|
|
|
|
if (el) {
|
|
name = el.tagName;
|
|
body = el.body;
|
|
|
|
if (typeof name !== 'string') {
|
|
codegen.context.addError(el, 'Element node with a dynamic tag name cannot be used to invoke a macro', 'ERR_INVOKE_MACRO');
|
|
return;
|
|
}
|
|
|
|
macroDef = codegen.context.getRegisteredMacro(name);
|
|
|
|
if (!macroDef) {
|
|
codegen.context.addError(el, 'Element node does not correspond to a macro', 'ERR_INVOKE_MACRO');
|
|
return;
|
|
}
|
|
|
|
if (el.argument) {
|
|
args = splitJavaScriptArgs(el.argument);
|
|
} else {
|
|
args = new Array(macroDef.params.length);
|
|
for (let i=0; i<args.length; i++) {
|
|
args[i] = builder.literal(undefined);
|
|
}
|
|
|
|
el.forEachAttribute((attr) => {
|
|
var paramName = attr.name;
|
|
var paramIndex = macroDef.getParamIndex(paramName);
|
|
if (paramIndex == null) {
|
|
codegen.context.addError(el, 'The "' + name + '" macro does not have a parameter named "' + paramName + '"', 'ERR_INVOKE_MACRO');
|
|
return;
|
|
}
|
|
|
|
var value = attr.value;
|
|
if (value == null) {
|
|
value = builder.literal(true);
|
|
}
|
|
args[paramIndex] = value;
|
|
});
|
|
}
|
|
} else {
|
|
macroDef = codegen.context.getRegisteredMacro(name);
|
|
if (!macroDef) {
|
|
codegen.addError('Macro not found with name "' + name + '"', 'ERR_INVOKE_MACRO');
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!args) {
|
|
args = [];
|
|
}
|
|
|
|
while (args.length < macroDef.params.length) {
|
|
args.push(builder.literal(undefined));
|
|
}
|
|
|
|
if (body && body.length) {
|
|
args[macroDef.getParamIndex('renderBody')] = builder.renderBodyFunction(body);
|
|
}
|
|
|
|
args[macroDef.getParamIndex('out')] = builder.identifier('out');
|
|
|
|
args = removeTrailingUndefineds(args);
|
|
|
|
return builder.functionCall(builder.identifier(macroDef.functionName), args);
|
|
}
|
|
}
|
|
|
|
module.exports = InvokeMacro; |