@neo-one/smart-contract-compiler
Version:
NEO•ONE TypeScript smart contract compiler.
146 lines (144 loc) • 7.34 kB
JavaScript
import { tsUtils } from '@neo-one/ts-utils';
import ts from 'typescript';
import { InternalObjectProperty } from '../constants';
import { NodeCompiler } from '../NodeCompiler';
export class ObjectLiteralExpressionCompiler extends NodeCompiler {
constructor() {
super(...arguments);
this.kind = ts.SyntaxKind.ObjectLiteralExpression;
}
visitNode(sb, node, optionsIn) {
const options = sb.pushValueOptions(optionsIn);
sb.emitHelper(node, options, sb.helpers.createObject);
tsUtils.object_.getProperties(node).forEach((prop) => {
if (ts.isGetAccessorDeclaration(prop) && tsUtils.accessor.getSetAccessor(prop) !== undefined) {
return;
}
sb.emitOp(prop, 'DUP');
if (ts.isPropertyAssignment(prop) ||
ts.isMethodDeclaration(prop) ||
ts.isGetAccessorDeclaration(prop) ||
ts.isSetAccessorDeclaration(prop)) {
const propertyName = tsUtils.node.getNameNode(prop);
const visitProp = () => {
if (ts.isPropertyAssignment(prop)) {
sb.visit(tsUtils.initializer.getInitializer(prop), options);
}
else {
sb.emitHelper(prop, options, sb.helpers.createCallArray);
sb.emitHelper(prop, options, sb.helpers.createFunctionObject({
property: InternalObjectProperty.Call,
}));
}
if (ts.isSetAccessorDeclaration(prop)) {
const getAccessor = tsUtils.accessor.getGetAccessor(prop);
if (getAccessor !== undefined) {
sb.emitHelper(getAccessor, options, sb.helpers.createCallArray);
sb.emitHelper(getAccessor, options, sb.helpers.createFunctionObject({
property: InternalObjectProperty.Call,
}));
}
}
};
const setSymbolProperty = () => {
if (ts.isSetAccessorDeclaration(prop) || ts.isGetAccessorDeclaration(prop)) {
sb.emitHelper(prop, options, sb.helpers.setAccessorSymbolObjectProperty({
hasSet: ts.isSetAccessorDeclaration(prop),
hasGet: ts.isGetAccessorDeclaration(prop) || tsUtils.accessor.getGetAccessor(prop) !== undefined,
}));
}
else {
sb.emitHelper(prop, options, sb.helpers.setSymbolObjectProperty);
}
};
const setDataProperty = () => {
if (ts.isSetAccessorDeclaration(prop) || ts.isGetAccessorDeclaration(prop)) {
sb.emitHelper(prop, options, sb.helpers.setAccessorPropertyObjectProperty({
hasSet: ts.isSetAccessorDeclaration(prop),
hasGet: ts.isGetAccessorDeclaration(prop) || tsUtils.accessor.getGetAccessor(prop) !== undefined,
}));
}
else {
sb.emitHelper(prop, options, sb.helpers.setDataPropertyObjectProperty);
}
};
const handlePossibleSymbol = (propertyNameType) => {
const handleSymbol = () => {
sb.emitHelper(prop, options, sb.helpers.unwrapSymbol);
visitProp();
setSymbolProperty();
};
const handleString = () => {
sb.emitHelper(prop, options, sb.helpers.toString({ type: propertyNameType }));
visitProp();
setDataProperty();
};
if (propertyNameType === undefined ||
(!tsUtils.type_.isOnlySymbolish(propertyNameType) && tsUtils.type_.hasSymbolish(propertyNameType))) {
sb.emitHelper(prop, options, sb.helpers.if({
condition: () => {
sb.emitOp(prop, 'DUP');
sb.emitHelper(prop, options, sb.helpers.isSymbol);
},
whenTrue: handleSymbol,
whenFalse: handleString,
}));
}
else if (tsUtils.type_.isOnlySymbolish(propertyNameType)) {
handleSymbol();
}
else {
handleString();
}
};
if (ts.isComputedPropertyName(propertyName)) {
const expr = tsUtils.expression.getExpression(propertyName);
const propertyNameType = sb.context.analysis.getType(expr);
sb.visit(expr, options);
handlePossibleSymbol(propertyNameType);
}
else {
if (ts.isIdentifier(propertyName)) {
sb.emitPushString(propertyName, tsUtils.node.getText(propertyName));
}
else {
sb.emitPushString(propertyName, ts.isStringLiteral(propertyName)
? tsUtils.literal.getLiteralValue(propertyName)
: `${tsUtils.literal.getLiteralValue(propertyName)}`);
}
visitProp();
setDataProperty();
}
}
else if (ts.isShorthandPropertyAssignment(prop)) {
const propertyName = tsUtils.node.getNameNode(prop);
sb.emitPushString(propertyName, tsUtils.node.getText(propertyName));
sb.visit(propertyName, options);
sb.emitHelper(prop, options, sb.helpers.setDataPropertyObjectProperty);
}
else {
const val = sb.scope.addUnique();
const objectVal = sb.scope.addUnique();
sb.scope.set(sb, node, options, objectVal);
sb.visit(tsUtils.expression.getExpression(prop), options);
sb.emitOp(node, 'DUP');
sb.scope.set(sb, node, options, val);
sb.emitHelper(node, options, sb.helpers.getPropertyObjectKeys);
sb.emitHelper(node, options, sb.helpers.arrForEach({
each: () => {
sb.scope.get(sb, node, options, objectVal);
sb.emitOp(node, 'SWAP');
sb.scope.get(sb, node, options, val);
sb.emitOp(node, 'OVER');
sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty);
sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty);
},
}));
}
});
if (!optionsIn.pushValue) {
sb.emitOp(node, 'DROP');
}
}
}
//# sourceMappingURL=ObjectLiteralExpressionCompiler.js.map