127 lines
2.7 KiB
JavaScript
127 lines
2.7 KiB
JavaScript
import { isArray } from '../utils.js';
|
|
import { SourceNode } from '#source-node';
|
|
|
|
function castChunk(chunk, codeGen, loc) {
|
|
if (isArray(chunk)) {
|
|
let ret = [];
|
|
|
|
for (let i = 0, len = chunk.length; i < len; i++) {
|
|
ret.push(codeGen.wrap(chunk[i], loc));
|
|
}
|
|
return ret;
|
|
} else if (typeof chunk === 'boolean' || typeof chunk === 'number') {
|
|
// Handle primitives that the SourceNode will throw up on
|
|
return chunk + '';
|
|
}
|
|
return chunk;
|
|
}
|
|
|
|
function CodeGen(srcFile) {
|
|
this.srcFile = srcFile;
|
|
this.source = [];
|
|
}
|
|
|
|
CodeGen.prototype = {
|
|
isEmpty() {
|
|
return !this.source.length;
|
|
},
|
|
prepend: function (source, loc) {
|
|
this.source.unshift(this.wrap(source, loc));
|
|
},
|
|
push: function (source, loc) {
|
|
this.source.push(this.wrap(source, loc));
|
|
},
|
|
|
|
merge: function () {
|
|
let source = this.empty();
|
|
this.each(function (line) {
|
|
source.add([' ', line, '\n']);
|
|
});
|
|
return source;
|
|
},
|
|
|
|
each: function (iter) {
|
|
for (let i = 0, len = this.source.length; i < len; i++) {
|
|
iter(this.source[i]);
|
|
}
|
|
},
|
|
|
|
empty: function () {
|
|
let loc = this.currentLocation || { start: {} };
|
|
return new SourceNode(loc.start.line, loc.start.column, this.srcFile);
|
|
},
|
|
wrap: function (chunk, loc = this.currentLocation || { start: {} }) {
|
|
if (chunk instanceof SourceNode) {
|
|
return chunk;
|
|
}
|
|
|
|
chunk = castChunk(chunk, this, loc);
|
|
|
|
return new SourceNode(
|
|
loc.start.line,
|
|
loc.start.column,
|
|
this.srcFile,
|
|
chunk
|
|
);
|
|
},
|
|
|
|
functionCall: function (fn, type, params) {
|
|
params = this.generateList(params);
|
|
return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']);
|
|
},
|
|
|
|
quotedString: function (str) {
|
|
return (
|
|
'"' +
|
|
(str + '')
|
|
.replace(/\\/g, '\\\\')
|
|
.replace(/"/g, '\\"')
|
|
.replace(/\n/g, '\\n')
|
|
.replace(/\r/g, '\\r')
|
|
.replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
|
|
.replace(/\u2029/g, '\\u2029') +
|
|
'"'
|
|
);
|
|
},
|
|
|
|
objectLiteral: function (obj) {
|
|
let pairs = [];
|
|
|
|
Object.keys(obj).forEach((key) => {
|
|
let value = castChunk(obj[key], this);
|
|
if (value !== 'undefined') {
|
|
pairs.push([this.quotedString(key), ':', value]);
|
|
}
|
|
});
|
|
|
|
let ret = this.generateList(pairs);
|
|
ret.prepend('{');
|
|
ret.add('}');
|
|
return ret;
|
|
},
|
|
|
|
generateList: function (entries) {
|
|
let ret = this.empty();
|
|
|
|
for (let i = 0, len = entries.length; i < len; i++) {
|
|
if (i) {
|
|
ret.add(',');
|
|
}
|
|
|
|
ret.add(castChunk(entries[i], this));
|
|
}
|
|
|
|
return ret;
|
|
},
|
|
|
|
generateArray: function (entries) {
|
|
let ret = this.generateList(entries);
|
|
ret.prepend('[');
|
|
ret.add(']');
|
|
|
|
return ret;
|
|
},
|
|
};
|
|
|
|
export default CodeGen;
|