1/* 2 * Copyright (c) 2022 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 */ 15interface ArkPrivate { 16 Stack: number; 17 Load(key: number): Object; 18} 19let flag: boolean = false; 20let fastStack: Object = undefined; 21let arkPritvate: ArkPrivate = globalThis.ArkPrivate || undefined; 22if (arkPritvate !== undefined) { 23 fastStack = arkPritvate.Load(arkPritvate.Stack); 24} else { 25 flag = true; 26} 27declare function requireNapi(s: string): any; 28if (flag || fastStack === undefined) { 29 const { errorUtil } = requireNapi('util.struct'); 30 class HandlerStack<T> { 31 private isOutBounds(obj: Stack<T>, prop: string): void { 32 let index: number = Number.parseInt(prop); 33 if (Number.isInteger(index)) { 34 errorUtil.checkRangeError('index', index, 0, obj.length - 1); 35 } 36 } 37 get(obj: Stack<T>, prop: string): T { 38 if (typeof prop === 'symbol') { 39 return obj[prop]; 40 } 41 this.isOutBounds(obj, prop); 42 return obj[prop]; 43 } 44 set(obj: Stack<T>, prop: any, value: T): boolean { 45 if (prop === 'elementNum' || prop === 'capacity') { 46 obj[prop] = value; 47 return true; 48 } 49 this.isOutBounds(obj, prop); 50 let index: number = Number.parseInt(prop); 51 if (index >= 0 && index < obj.length && Number.isInteger(index)) { 52 obj[index] = value; 53 return true; 54 } 55 return false; 56 } 57 ownKeys(obj: Stack<T>): Array<string> { 58 let keys: string[] = []; 59 let length: number = obj.length; 60 for (let i: number = 0; i < length; i++) { 61 keys.push(i.toString()); 62 } 63 return keys; 64 } 65 defineProperty(): boolean { 66 return true; 67 } 68 getOwnPropertyDescriptor(obj: Stack<T>, prop: string): Object { 69 this.isOutBounds(obj, prop); 70 let index: number = Number.parseInt(prop); 71 if (index >= 0 && index < obj.length && Number.isInteger(index)) { 72 return Object.getOwnPropertyDescriptor(obj, prop); 73 } 74 return Object; 75 } 76 setPrototypeOf(): T { 77 throw new Error(`Can't setPrototype on Stack Object`); 78 } 79 } 80 interface IterableIterator<T> { 81 next: () => { 82 value: T; 83 done: boolean; 84 }; 85 } 86 class Stack<T> { 87 private elementNum: number = 0; 88 private capacity: number = 10; // 10 : means number 89 constructor() { 90 errorUtil.checkNewTargetIsNullError('Stack', !new.target); 91 return new Proxy(this, new HandlerStack()); 92 } 93 get length(): number { 94 return this.elementNum; 95 } 96 push(item: T): T { 97 errorUtil.checkBindError('push', Stack, this); 98 if (this.isFull()) { 99 this.increaseCapacity(); 100 } 101 this[this.elementNum++] = item; 102 return item; 103 } 104 pop(): T { 105 errorUtil.checkBindError('pop', Stack, this); 106 if (this.isEmpty()) { 107 return undefined; 108 } 109 let result: T = undefined; 110 result = this[this.length - 1]; 111 this.elementNum--; 112 return result; 113 } 114 peek(): T { 115 errorUtil.checkBindError('peek', Stack, this); 116 if (this.isEmpty()) { 117 return undefined; 118 } 119 return this[this.length - 1]; 120 } 121 locate(element: T): number { 122 errorUtil.checkBindError('locate', Stack, this); 123 for (let i: number = 0; i < this.length; i++) { 124 if (this[i] === element) { 125 return i; 126 } 127 } 128 return -1; 129 } 130 isEmpty(): boolean { 131 errorUtil.checkBindError('isEmpty', Stack, this); 132 return this.elementNum === 0; 133 } 134 forEach(callbackfn: (value: T, index?: number, stack?: Stack<T>) => void, 135 thisArg?: Object): void { 136 errorUtil.checkBindError('forEach', Stack, this); 137 errorUtil.checkTypeError('callbackfn', 'callable', callbackfn); 138 for (let i: number = 0; i < this.length; i++) { 139 callbackfn.call(thisArg, this[i], i, this); 140 } 141 } 142 private isFull(): boolean { 143 return this.elementNum === this.capacity; 144 } 145 private increaseCapacity(): void { 146 this.capacity = 1.5 * this.capacity; // 1.5 : means number 147 } 148 [Symbol.iterator](): IterableIterator<T> { 149 errorUtil.checkBindError('Symbol.iterator', Stack, this); 150 let count: number = 0; 151 let stack: Stack<T> = this; 152 return { 153 next: function (): { done: boolean, value: T } { 154 let done: boolean = false; 155 let value: T = undefined; 156 done = count >= stack.elementNum; 157 value = done ? undefined : stack[count++]; 158 return { 159 done: done, 160 value: value, 161 }; 162 }, 163 }; 164 } 165 } 166 Object.freeze(Stack); 167 fastStack = Stack; 168} 169export default fastStack; 170