diff --git a/CHANGELOG.md b/CHANGELOG.md index 4add549c3..b5ffbda02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ### Enhancements -* [artifact-manager] Issue 220 / mvn archetype:generate for abx project - updated the package.json template for generating abx actions -======= +* [artifact-manager] Issue 220 / mvn archetype:generate for abx project - update the package.json template for generating abx actions +* [typescript/vrotsc] Implement `Object.setPrototypeOf()` function + ### Fixes * [vro-scripting-api] Revert 110 / Mocking for configuration elements is incorrect. @@ -13,8 +14,6 @@ ### Fixes * [vro-types] 251 / Add missing types to AD Plugin - -### Fixes * [artifact-manager] IACCOE-809 : Fixed an issue for importing Aria Pipelines with dependencies on another pipelines for rollback. ## v2.38.0 - 29 Mar 2024 diff --git a/docs/versions/latest/Release.md b/docs/versions/latest/Release.md index 9b01bff70..dc232cc75 100644 --- a/docs/versions/latest/Release.md +++ b/docs/versions/latest/Release.md @@ -17,6 +17,37 @@ [//]: # (Features -> New Functionality) ## Features + +### Implement `Object.setPrototypeOf()` function +Add support for native `Object.setPrototypeOf()` function that can be used to properly setup prototype chain during inheritance. + +E.g. with the following code the prototype chain is setup properly and the log message is `Constructor name: NsxtError`. +```typescript +class NsxtError extends Error { + public readonly cause: string + constructor(message: string, service: string) { + super(`Received error ${message} from NSX-T Service ${service}.`); + Object.setPrototypeOf(this, new.target.prototype) + } +} + +const testError = new NsxtError("Object not found", "SecurityPolicyService"); +System.log(`Constructor name: ${testError.constructor.name}`); +``` + +Without the `Object.setPrototypeOf` the NsxtError is not properly added to the prototype chain and the log message is `Constructor name: Error`. +```typescript +class NsxtError extends Error { + public readonly cause: string + constructor(message: string, service: string) { + super(`Received error ${message} from NSX-T Service ${service}.`); + } +} + +const testError = new NsxtError("Object not found", "SecurityPolicyService"); +System.log(`Constructor name: ${testError.constructor.name}`); +``` + ### Pretty formatted JSON for Custom Forms when storing them together with Custom Form Metadata When Custom Forms are pulled from Aria Automation, they are stored on the file system (the repo) in a form similar to ```json diff --git a/packages/ecmascript/src/Shims.ts b/packages/ecmascript/src/Shims.ts index de7d62e6c..ff76df7de 100644 --- a/packages/ecmascript/src/Shims.ts +++ b/packages/ecmascript/src/Shims.ts @@ -160,6 +160,11 @@ export default class Shims { return Object.keys(target).map(key => target[key]); } + static objectSetPrototypeOf(target, prototype): any { + target.__proto__ = prototype; + return target; + } + static spreadArrays() { var size = 0; for (var i = 0, len = arguments.length; i < len; i++) { diff --git a/typescript/vrotsc/src/compiler/transformer/codeTransformers/shims.ts b/typescript/vrotsc/src/compiler/transformer/codeTransformers/shims.ts index 45a9bab14..2c02568c0 100644 --- a/typescript/vrotsc/src/compiler/transformer/codeTransformers/shims.ts +++ b/typescript/vrotsc/src/compiler/transformer/codeTransformers/shims.ts @@ -1,9 +1,23 @@ +/*- + * #%L + * vrotsc + * %% + * Copyright (C) 2023 - 2024 VMware + * %% + * Build Tools for VMware Aria + * Copyright 2023 VMware, Inc. + * + * This product is licensed to you under the BSD-2 license (the "License"). You may not use this product except in compliance with the BSD-2 License. + * + * This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. + * #L% + */ import * as ts from "typescript"; import { HierarchyFacts, ScriptTransformationContext } from "../../../types"; import { NodeVisitor } from "../../visitor"; -import { getIdentifierTextOrNull } from "../helpers/node"; import { transformSpreadAssignment } from "../codeTransformers//object"; import { transformSpreadElement } from "../codeTransformers/array"; +import { getIdentifierTextOrNull } from "../helpers/node"; import { createDeclarationPrologueStatements } from "./prologueStatements"; // Shims are used to replace the built-in objects with the VROES shims. @@ -76,9 +90,9 @@ export function transformShims(sourceFile: ts.SourceFile, context: ScriptTransfo } } - /** - * Visits the entire source file and replaces variables declarations with the VROES shims. - */ + /** + * Visits the entire source file and replaces variables declarations with the VROES shims. + */ function visitIdentifier(node: ts.Identifier): ts.Identifier { const shimRef = ShimReferences[node.text]; if (shimRef) { @@ -97,9 +111,9 @@ export function transformShims(sourceFile: ts.SourceFile, context: ScriptTransfo return visitor.visitEachChild(node); } - /** - * Will place the prologue statements at the top of the file and replace the built-in objects with the VROES shims. - */ + /** + * Will place the prologue statements at the top of the file and replace the built-in objects with the VROES shims. + */ function visitSourceFile(node: ts.SourceFile): ts.SourceFile { const statements = visitor.visitNodes(node.statements); const prologue = createDeclarationPrologueStatements(context); @@ -114,20 +128,20 @@ export function transformShims(sourceFile: ts.SourceFile, context: ScriptTransfo node.statements)); } - /** - * Visits the entire source file and replaces some built-in methods with the VROES shims. - * - * Example: - * ```ts - * "foo".startsWith("f"); // Transformed to VROES.Shims.stringStartsWith("foo", "f"); - * "foo".endsWith("o"); // Transformed to VROES.Shims.stringEndsWith("foo", "o"); - * "foo".includes("o"); // Transformed to VROES.Shims.stringIncludes("foo", "o"); - * // etc... - * ``` - * - * @param node - The node to visit. - * @returns - The result of visiting the node. - */ + /** + * Visits the entire source file and replaces some built-in methods with the VROES shims. + * + * Example: + * ```ts + * "foo".startsWith("f"); // Transformed to VROES.Shims.stringStartsWith("foo", "f"); + * "foo".endsWith("o"); // Transformed to VROES.Shims.stringEndsWith("foo", "o"); + * "foo".includes("o"); // Transformed to VROES.Shims.stringIncludes("foo", "o"); + * // etc... + * ``` + * + * @param node - The node to visit. + * @returns - The result of visiting the node. + */ function visitCallExpression(node: ts.CallExpression): ts.Expression { const symbol = context.typeChecker.getSymbolAtLocation(node.expression); if (symbol) { @@ -156,6 +170,8 @@ export function transformShims(sourceFile: ts.SourceFile, context: ScriptTransfo return shimStaticCall("arrayOf", node); case "ObjectConstructor.assign": return shimStaticCall("objectAssign", node); + case "ObjectConstructor.setPrototypeOf": + return shimStaticCall("objectSetPrototypeOf", node); } } @@ -164,12 +180,12 @@ export function transformShims(sourceFile: ts.SourceFile, context: ScriptTransfo } - /** - * Helper function to shim instance calls. - * - * if the node is a call expression and the expression is a property access expression, - * then it will be replaced with the VROES shims. - */ + /** + * Helper function to shim instance calls. + * + * if the node is a call expression and the expression is a property access expression, + * then it will be replaced with the VROES shims. + */ function shimInstanceCall(methodName: string, node: ts.CallExpression): ts.CallExpression { if (node.expression.kind !== ts.SyntaxKind.PropertyAccessExpression) { return visitor.visitEachChild(node); @@ -191,9 +207,9 @@ export function transformShims(sourceFile: ts.SourceFile, context: ScriptTransfo visitor.visitNodes(ts.createNodeArray(args, false))); } - /** - * Same as shimInstanceCall but for static calls. - */ + /** + * Same as shimInstanceCall but for static calls. + */ function shimStaticCall(methodName: string, node: ts.CallExpression): ts.CallExpression { context.file.hierarchyFacts |= HierarchyFacts.ContainsPolyfills; @@ -241,9 +257,9 @@ export function transformShimsBefore(sourceFile: ts.SourceFile, context: ScriptT } } - /** - * Visits the entire source file and replaces the spread elements with the VROES shims. - */ + /** + * Visits the entire source file and replaces the spread elements with the VROES shims. + */ function visitSourceFile(node: ts.SourceFile): ts.SourceFile { const statements = visitor.visitNodes(node.statements);