UNPKG

@neo-one/smart-contract-compiler

Version:

NEO•ONE TypeScript smart contract compiler.

146 lines (144 loc) 7.34 kB
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