1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16//@ts-ignore -- to avoid @types/node missing 17import { EventEmitter } from 'stream'; 18//@ts-ignore -- to avoid @types/node missing 19const etsVm = require('lib/module/ets_interop_js_napi'); 20 21type ClassType = new (...args: {}[]) => {}; 22 23const ETS_MODULE_NAME: string = 'interop_class_extension'; 24const makePrefix = (packageName: string): string => 'L' + packageName.replace('.', '/') + '/'; 25 26const getClass = (name: string, packageName?: string): ClassType => etsVm.getClass(makePrefix(packageName ?? ETS_MODULE_NAME) + name + ';'); 27 28export const DEFAULT_STRING_VALUE = 'Panda'; 29//@ts-ignore -- to avoid @types/node missing 30export const DEFAULT_NUMERIC_VALUE = Math.round(Math.random() * Number!.MAX_SAFE_INTEGER); 31 32type AnyType = {}; 33 34export const helperIsJSInstanceOf = (obj: AnyType, classObj: Function): boolean => { 35 return obj instanceof classObj; 36}; 37 38export class TestUserClass { 39 private _privateValue: string = DEFAULT_STRING_VALUE; 40 protected protectedValue: string = DEFAULT_STRING_VALUE; 41 public publicValue: string = DEFAULT_STRING_VALUE; 42 public readonly readonlyValue: string = DEFAULT_STRING_VALUE; 43 public readonly constructorSetValue: string; 44 45 static isMyInstance(obj: {}): boolean { 46 return obj instanceof TestUserClass; 47 } 48 49 constructor(constructorArg: string) { 50 this.constructorSetValue = constructorArg; 51 } 52} 53 54export const TestNativeClass = EventEmitter; 55 56export const extendUserClass = (): boolean => { 57 const TSTestUserClass = getClass('TSTestUserClass'); 58 class ExtendedEtsUserClass extends TSTestUserClass {} 59 const classInstance = new ExtendedEtsUserClass(); 60 return classInstance instanceof ExtendedEtsUserClass; 61}; 62 63export const extendNativeClass = (): boolean => { 64 const TSTestNativeClass = getClass('ArrayBuffer', 'escompat'); 65 class ExtendedEtsNativeClass extends TSTestNativeClass { 66 constructor(length: 2) { 67 super(length); 68 } 69 } 70 const classInstance = new ExtendedEtsNativeClass(2); 71 return classInstance instanceof TSTestNativeClass; 72}; 73 74export const jsRespectsProtectedModifier = (): boolean => { 75 const TSTestUserClass = getClass('TSTestUserClass'); 76 try { 77 class ExtendedEtsUserClass extends TSTestUserClass { 78 constructor() { 79 super(); 80 //@ts-ignore -- to ignore compile-time check, as TSTestUserClass is only acquired in runtime 81 this.protectedProperty = 'redefinedProtected'; 82 } 83 84 validProtectedGetter(): string { 85 //@ts-ignore -- to ignore compile-time check, as TSTestUserClass is only acquired in runtime 86 return this.protectedProperty; 87 } 88 } 89 const classInstance = new ExtendedEtsUserClass(); 90 return classInstance.validProtectedGetter() === 'redefinedProtected'; 91 } catch (e) { 92 return false; 93 } 94}; 95 96export const jsRespectsStaticModifier = (): boolean => { 97 const TSTestUserClass = getClass('TSTestUserClass'); 98 class ExtendedEtsUserClass extends TSTestUserClass {} 99 //@ts-ignore -- to ignore compile-time check, as TSTestUserClass is only acquired in runtime 100 return ExtendedEtsUserClass?.staticProperty === 'static'; 101}; 102