From 359e1f66c37b38b475a07451aaef606591e7c5a2 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 8 Dec 2023 11:06:15 -0500 Subject: [PATCH 1/8] Fix Set.entries() --- .gitignore | 8 +- .npmignore | 6 + README.md | 53 + Reflect.d.ts | 494 ------ Reflect.js | 1141 ------------- Reflect.js.map | 1 - Reflect.ts | 132 +- ReflectLite.ts | 1505 +++++++++++++++++ ReflectNoConflict.ts | 1368 +++++++++++++++ bower.json | 36 - globals.d.ts | 91 + gulpfile.js | 66 +- no-conflict.d.ts | 484 ++++++ package.json | 37 +- reflect-metadata.d.ts | 20 - test/full/reflect-decorate.ts | 211 +++ test/full/reflect-definemetadata.ts | 20 + test/full/reflect-deletemetadata.ts | 41 + test/full/reflect-getmetadata.ts | 54 + test/full/reflect-getmetadatakeys.ts | 101 ++ test/full/reflect-getownmetadata.ts | 54 + test/full/reflect-getownmetadatakeys.ts | 81 + test/full/reflect-hasmetadata.ts | 54 + test/full/reflect-hasownmetadata.ts | 54 + test/{ => full}/reflect-metadata.ts | 5 +- test/{ => full}/reflect-other.ts | 2 +- test/lite/reflect-decorate.ts | 211 +++ test/lite/reflect-definemetadata.ts | 20 + test/lite/reflect-deletemetadata.ts | 41 + test/lite/reflect-getmetadata.ts | 54 + test/lite/reflect-getmetadatakeys.ts | 101 ++ test/lite/reflect-getownmetadata.ts | 54 + test/lite/reflect-getownmetadatakeys.ts | 81 + test/lite/reflect-hasmetadata.ts | 54 + test/lite/reflect-hasownmetadata.ts | 54 + test/lite/reflect-metadata.ts | 41 + test/lite/reflect-other.ts | 17 + test/{ => no-conflict}/reflect-decorate.ts | 86 +- .../reflect-definemetadata.ts | 6 +- .../reflect-deletemetadata.ts | 20 +- test/{ => no-conflict}/reflect-getmetadata.ts | 14 +- .../reflect-getmetadatakeys.ts | 36 +- .../reflect-getownmetadata.ts | 14 +- .../reflect-getownmetadatakeys.ts | 30 +- test/{ => no-conflict}/reflect-hasmetadata.ts | 14 +- .../reflect-hasownmetadata.ts | 14 +- test/no-conflict/reflect-metadata.ts | 41 + test/tsconfig.json | 3 +- tsconfig-release.json | 35 +- tsconfig.json | 5 +- typings.d.ts | 20 - 51 files changed, 5236 insertions(+), 1949 deletions(-) delete mode 100644 Reflect.d.ts delete mode 100644 Reflect.js delete mode 100644 Reflect.js.map create mode 100644 ReflectLite.ts create mode 100644 ReflectNoConflict.ts delete mode 100644 bower.json create mode 100644 globals.d.ts create mode 100644 no-conflict.d.ts delete mode 100644 reflect-metadata.d.ts create mode 100644 test/full/reflect-decorate.ts create mode 100644 test/full/reflect-definemetadata.ts create mode 100644 test/full/reflect-deletemetadata.ts create mode 100644 test/full/reflect-getmetadata.ts create mode 100644 test/full/reflect-getmetadatakeys.ts create mode 100644 test/full/reflect-getownmetadata.ts create mode 100644 test/full/reflect-getownmetadatakeys.ts create mode 100644 test/full/reflect-hasmetadata.ts create mode 100644 test/full/reflect-hasownmetadata.ts rename test/{ => full}/reflect-metadata.ts (91%) rename test/{ => full}/reflect-other.ts (84%) create mode 100644 test/lite/reflect-decorate.ts create mode 100644 test/lite/reflect-definemetadata.ts create mode 100644 test/lite/reflect-deletemetadata.ts create mode 100644 test/lite/reflect-getmetadata.ts create mode 100644 test/lite/reflect-getmetadatakeys.ts create mode 100644 test/lite/reflect-getownmetadata.ts create mode 100644 test/lite/reflect-getownmetadatakeys.ts create mode 100644 test/lite/reflect-hasmetadata.ts create mode 100644 test/lite/reflect-hasownmetadata.ts create mode 100644 test/lite/reflect-metadata.ts create mode 100644 test/lite/reflect-other.ts rename test/{ => no-conflict}/reflect-decorate.ts (58%) rename test/{ => no-conflict}/reflect-definemetadata.ts (81%) rename test/{ => no-conflict}/reflect-deletemetadata.ts (77%) rename test/{ => no-conflict}/reflect-getmetadata.ts (80%) rename test/{ => no-conflict}/reflect-getmetadatakeys.ts (73%) rename test/{ => no-conflict}/reflect-getownmetadata.ts (88%) rename test/{ => no-conflict}/reflect-getownmetadatakeys.ts (70%) rename test/{ => no-conflict}/reflect-hasmetadata.ts (78%) rename test/{ => no-conflict}/reflect-hasownmetadata.ts (88%) create mode 100644 test/no-conflict/reflect-metadata.ts delete mode 100644 typings.d.ts diff --git a/.gitignore b/.gitignore index 005715f..fa2f5e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,10 @@ .vscode/ node_modules/ test/**/*.js -test/**/*.js.map \ No newline at end of file +test/**/*.js.map +index.d.mts +no-conflict.d.mts +*.js +*.js.map +*.mjs +*.mjs.map diff --git a/.npmignore b/.npmignore index 53a9e9b..55d2120 100644 --- a/.npmignore +++ b/.npmignore @@ -1,14 +1,20 @@ .vscode node_modules out +docs spec temp test typings bower.json gulpfile.js +globals.d.ts Reflect.ts Reflect.js.map +ReflectLite.ts +ReflectLite.js.map +ReflectNoConflict.ts +ReflectNoConflict.js.map spec.html tsconfig.json tsconfig-release.json \ No newline at end of file diff --git a/README.md b/README.md index be056dc..8f6feb5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # Metadata Reflection API +NOTE: Now that both [Decorators](https://github.com/tc39/proposal-decorators) and +[Decorator Metadata](https://github.com/tc39/proposal-decorator-metadata) have achieved Stage 3 within TC39, the API +proposed below is no longer being considered for standardization. However, this package will continue to support +projects that leverage TypeScript's legacy `--experimentalDecorators` option as some projects may not be able to migrate +to use standard decorators. + * [Detailed proposal][Metadata-Spec] ## Installation @@ -8,6 +14,53 @@ npm install reflect-metadata ``` +## Usage + +### ES Modules in NodeJS/Browser, TypeScript/Babel, Bundlers +```ts +// - Modifies global `Reflect` object (or defines one in ES5 runtimes). +// - Supports ESM and CommonJS. +// - Contains internal polyfills for `Map`, `Set`, and `WeakMap` for older runtimes. +import "reflect-metadata"; + +// - Modifies global `Reflect` object (or defines one in ES5 runtimes). +// - Supports ESM and CommonJS. +// - Requires runtime support for `"exports"` in `package.json`. +// - Does not include internal polyfills. +import "reflect-metadata/lite"; +``` + +### CommonJS +```ts +// - Modifies global `Reflect` object (or defines one in ES5 runtimes). +// - Contains internal polyfills for `Map`, `Set`, and `WeakMap` for older runtimes. +require("reflect-metadata"); + +// - Modifies global `Reflect` object (or defines one in ES5 runtimes). +// - Requires runtime support for `"exports"` in `package.json`. +// - Does not include internal polyfills. +require("reflect-metadata/lite"); +``` + +### In the Browser via ` + + + + +``` + +**Script** +```js +// - Makes types available in your editor. +/// + +``` + ## Background * Decorators add the ability to augment a class and its members as the class is defined, through a declarative syntax. diff --git a/Reflect.d.ts b/Reflect.d.ts deleted file mode 100644 index 7cce59f..0000000 --- a/Reflect.d.ts +++ /dev/null @@ -1,494 +0,0 @@ -/*! ***************************************************************************** -Copyright (C) Microsoft. All rights reserved. -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ - -// NOTE: This file is obsolete and may be removed in a later release. -// For CommonJS/AMD/UMD/SystemJS declarations please use 'index.d.ts'. -// For standalone browser declarations, please use 'standalone.d.ts'. - -declare module "reflect-metadata" { - // The "reflect-metadata" module has no imports or exports, but can be used by modules to load the polyfill. -} - -declare namespace Reflect { - /** - * Applies a set of decorators to a target object. - * @param decorators An array of decorators. - * @param target The target object. - * @returns The result of applying the provided decorators. - * @remarks Decorators are applied in reverse order of their positions in the array. - * @example - * - * class Example { } - * - * // constructor - * Example = Reflect.decorate(decoratorsArray, Example); - * - */ - function decorate(decorators: ClassDecorator[], target: Function): Function; - /** - * Applies a set of decorators to a property of a target object. - * @param decorators An array of decorators. - * @param target The target object. - * @param targetKey The property key to decorate. - * @param descriptor A property descriptor - * @remarks Decorators are applied in reverse order. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * static staticMethod() { } - * method() { } - * } - * - * // property (on constructor) - * Reflect.decorate(decoratorsArray, Example, "staticProperty"); - * - * // property (on prototype) - * Reflect.decorate(decoratorsArray, Example.prototype, "property"); - * - * // method (on constructor) - * Object.defineProperty(Example, "staticMethod", - * Reflect.decorate(decoratorsArray, Example, "staticMethod", - * Object.getOwnPropertyDescriptor(Example, "staticMethod"))); - * - * // method (on prototype) - * Object.defineProperty(Example.prototype, "method", - * Reflect.decorate(decoratorsArray, Example.prototype, "method", - * Object.getOwnPropertyDescriptor(Example.prototype, "method"))); - * - */ - function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: Object, targetKey: string | symbol, descriptor?: PropertyDescriptor): PropertyDescriptor; - /** - * A default metadata decorator factory that can be used on a class, class member, or parameter. - * @param metadataKey The key for the metadata entry. - * @param metadataValue The value for the metadata entry. - * @returns A decorator function. - * @remarks - * If `metadataKey` is already defined for the target and target key, the - * metadataValue for that key will be overwritten. - * @example - * - * // constructor - * @Reflect.metadata(key, value) - * class Example { - * } - * - * // property (on constructor, TypeScript only) - * class Example { - * @Reflect.metadata(key, value) - * static staticProperty; - * } - * - * // property (on prototype, TypeScript only) - * class Example { - * @Reflect.metadata(key, value) - * property; - * } - * - * // method (on constructor) - * class Example { - * @Reflect.metadata(key, value) - * static staticMethod() { } - * } - * - * // method (on prototype) - * class Example { - * @Reflect.metadata(key, value) - * method() { } - * } - * - */ - function metadata(metadataKey: any, metadataValue: any): { - (target: Function): void; - (target: Object, targetKey: string | symbol): void; - }; - /** - * Define a unique metadata entry on the target. - * @param metadataKey A key used to store and retrieve metadata. - * @param metadataValue A value that contains attached metadata. - * @param target The target object on which to define metadata. - * @example - * - * class Example { - * } - * - * // constructor - * Reflect.defineMetadata("custom:annotation", options, Example); - * - * // decorator factory as metadata-producing annotation. - * function MyAnnotation(options): ClassDecorator { - * return target => Reflect.defineMetadata("custom:annotation", options, target); - * } - * - */ - function defineMetadata(metadataKey: any, metadataValue: any, target: Object): void; - /** - * Define a unique metadata entry on the target. - * @param metadataKey A key used to store and retrieve metadata. - * @param metadataValue A value that contains attached metadata. - * @param target The target object on which to define metadata. - * @param targetKey The property key for the target. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * static staticMethod(p) { } - * method(p) { } - * } - * - * // property (on constructor) - * Reflect.defineMetadata("custom:annotation", Number, Example, "staticProperty"); - * - * // property (on prototype) - * Reflect.defineMetadata("custom:annotation", Number, Example.prototype, "property"); - * - * // method (on constructor) - * Reflect.defineMetadata("custom:annotation", Number, Example, "staticMethod"); - * - * // method (on prototype) - * Reflect.defineMetadata("custom:annotation", Number, Example.prototype, "method"); - * - * // decorator factory as metadata-producing annotation. - * function MyAnnotation(options): PropertyDecorator { - * return (target, key) => Reflect.defineMetadata("custom:annotation", options, target, key); - * } - * - */ - function defineMetadata(metadataKey: any, metadataValue: any, target: Object, targetKey: string | symbol): void; - /** - * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. - * @example - * - * class Example { - * } - * - * // constructor - * result = Reflect.hasMetadata("custom:annotation", Example); - * - */ - function hasMetadata(metadataKey: any, target: Object): boolean; - /** - * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @param targetKey The property key for the target. - * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * static staticMethod(p) { } - * method(p) { } - * } - * - * // property (on constructor) - * result = Reflect.hasMetadata("custom:annotation", Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.hasMetadata("custom:annotation", Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "method"); - * - */ - function hasMetadata(metadataKey: any, target: Object, targetKey: string | symbol): boolean; - /** - * Gets a value indicating whether the target object has the provided metadata key defined. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. - * @example - * - * class Example { - * } - * - * // constructor - * result = Reflect.hasOwnMetadata("custom:annotation", Example); - * - */ - function hasOwnMetadata(metadataKey: any, target: Object): boolean; - /** - * Gets a value indicating whether the target object has the provided metadata key defined. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @param targetKey The property key for the target. - * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * static staticMethod(p) { } - * method(p) { } - * } - * - * // property (on constructor) - * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "method"); - * - */ - function hasOwnMetadata(metadataKey: any, target: Object, targetKey: string | symbol): boolean; - /** - * Gets the metadata value for the provided metadata key on the target object or its prototype chain. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @returns The metadata value for the metadata key if found; otherwise, `undefined`. - * @example - * - * class Example { - * } - * - * // constructor - * result = Reflect.getMetadata("custom:annotation", Example); - * - */ - function getMetadata(metadataKey: any, target: Object): any; - /** - * Gets the metadata value for the provided metadata key on the target object or its prototype chain. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @param targetKey The property key for the target. - * @returns The metadata value for the metadata key if found; otherwise, `undefined`. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * static staticMethod(p) { } - * method(p) { } - * } - * - * // property (on constructor) - * result = Reflect.getMetadata("custom:annotation", Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.getMetadata("custom:annotation", Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.getMetadata("custom:annotation", Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.getMetadata("custom:annotation", Example.prototype, "method"); - * - */ - function getMetadata(metadataKey: any, target: Object, targetKey: string | symbol): any; - /** - * Gets the metadata value for the provided metadata key on the target object. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @returns The metadata value for the metadata key if found; otherwise, `undefined`. - * @example - * - * class Example { - * } - * - * // constructor - * result = Reflect.getOwnMetadata("custom:annotation", Example); - * - */ - function getOwnMetadata(metadataKey: any, target: Object): any; - /** - * Gets the metadata value for the provided metadata key on the target object. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @param targetKey The property key for the target. - * @returns The metadata value for the metadata key if found; otherwise, `undefined`. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * static staticMethod(p) { } - * method(p) { } - * } - * - * // property (on constructor) - * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "method"); - * - */ - function getOwnMetadata(metadataKey: any, target: Object, targetKey: string | symbol): any; - /** - * Gets the metadata keys defined on the target object or its prototype chain. - * @param target The target object on which the metadata is defined. - * @returns An array of unique metadata keys. - * @example - * - * class Example { - * } - * - * // constructor - * result = Reflect.getMetadataKeys(Example); - * - */ - function getMetadataKeys(target: Object): any[]; - /** - * Gets the metadata keys defined on the target object or its prototype chain. - * @param target The target object on which the metadata is defined. - * @param targetKey The property key for the target. - * @returns An array of unique metadata keys. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * static staticMethod(p) { } - * method(p) { } - * } - * - * // property (on constructor) - * result = Reflect.getMetadataKeys(Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.getMetadataKeys(Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.getMetadataKeys(Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.getMetadataKeys(Example.prototype, "method"); - * - */ - function getMetadataKeys(target: Object, targetKey: string | symbol): any[]; - /** - * Gets the unique metadata keys defined on the target object. - * @param target The target object on which the metadata is defined. - * @returns An array of unique metadata keys. - * @example - * - * class Example { - * } - * - * // constructor - * result = Reflect.getOwnMetadataKeys(Example); - * - */ - function getOwnMetadataKeys(target: Object): any[]; - /** - * Gets the unique metadata keys defined on the target object. - * @param target The target object on which the metadata is defined. - * @param targetKey The property key for the target. - * @returns An array of unique metadata keys. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * static staticMethod(p) { } - * method(p) { } - * } - * - * // property (on constructor) - * result = Reflect.getOwnMetadataKeys(Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.getOwnMetadataKeys(Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.getOwnMetadataKeys(Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.getOwnMetadataKeys(Example.prototype, "method"); - * - */ - function getOwnMetadataKeys(target: Object, targetKey: string | symbol): any[]; - /** - * Deletes the metadata entry from the target object with the provided key. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @returns `true` if the metadata entry was found and deleted; otherwise, false. - * @example - * - * class Example { - * } - * - * // constructor - * result = Reflect.deleteMetadata("custom:annotation", Example); - * - */ - function deleteMetadata(metadataKey: any, target: Object): boolean; - /** - * Deletes the metadata entry from the target object with the provided key. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @param targetKey The property key for the target. - * @returns `true` if the metadata entry was found and deleted; otherwise, false. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * static staticMethod(p) { } - * method(p) { } - * } - * - * // property (on constructor) - * result = Reflect.deleteMetadata("custom:annotation", Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.deleteMetadata("custom:annotation", Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "method"); - * - */ - function deleteMetadata(metadataKey: any, target: Object, targetKey: string | symbol): boolean; -} \ No newline at end of file diff --git a/Reflect.js b/Reflect.js deleted file mode 100644 index c1ff58f..0000000 --- a/Reflect.js +++ /dev/null @@ -1,1141 +0,0 @@ -/*! ***************************************************************************** -Copyright (C) Microsoft. All rights reserved. -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ -var Reflect; -(function (Reflect) { - // Metadata Proposal - // https://rbuckton.github.io/reflect-metadata/ - (function (factory) { - var root = typeof global === "object" ? global : - typeof self === "object" ? self : - typeof this === "object" ? this : - Function("return this;")(); - var exporter = makeExporter(Reflect); - if (typeof root.Reflect === "undefined") { - root.Reflect = Reflect; - } - else { - exporter = makeExporter(root.Reflect, exporter); - } - factory(exporter); - function makeExporter(target, previous) { - return function (key, value) { - if (typeof target[key] !== "function") { - Object.defineProperty(target, key, { configurable: true, writable: true, value: value }); - } - if (previous) - previous(key, value); - }; - } - })(function (exporter) { - var hasOwn = Object.prototype.hasOwnProperty; - // feature test for Symbol support - var supportsSymbol = typeof Symbol === "function"; - var toPrimitiveSymbol = supportsSymbol && typeof Symbol.toPrimitive !== "undefined" ? Symbol.toPrimitive : "@@toPrimitive"; - var iteratorSymbol = supportsSymbol && typeof Symbol.iterator !== "undefined" ? Symbol.iterator : "@@iterator"; - var supportsCreate = typeof Object.create === "function"; // feature test for Object.create support - var supportsProto = { __proto__: [] } instanceof Array; // feature test for __proto__ support - var downLevel = !supportsCreate && !supportsProto; - var HashMap = { - // create an object in dictionary mode (a.k.a. "slow" mode in v8) - create: supportsCreate - ? function () { return MakeDictionary(Object.create(null)); } - : supportsProto - ? function () { return MakeDictionary({ __proto__: null }); } - : function () { return MakeDictionary({}); }, - has: downLevel - ? function (map, key) { return hasOwn.call(map, key); } - : function (map, key) { return key in map; }, - get: downLevel - ? function (map, key) { return hasOwn.call(map, key) ? map[key] : undefined; } - : function (map, key) { return map[key]; }, - }; - // Load global or shim versions of Map, Set, and WeakMap - var functionPrototype = Object.getPrototypeOf(Function); - var usePolyfill = typeof process === "object" && process["env" + ""] && process["env" + ""]["REFLECT_METADATA_USE_MAP_POLYFILL"] === "true"; - var _Map = !usePolyfill && typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : CreateMapPolyfill(); - var _Set = !usePolyfill && typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : CreateSetPolyfill(); - var _WeakMap = !usePolyfill && typeof WeakMap === "function" ? WeakMap : CreateWeakMapPolyfill(); - // [[Metadata]] internal slot - // https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots - var Metadata = new _WeakMap(); - /** - * Applies a set of decorators to a property of a target object. - * @param decorators An array of decorators. - * @param target The target object. - * @param propertyKey (Optional) The property key to decorate. - * @param attributes (Optional) The property descriptor for the target key. - * @remarks Decorators are applied in reverse order. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * constructor(p) { } - * static staticMethod(p) { } - * method(p) { } - * } - * - * // constructor - * Example = Reflect.decorate(decoratorsArray, Example); - * - * // property (on constructor) - * Reflect.decorate(decoratorsArray, Example, "staticProperty"); - * - * // property (on prototype) - * Reflect.decorate(decoratorsArray, Example.prototype, "property"); - * - * // method (on constructor) - * Object.defineProperty(Example, "staticMethod", - * Reflect.decorate(decoratorsArray, Example, "staticMethod", - * Object.getOwnPropertyDescriptor(Example, "staticMethod"))); - * - * // method (on prototype) - * Object.defineProperty(Example.prototype, "method", - * Reflect.decorate(decoratorsArray, Example.prototype, "method", - * Object.getOwnPropertyDescriptor(Example.prototype, "method"))); - * - */ - function decorate(decorators, target, propertyKey, attributes) { - if (!IsUndefined(propertyKey)) { - if (!IsArray(decorators)) - throw new TypeError(); - if (!IsObject(target)) - throw new TypeError(); - if (!IsObject(attributes) && !IsUndefined(attributes) && !IsNull(attributes)) - throw new TypeError(); - if (IsNull(attributes)) - attributes = undefined; - propertyKey = ToPropertyKey(propertyKey); - return DecorateProperty(decorators, target, propertyKey, attributes); - } - else { - if (!IsArray(decorators)) - throw new TypeError(); - if (!IsConstructor(target)) - throw new TypeError(); - return DecorateConstructor(decorators, target); - } - } - exporter("decorate", decorate); - // 4.1.2 Reflect.metadata(metadataKey, metadataValue) - // https://rbuckton.github.io/reflect-metadata/#reflect.metadata - /** - * A default metadata decorator factory that can be used on a class, class member, or parameter. - * @param metadataKey The key for the metadata entry. - * @param metadataValue The value for the metadata entry. - * @returns A decorator function. - * @remarks - * If `metadataKey` is already defined for the target and target key, the - * metadataValue for that key will be overwritten. - * @example - * - * // constructor - * @Reflect.metadata(key, value) - * class Example { - * } - * - * // property (on constructor, TypeScript only) - * class Example { - * @Reflect.metadata(key, value) - * static staticProperty; - * } - * - * // property (on prototype, TypeScript only) - * class Example { - * @Reflect.metadata(key, value) - * property; - * } - * - * // method (on constructor) - * class Example { - * @Reflect.metadata(key, value) - * static staticMethod() { } - * } - * - * // method (on prototype) - * class Example { - * @Reflect.metadata(key, value) - * method() { } - * } - * - */ - function metadata(metadataKey, metadataValue) { - function decorator(target, propertyKey) { - if (!IsObject(target)) - throw new TypeError(); - if (!IsUndefined(propertyKey) && !IsPropertyKey(propertyKey)) - throw new TypeError(); - OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey); - } - return decorator; - } - exporter("metadata", metadata); - /** - * Define a unique metadata entry on the target. - * @param metadataKey A key used to store and retrieve metadata. - * @param metadataValue A value that contains attached metadata. - * @param target The target object on which to define metadata. - * @param propertyKey (Optional) The property key for the target. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * constructor(p) { } - * static staticMethod(p) { } - * method(p) { } - * } - * - * // constructor - * Reflect.defineMetadata("custom:annotation", options, Example); - * - * // property (on constructor) - * Reflect.defineMetadata("custom:annotation", options, Example, "staticProperty"); - * - * // property (on prototype) - * Reflect.defineMetadata("custom:annotation", options, Example.prototype, "property"); - * - * // method (on constructor) - * Reflect.defineMetadata("custom:annotation", options, Example, "staticMethod"); - * - * // method (on prototype) - * Reflect.defineMetadata("custom:annotation", options, Example.prototype, "method"); - * - * // decorator factory as metadata-producing annotation. - * function MyAnnotation(options): Decorator { - * return (target, key?) => Reflect.defineMetadata("custom:annotation", options, target, key); - * } - * - */ - function defineMetadata(metadataKey, metadataValue, target, propertyKey) { - if (!IsObject(target)) - throw new TypeError(); - if (!IsUndefined(propertyKey)) - propertyKey = ToPropertyKey(propertyKey); - return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey); - } - exporter("defineMetadata", defineMetadata); - /** - * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @param propertyKey (Optional) The property key for the target. - * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * constructor(p) { } - * static staticMethod(p) { } - * method(p) { } - * } - * - * // constructor - * result = Reflect.hasMetadata("custom:annotation", Example); - * - * // property (on constructor) - * result = Reflect.hasMetadata("custom:annotation", Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.hasMetadata("custom:annotation", Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "method"); - * - */ - function hasMetadata(metadataKey, target, propertyKey) { - if (!IsObject(target)) - throw new TypeError(); - if (!IsUndefined(propertyKey)) - propertyKey = ToPropertyKey(propertyKey); - return OrdinaryHasMetadata(metadataKey, target, propertyKey); - } - exporter("hasMetadata", hasMetadata); - /** - * Gets a value indicating whether the target object has the provided metadata key defined. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @param propertyKey (Optional) The property key for the target. - * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * constructor(p) { } - * static staticMethod(p) { } - * method(p) { } - * } - * - * // constructor - * result = Reflect.hasOwnMetadata("custom:annotation", Example); - * - * // property (on constructor) - * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "method"); - * - */ - function hasOwnMetadata(metadataKey, target, propertyKey) { - if (!IsObject(target)) - throw new TypeError(); - if (!IsUndefined(propertyKey)) - propertyKey = ToPropertyKey(propertyKey); - return OrdinaryHasOwnMetadata(metadataKey, target, propertyKey); - } - exporter("hasOwnMetadata", hasOwnMetadata); - /** - * Gets the metadata value for the provided metadata key on the target object or its prototype chain. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @param propertyKey (Optional) The property key for the target. - * @returns The metadata value for the metadata key if found; otherwise, `undefined`. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * constructor(p) { } - * static staticMethod(p) { } - * method(p) { } - * } - * - * // constructor - * result = Reflect.getMetadata("custom:annotation", Example); - * - * // property (on constructor) - * result = Reflect.getMetadata("custom:annotation", Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.getMetadata("custom:annotation", Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.getMetadata("custom:annotation", Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.getMetadata("custom:annotation", Example.prototype, "method"); - * - */ - function getMetadata(metadataKey, target, propertyKey) { - if (!IsObject(target)) - throw new TypeError(); - if (!IsUndefined(propertyKey)) - propertyKey = ToPropertyKey(propertyKey); - return OrdinaryGetMetadata(metadataKey, target, propertyKey); - } - exporter("getMetadata", getMetadata); - /** - * Gets the metadata value for the provided metadata key on the target object. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @param propertyKey (Optional) The property key for the target. - * @returns The metadata value for the metadata key if found; otherwise, `undefined`. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * constructor(p) { } - * static staticMethod(p) { } - * method(p) { } - * } - * - * // constructor - * result = Reflect.getOwnMetadata("custom:annotation", Example); - * - * // property (on constructor) - * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "method"); - * - */ - function getOwnMetadata(metadataKey, target, propertyKey) { - if (!IsObject(target)) - throw new TypeError(); - if (!IsUndefined(propertyKey)) - propertyKey = ToPropertyKey(propertyKey); - return OrdinaryGetOwnMetadata(metadataKey, target, propertyKey); - } - exporter("getOwnMetadata", getOwnMetadata); - /** - * Gets the metadata keys defined on the target object or its prototype chain. - * @param target The target object on which the metadata is defined. - * @param propertyKey (Optional) The property key for the target. - * @returns An array of unique metadata keys. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * constructor(p) { } - * static staticMethod(p) { } - * method(p) { } - * } - * - * // constructor - * result = Reflect.getMetadataKeys(Example); - * - * // property (on constructor) - * result = Reflect.getMetadataKeys(Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.getMetadataKeys(Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.getMetadataKeys(Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.getMetadataKeys(Example.prototype, "method"); - * - */ - function getMetadataKeys(target, propertyKey) { - if (!IsObject(target)) - throw new TypeError(); - if (!IsUndefined(propertyKey)) - propertyKey = ToPropertyKey(propertyKey); - return OrdinaryMetadataKeys(target, propertyKey); - } - exporter("getMetadataKeys", getMetadataKeys); - /** - * Gets the unique metadata keys defined on the target object. - * @param target The target object on which the metadata is defined. - * @param propertyKey (Optional) The property key for the target. - * @returns An array of unique metadata keys. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * constructor(p) { } - * static staticMethod(p) { } - * method(p) { } - * } - * - * // constructor - * result = Reflect.getOwnMetadataKeys(Example); - * - * // property (on constructor) - * result = Reflect.getOwnMetadataKeys(Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.getOwnMetadataKeys(Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.getOwnMetadataKeys(Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.getOwnMetadataKeys(Example.prototype, "method"); - * - */ - function getOwnMetadataKeys(target, propertyKey) { - if (!IsObject(target)) - throw new TypeError(); - if (!IsUndefined(propertyKey)) - propertyKey = ToPropertyKey(propertyKey); - return OrdinaryOwnMetadataKeys(target, propertyKey); - } - exporter("getOwnMetadataKeys", getOwnMetadataKeys); - /** - * Deletes the metadata entry from the target object with the provided key. - * @param metadataKey A key used to store and retrieve metadata. - * @param target The target object on which the metadata is defined. - * @param propertyKey (Optional) The property key for the target. - * @returns `true` if the metadata entry was found and deleted; otherwise, false. - * @example - * - * class Example { - * // property declarations are not part of ES6, though they are valid in TypeScript: - * // static staticProperty; - * // property; - * - * constructor(p) { } - * static staticMethod(p) { } - * method(p) { } - * } - * - * // constructor - * result = Reflect.deleteMetadata("custom:annotation", Example); - * - * // property (on constructor) - * result = Reflect.deleteMetadata("custom:annotation", Example, "staticProperty"); - * - * // property (on prototype) - * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "property"); - * - * // method (on constructor) - * result = Reflect.deleteMetadata("custom:annotation", Example, "staticMethod"); - * - * // method (on prototype) - * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "method"); - * - */ - function deleteMetadata(metadataKey, target, propertyKey) { - if (!IsObject(target)) - throw new TypeError(); - if (!IsUndefined(propertyKey)) - propertyKey = ToPropertyKey(propertyKey); - var metadataMap = GetOrCreateMetadataMap(target, propertyKey, /*Create*/ false); - if (IsUndefined(metadataMap)) - return false; - if (!metadataMap.delete(metadataKey)) - return false; - if (metadataMap.size > 0) - return true; - var targetMetadata = Metadata.get(target); - targetMetadata.delete(propertyKey); - if (targetMetadata.size > 0) - return true; - Metadata.delete(target); - return true; - } - exporter("deleteMetadata", deleteMetadata); - function DecorateConstructor(decorators, target) { - for (var i = decorators.length - 1; i >= 0; --i) { - var decorator = decorators[i]; - var decorated = decorator(target); - if (!IsUndefined(decorated) && !IsNull(decorated)) { - if (!IsConstructor(decorated)) - throw new TypeError(); - target = decorated; - } - } - return target; - } - function DecorateProperty(decorators, target, propertyKey, descriptor) { - for (var i = decorators.length - 1; i >= 0; --i) { - var decorator = decorators[i]; - var decorated = decorator(target, propertyKey, descriptor); - if (!IsUndefined(decorated) && !IsNull(decorated)) { - if (!IsObject(decorated)) - throw new TypeError(); - descriptor = decorated; - } - } - return descriptor; - } - function GetOrCreateMetadataMap(O, P, Create) { - var targetMetadata = Metadata.get(O); - if (IsUndefined(targetMetadata)) { - if (!Create) - return undefined; - targetMetadata = new _Map(); - Metadata.set(O, targetMetadata); - } - var metadataMap = targetMetadata.get(P); - if (IsUndefined(metadataMap)) { - if (!Create) - return undefined; - metadataMap = new _Map(); - targetMetadata.set(P, metadataMap); - } - return metadataMap; - } - // 3.1.1.1 OrdinaryHasMetadata(MetadataKey, O, P) - // https://rbuckton.github.io/reflect-metadata/#ordinaryhasmetadata - function OrdinaryHasMetadata(MetadataKey, O, P) { - var hasOwn = OrdinaryHasOwnMetadata(MetadataKey, O, P); - if (hasOwn) - return true; - var parent = OrdinaryGetPrototypeOf(O); - if (!IsNull(parent)) - return OrdinaryHasMetadata(MetadataKey, parent, P); - return false; - } - // 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P) - // https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata - function OrdinaryHasOwnMetadata(MetadataKey, O, P) { - var metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) - return false; - return ToBoolean(metadataMap.has(MetadataKey)); - } - // 3.1.3.1 OrdinaryGetMetadata(MetadataKey, O, P) - // https://rbuckton.github.io/reflect-metadata/#ordinarygetmetadata - function OrdinaryGetMetadata(MetadataKey, O, P) { - var hasOwn = OrdinaryHasOwnMetadata(MetadataKey, O, P); - if (hasOwn) - return OrdinaryGetOwnMetadata(MetadataKey, O, P); - var parent = OrdinaryGetPrototypeOf(O); - if (!IsNull(parent)) - return OrdinaryGetMetadata(MetadataKey, parent, P); - return undefined; - } - // 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P) - // https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata - function OrdinaryGetOwnMetadata(MetadataKey, O, P) { - var metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) - return undefined; - return metadataMap.get(MetadataKey); - } - // 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) - // https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata - function OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) { - var metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ true); - metadataMap.set(MetadataKey, MetadataValue); - } - // 3.1.6.1 OrdinaryMetadataKeys(O, P) - // https://rbuckton.github.io/reflect-metadata/#ordinarymetadatakeys - function OrdinaryMetadataKeys(O, P) { - var ownKeys = OrdinaryOwnMetadataKeys(O, P); - var parent = OrdinaryGetPrototypeOf(O); - if (parent === null) - return ownKeys; - var parentKeys = OrdinaryMetadataKeys(parent, P); - if (parentKeys.length <= 0) - return ownKeys; - if (ownKeys.length <= 0) - return parentKeys; - var set = new _Set(); - var keys = []; - for (var _i = 0, ownKeys_1 = ownKeys; _i < ownKeys_1.length; _i++) { - var key = ownKeys_1[_i]; - var hasKey = set.has(key); - if (!hasKey) { - set.add(key); - keys.push(key); - } - } - for (var _a = 0, parentKeys_1 = parentKeys; _a < parentKeys_1.length; _a++) { - var key = parentKeys_1[_a]; - var hasKey = set.has(key); - if (!hasKey) { - set.add(key); - keys.push(key); - } - } - return keys; - } - // 3.1.7.1 OrdinaryOwnMetadataKeys(O, P) - // https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys - function OrdinaryOwnMetadataKeys(O, P) { - var keys = []; - var metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) - return keys; - var keysObj = metadataMap.keys(); - var iterator = GetIterator(keysObj); - var k = 0; - while (true) { - var next = IteratorStep(iterator); - if (!next) { - keys.length = k; - return keys; - } - var nextValue = IteratorValue(next); - try { - keys[k] = nextValue; - } - catch (e) { - try { - IteratorClose(iterator); - } - finally { - throw e; - } - } - k++; - } - } - // 6 ECMAScript Data Typ0es and Values - // https://tc39.github.io/ecma262/#sec-ecmascript-data-types-and-values - function Type(x) { - if (x === null) - return 1 /* Null */; - switch (typeof x) { - case "undefined": return 0 /* Undefined */; - case "boolean": return 2 /* Boolean */; - case "string": return 3 /* String */; - case "symbol": return 4 /* Symbol */; - case "number": return 5 /* Number */; - case "object": return x === null ? 1 /* Null */ : 6 /* Object */; - default: return 6 /* Object */; - } - } - // 6.1.1 The Undefined Type - // https://tc39.github.io/ecma262/#sec-ecmascript-language-types-undefined-type - function IsUndefined(x) { - return x === undefined; - } - // 6.1.2 The Null Type - // https://tc39.github.io/ecma262/#sec-ecmascript-language-types-null-type - function IsNull(x) { - return x === null; - } - // 6.1.5 The Symbol Type - // https://tc39.github.io/ecma262/#sec-ecmascript-language-types-symbol-type - function IsSymbol(x) { - return typeof x === "symbol"; - } - // 6.1.7 The Object Type - // https://tc39.github.io/ecma262/#sec-object-type - function IsObject(x) { - return typeof x === "object" ? x !== null : typeof x === "function"; - } - // 7.1 Type Conversion - // https://tc39.github.io/ecma262/#sec-type-conversion - // 7.1.1 ToPrimitive(input [, PreferredType]) - // https://tc39.github.io/ecma262/#sec-toprimitive - function ToPrimitive(input, PreferredType) { - switch (Type(input)) { - case 0 /* Undefined */: return input; - case 1 /* Null */: return input; - case 2 /* Boolean */: return input; - case 3 /* String */: return input; - case 4 /* Symbol */: return input; - case 5 /* Number */: return input; - } - var hint = PreferredType === 3 /* String */ ? "string" : PreferredType === 5 /* Number */ ? "number" : "default"; - var exoticToPrim = GetMethod(input, toPrimitiveSymbol); - if (exoticToPrim !== undefined) { - var result = exoticToPrim.call(input, hint); - if (IsObject(result)) - throw new TypeError(); - return result; - } - return OrdinaryToPrimitive(input, hint === "default" ? "number" : hint); - } - // 7.1.1.1 OrdinaryToPrimitive(O, hint) - // https://tc39.github.io/ecma262/#sec-ordinarytoprimitive - function OrdinaryToPrimitive(O, hint) { - if (hint === "string") { - var toString_1 = O.toString; - if (IsCallable(toString_1)) { - var result = toString_1.call(O); - if (!IsObject(result)) - return result; - } - var valueOf = O.valueOf; - if (IsCallable(valueOf)) { - var result = valueOf.call(O); - if (!IsObject(result)) - return result; - } - } - else { - var valueOf = O.valueOf; - if (IsCallable(valueOf)) { - var result = valueOf.call(O); - if (!IsObject(result)) - return result; - } - var toString_2 = O.toString; - if (IsCallable(toString_2)) { - var result = toString_2.call(O); - if (!IsObject(result)) - return result; - } - } - throw new TypeError(); - } - // 7.1.2 ToBoolean(argument) - // https://tc39.github.io/ecma262/2016/#sec-toboolean - function ToBoolean(argument) { - return !!argument; - } - // 7.1.12 ToString(argument) - // https://tc39.github.io/ecma262/#sec-tostring - function ToString(argument) { - return "" + argument; - } - // 7.1.14 ToPropertyKey(argument) - // https://tc39.github.io/ecma262/#sec-topropertykey - function ToPropertyKey(argument) { - var key = ToPrimitive(argument, 3 /* String */); - if (IsSymbol(key)) - return key; - return ToString(key); - } - // 7.2 Testing and Comparison Operations - // https://tc39.github.io/ecma262/#sec-testing-and-comparison-operations - // 7.2.2 IsArray(argument) - // https://tc39.github.io/ecma262/#sec-isarray - function IsArray(argument) { - return Array.isArray - ? Array.isArray(argument) - : argument instanceof Object - ? argument instanceof Array - : Object.prototype.toString.call(argument) === "[object Array]"; - } - // 7.2.3 IsCallable(argument) - // https://tc39.github.io/ecma262/#sec-iscallable - function IsCallable(argument) { - // NOTE: This is an approximation as we cannot check for [[Call]] internal method. - return typeof argument === "function"; - } - // 7.2.4 IsConstructor(argument) - // https://tc39.github.io/ecma262/#sec-isconstructor - function IsConstructor(argument) { - // NOTE: This is an approximation as we cannot check for [[Construct]] internal method. - return typeof argument === "function"; - } - // 7.2.7 IsPropertyKey(argument) - // https://tc39.github.io/ecma262/#sec-ispropertykey - function IsPropertyKey(argument) { - switch (Type(argument)) { - case 3 /* String */: return true; - case 4 /* Symbol */: return true; - default: return false; - } - } - function SameValueZero(x, y) { - return x === y || x !== x && y !== y; - } - // 7.3 Operations on Objects - // https://tc39.github.io/ecma262/#sec-operations-on-objects - // 7.3.9 GetMethod(V, P) - // https://tc39.github.io/ecma262/#sec-getmethod - function GetMethod(V, P) { - var func = V[P]; - if (func === undefined || func === null) - return undefined; - if (!IsCallable(func)) - throw new TypeError(); - return func; - } - // 7.4 Operations on Iterator Objects - // https://tc39.github.io/ecma262/#sec-operations-on-iterator-objects - function GetIterator(obj) { - var method = GetMethod(obj, iteratorSymbol); - if (!IsCallable(method)) - throw new TypeError(); // from Call - var iterator = method.call(obj); - if (!IsObject(iterator)) - throw new TypeError(); - return iterator; - } - // 7.4.4 IteratorValue(iterResult) - // https://tc39.github.io/ecma262/2016/#sec-iteratorvalue - function IteratorValue(iterResult) { - return iterResult.value; - } - // 7.4.5 IteratorStep(iterator) - // https://tc39.github.io/ecma262/#sec-iteratorstep - function IteratorStep(iterator) { - var result = iterator.next(); - return result.done ? false : result; - } - // 7.4.6 IteratorClose(iterator, completion) - // https://tc39.github.io/ecma262/#sec-iteratorclose - function IteratorClose(iterator) { - var f = iterator["return"]; - if (f) - f.call(iterator); - } - // 9.1 Ordinary Object Internal Methods and Internal Slots - // https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots - // 9.1.1.1 OrdinaryGetPrototypeOf(O) - // https://tc39.github.io/ecma262/#sec-ordinarygetprototypeof - function OrdinaryGetPrototypeOf(O) { - var proto = Object.getPrototypeOf(O); - if (typeof O !== "function" || O === functionPrototype) - return proto; - // TypeScript doesn't set __proto__ in ES5, as it's non-standard. - // Try to determine the superclass constructor. Compatible implementations - // must either set __proto__ on a subclass constructor to the superclass constructor, - // or ensure each class has a valid `constructor` property on its prototype that - // points back to the constructor. - // If this is not the same as Function.[[Prototype]], then this is definately inherited. - // This is the case when in ES6 or when using __proto__ in a compatible browser. - if (proto !== functionPrototype) - return proto; - // If the super prototype is Object.prototype, null, or undefined, then we cannot determine the heritage. - var prototype = O.prototype; - var prototypeProto = prototype && Object.getPrototypeOf(prototype); - if (prototypeProto == null || prototypeProto === Object.prototype) - return proto; - // If the constructor was not a function, then we cannot determine the heritage. - var constructor = prototypeProto.constructor; - if (typeof constructor !== "function") - return proto; - // If we have some kind of self-reference, then we cannot determine the heritage. - if (constructor === O) - return proto; - // we have a pretty good guess at the heritage. - return constructor; - } - // naive Map shim - function CreateMapPolyfill() { - var cacheSentinel = {}; - var arraySentinel = []; - var MapIterator = /** @class */ (function () { - function MapIterator(keys, values, selector) { - this._index = 0; - this._keys = keys; - this._values = values; - this._selector = selector; - } - MapIterator.prototype["@@iterator"] = function () { return this; }; - MapIterator.prototype[iteratorSymbol] = function () { return this; }; - MapIterator.prototype.next = function () { - var index = this._index; - if (index >= 0 && index < this._keys.length) { - var result = this._selector(this._keys[index], this._values[index]); - if (index + 1 >= this._keys.length) { - this._index = -1; - this._keys = arraySentinel; - this._values = arraySentinel; - } - else { - this._index++; - } - return { value: result, done: false }; - } - return { value: undefined, done: true }; - }; - MapIterator.prototype.throw = function (error) { - if (this._index >= 0) { - this._index = -1; - this._keys = arraySentinel; - this._values = arraySentinel; - } - throw error; - }; - MapIterator.prototype.return = function (value) { - if (this._index >= 0) { - this._index = -1; - this._keys = arraySentinel; - this._values = arraySentinel; - } - return { value: value, done: true }; - }; - return MapIterator; - }()); - return /** @class */ (function () { - function Map() { - this._keys = []; - this._values = []; - this._cacheKey = cacheSentinel; - this._cacheIndex = -2; - } - Object.defineProperty(Map.prototype, "size", { - get: function () { return this._keys.length; }, - enumerable: true, - configurable: true - }); - Map.prototype.has = function (key) { return this._find(key, /*insert*/ false) >= 0; }; - Map.prototype.get = function (key) { - var index = this._find(key, /*insert*/ false); - return index >= 0 ? this._values[index] : undefined; - }; - Map.prototype.set = function (key, value) { - var index = this._find(key, /*insert*/ true); - this._values[index] = value; - return this; - }; - Map.prototype.delete = function (key) { - var index = this._find(key, /*insert*/ false); - if (index >= 0) { - var size = this._keys.length; - for (var i = index + 1; i < size; i++) { - this._keys[i - 1] = this._keys[i]; - this._values[i - 1] = this._values[i]; - } - this._keys.length--; - this._values.length--; - if (SameValueZero(key, this._cacheKey)) { - this._cacheKey = cacheSentinel; - this._cacheIndex = -2; - } - return true; - } - return false; - }; - Map.prototype.clear = function () { - this._keys.length = 0; - this._values.length = 0; - this._cacheKey = cacheSentinel; - this._cacheIndex = -2; - }; - Map.prototype.keys = function () { return new MapIterator(this._keys, this._values, getKey); }; - Map.prototype.values = function () { return new MapIterator(this._keys, this._values, getValue); }; - Map.prototype.entries = function () { return new MapIterator(this._keys, this._values, getEntry); }; - Map.prototype["@@iterator"] = function () { return this.entries(); }; - Map.prototype[iteratorSymbol] = function () { return this.entries(); }; - Map.prototype._find = function (key, insert) { - if (!SameValueZero(this._cacheKey, key)) { - this._cacheIndex = -1; - for (var i = 0; i < this._keys.length; i++) { - if (SameValueZero(this._keys[i], key)) { - this._cacheIndex = i; - break; - } - } - } - if (this._cacheIndex < 0 && insert) { - this._cacheIndex = this._keys.length; - this._keys.push(key); - this._values.push(undefined); - } - return this._cacheIndex; - }; - return Map; - }()); - function getKey(key, _) { - return key; - } - function getValue(_, value) { - return value; - } - function getEntry(key, value) { - return [key, value]; - } - } - // naive Set shim - function CreateSetPolyfill() { - return /** @class */ (function () { - function Set() { - this._map = new _Map(); - } - Object.defineProperty(Set.prototype, "size", { - get: function () { return this._map.size; }, - enumerable: true, - configurable: true - }); - Set.prototype.has = function (value) { return this._map.has(value); }; - Set.prototype.add = function (value) { return this._map.set(value, value), this; }; - Set.prototype.delete = function (value) { return this._map.delete(value); }; - Set.prototype.clear = function () { this._map.clear(); }; - Set.prototype.keys = function () { return this._map.keys(); }; - Set.prototype.values = function () { return this._map.keys(); }; - Set.prototype.entries = function () { return this._map.keys(); }; - Set.prototype["@@iterator"] = function () { return this.keys(); }; - Set.prototype[iteratorSymbol] = function () { return this.keys(); }; - return Set; - }()); - } - // naive WeakMap shim - function CreateWeakMapPolyfill() { - var UUID_SIZE = 16; - var keys = HashMap.create(); - var rootKey = CreateUniqueKey(); - return /** @class */ (function () { - function WeakMap() { - this._key = CreateUniqueKey(); - } - WeakMap.prototype.has = function (target) { - var table = GetOrCreateWeakMapTable(target, /*create*/ false); - return table !== undefined ? HashMap.has(table, this._key) : false; - }; - WeakMap.prototype.get = function (target) { - var table = GetOrCreateWeakMapTable(target, /*create*/ false); - return table !== undefined ? HashMap.get(table, this._key) : undefined; - }; - WeakMap.prototype.set = function (target, value) { - var table = GetOrCreateWeakMapTable(target, /*create*/ true); - table[this._key] = value; - return this; - }; - WeakMap.prototype.delete = function (target) { - var table = GetOrCreateWeakMapTable(target, /*create*/ false); - return table !== undefined ? delete table[this._key] : false; - }; - WeakMap.prototype.clear = function () { - // NOTE: not a real clear, just makes the previous data unreachable - this._key = CreateUniqueKey(); - }; - return WeakMap; - }()); - function CreateUniqueKey() { - var key; - do - key = "@@WeakMap@@" + CreateUUID(); - while (HashMap.has(keys, key)); - keys[key] = true; - return key; - } - function GetOrCreateWeakMapTable(target, create) { - if (!hasOwn.call(target, rootKey)) { - if (!create) - return undefined; - Object.defineProperty(target, rootKey, { value: HashMap.create() }); - } - return target[rootKey]; - } - function FillRandomBytes(buffer, size) { - for (var i = 0; i < size; ++i) - buffer[i] = Math.random() * 0xff | 0; - return buffer; - } - function GenRandomBytes(size) { - if (typeof Uint8Array === "function") { - if (typeof crypto !== "undefined") - return crypto.getRandomValues(new Uint8Array(size)); - if (typeof msCrypto !== "undefined") - return msCrypto.getRandomValues(new Uint8Array(size)); - return FillRandomBytes(new Uint8Array(size), size); - } - return FillRandomBytes(new Array(size), size); - } - function CreateUUID() { - var data = GenRandomBytes(UUID_SIZE); - // mark as random - RFC 4122 § 4.4 - data[6] = data[6] & 0x4f | 0x40; - data[8] = data[8] & 0xbf | 0x80; - var result = ""; - for (var offset = 0; offset < UUID_SIZE; ++offset) { - var byte = data[offset]; - if (offset === 4 || offset === 6 || offset === 8) - result += "-"; - if (byte < 16) - result += "0"; - result += byte.toString(16).toLowerCase(); - } - return result; - } - } - // uses a heuristic used by v8 and chakra to force an object into dictionary mode. - function MakeDictionary(obj) { - obj.__ = undefined; - delete obj.__; - return obj; - } - }); -})(Reflect || (Reflect = {})); -//# sourceMappingURL=Reflect.js.map \ No newline at end of file diff --git a/Reflect.js.map b/Reflect.js.map deleted file mode 100644 index 466a91b..0000000 --- a/Reflect.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Reflect.js","sourceRoot":"","sources":["Reflect.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/Reflect.ts b/Reflect.ts index 62e6080..c8e1414 100644 --- a/Reflect.ts +++ b/Reflect.ts @@ -12,6 +12,7 @@ MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ + namespace Reflect { // Metadata Proposal // https://rbuckton.github.io/reflect-metadata/ @@ -23,77 +24,10 @@ namespace Reflect { length: number; } - type IteratorResult = { value: T, done: false } | { value: never, done: true }; - - interface Iterator { - next(value?: any): IteratorResult; - throw?(value: any): IteratorResult; - return?(value?: T): IteratorResult; - } - - interface Iterable { - "@@iterator"(): Iterator; - } - - interface IterableIterator extends Iterator { - "@@iterator"(): IterableIterator; - } - - interface Map extends Iterable<[K, V]> { - size: number; - has(key: K): boolean; - get(key: K): V; - set(key: K, value?: V): this; - delete(key: K): boolean; - clear(): void; - keys(): IterableIterator; - values(): IterableIterator; - entries(): IterableIterator<[K, V]>; - } - - interface MapConstructor { - new (): Map; - new (): Map; - prototype: Map; - } + type MemberDecorator = (target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor) => PropertyDescriptor | void; - interface Set extends Iterable { - size: number; - has(value: T): boolean; - add(value: T): this; - delete(value: T): boolean; - clear(): void; - keys(): IterableIterator; - values(): IterableIterator; - entries(): IterableIterator<[T, T]>; - } - - interface SetConstructor { - new (): Set; - new (): Set; - prototype: Set; - } - - interface WeakMap { - clear(): void; - delete(key: K): boolean; - get(key: K): V; - has(key: K): boolean; - set(key: K, value?: V): WeakMap; - } - - interface WeakMapConstructor { - new (): WeakMap; - new (): WeakMap; - prototype: WeakMap; - } - - type MemberDecorator = (target: Object, propertyKey: string | symbol, descriptor?: TypedPropertyDescriptor) => TypedPropertyDescriptor | void; - declare const Symbol: { iterator: symbol, toPrimitive: symbol }; - declare const Set: SetConstructor; - declare const WeakMap: WeakMapConstructor; - declare const Map: MapConstructor; declare const global: any; + declare const globalThis: any; declare const crypto: Crypto; declare const msCrypto: Crypto; declare const process: any; @@ -621,10 +555,12 @@ namespace Reflect { export declare function deleteMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; (function (this: any, factory: (exporter: (key: K, value: typeof Reflect[K]) => void) => void) { - const root = typeof global === "object" ? global : + const root = + typeof globalThis === "object" ? globalThis : + typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : - Function("return this;")(); + sloppyModeThis(); let exporter = makeExporter(Reflect); if (typeof root.Reflect === "undefined") { @@ -644,6 +580,18 @@ namespace Reflect { if (previous) previous(key, value); }; } + + function functionThis() { + try { return Function("return this;")(); } catch (_) { } + } + + function indirectEvalThis() { + try { return (void 0, eval)("(function() { return this; })()"); } catch (_) { } + } + + function sloppyModeThis() { + return functionThis() || indirectEvalThis(); + } }) (function (exporter) { const hasOwn = Object.prototype.hasOwnProperty; @@ -1533,13 +1481,13 @@ namespace Reflect { // 7.4.4 IteratorValue(iterResult) // https://tc39.github.io/ecma262/2016/#sec-iteratorvalue - function IteratorValue(iterResult: IteratorResult): T { + function IteratorValue(iterResult: __IteratorResult): T { return iterResult.value; } // 7.4.5 IteratorStep(iterator) // https://tc39.github.io/ecma262/#sec-iteratorstep - function IteratorStep(iterator: Iterator): IteratorResult | false { + function IteratorStep(iterator: Iterator): __IteratorResult | false { const result = iterator.next(); return result.done ? false : result; } @@ -1601,9 +1549,9 @@ namespace Reflect { this._values = values; this._selector = selector; } - "@@iterator"() { return this; } - [iteratorSymbol]() { return this; } - next(): IteratorResult { + "@@iterator"(): IterableIterator { return this; } + [iteratorSymbol](): IterableIterator { return this; } + next(): __IteratorResult { const index = this._index; if (index >= 0 && index < this._keys.length) { const result = this._selector(this._keys[index], this._values[index]); @@ -1619,7 +1567,7 @@ namespace Reflect { } return { value: undefined, done: true }; } - throw(error: any): IteratorResult { + throw(error: any): __IteratorResult { if (this._index >= 0) { this._index = -1; this._keys = arraySentinel; @@ -1627,7 +1575,7 @@ namespace Reflect { } throw error; } - return(value?: R): IteratorResult { + return(value?: R): __IteratorResult { if (this._index >= 0) { this._index = -1; this._keys = arraySentinel; @@ -1637,10 +1585,14 @@ namespace Reflect { } } - return class Map { + interface MapIterator { + [Symbol.iterator](): IterableIterator; + } + + class Map { private _keys: K[] = []; private _values: (V | undefined)[] = []; - private _cacheKey = cacheSentinel; + private _cacheKey: any = cacheSentinel; private _cacheIndex = -2; get size() { return this._keys.length; } has(key: K): boolean { return this._find(key, /*insert*/ false) >= 0; } @@ -1699,7 +1651,13 @@ namespace Reflect { } return this._cacheIndex; } - }; + } + + interface Map { + [Symbol.iterator](): IterableIterator<[K, V]>; + } + + return Map; function getKey(key: K, _: V) { return key; @@ -1716,7 +1674,7 @@ namespace Reflect { // naive Set shim function CreateSetPolyfill(): SetConstructor { - return class Set { + class Set { private _map = new _Map(); get size() { return this._map.size; } has(value: T): boolean { return this._map.has(value); } @@ -1725,10 +1683,14 @@ namespace Reflect { clear(): void { this._map.clear(); } keys() { return this._map.keys(); } values() { return this._map.keys(); } - entries() { return this._map.keys(); } + entries() { return this._map.entries(); } "@@iterator"() { return this.keys(); } [iteratorSymbol]() { return this.keys(); } - }; + } + interface Set { + [Symbol.iterator](): IterableIterator; + } + return Set; } // naive WeakMap shim @@ -1816,4 +1778,4 @@ namespace Reflect { return obj; } }); -} \ No newline at end of file +} diff --git a/ReflectLite.ts b/ReflectLite.ts new file mode 100644 index 0000000..78153af --- /dev/null +++ b/ReflectLite.ts @@ -0,0 +1,1505 @@ +/*! ***************************************************************************** +Copyright (C) Microsoft. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + +namespace Reflect { + // Metadata Proposal + // https://rbuckton.github.io/reflect-metadata/ + + type MemberDecorator = (target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor) => PropertyDescriptor | void; + + declare const global: any; + declare const globalThis: any; + declare const self: any; + + /** + * Applies a set of decorators to a target object. + * @param decorators An array of decorators. + * @param target The target object. + * @returns The result of applying the provided decorators. + * @remarks Decorators are applied in reverse order of their positions in the array. + * @example + * + * class Example { } + * + * // constructor + * Example = Reflect.decorate(decoratorsArray, Example); + * + */ + export declare function decorate(decorators: ClassDecorator[], target: Function): Function; + + /** + * Applies a set of decorators to a property of a target object. + * @param decorators An array of decorators. + * @param target The target object. + * @param propertyKey The property key to decorate. + * @param attributes A property descriptor. + * @remarks Decorators are applied in reverse order. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod() { } + * method() { } + * } + * + * // property (on constructor) + * Reflect.decorate(decoratorsArray, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.decorate(decoratorsArray, Example.prototype, "property"); + * + * // method (on constructor) + * Object.defineProperty(Example, "staticMethod", + * Reflect.decorate(decoratorsArray, Example, "staticMethod", + * Object.getOwnPropertyDescriptor(Example, "staticMethod"))); + * + * // method (on prototype) + * Object.defineProperty(Example.prototype, "method", + * Reflect.decorate(decoratorsArray, Example.prototype, "method", + * Object.getOwnPropertyDescriptor(Example.prototype, "method"))); + * + */ + export declare function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined; + + /** + * Applies a set of decorators to a property of a target object. + * @param decorators An array of decorators. + * @param target The target object. + * @param propertyKey The property key to decorate. + * @param attributes A property descriptor. + * @remarks Decorators are applied in reverse order. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod() { } + * method() { } + * } + * + * // property (on constructor) + * Reflect.decorate(decoratorsArray, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.decorate(decoratorsArray, Example.prototype, "property"); + * + * // method (on constructor) + * Object.defineProperty(Example, "staticMethod", + * Reflect.decorate(decoratorsArray, Example, "staticMethod", + * Object.getOwnPropertyDescriptor(Example, "staticMethod"))); + * + * // method (on prototype) + * Object.defineProperty(Example.prototype, "method", + * Reflect.decorate(decoratorsArray, Example.prototype, "method", + * Object.getOwnPropertyDescriptor(Example.prototype, "method"))); + * + */ + export declare function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes: PropertyDescriptor): PropertyDescriptor; + + /** + * A default metadata decorator factory that can be used on a class, class member, or parameter. + * @param metadataKey The key for the metadata entry. + * @param metadataValue The value for the metadata entry. + * @returns A decorator function. + * @remarks + * If `metadataKey` is already defined for the target and target key, the + * metadataValue for that key will be overwritten. + * @example + * + * // constructor + * @Reflect.metadata(key, value) + * class Example { + * } + * + * // property (on constructor, TypeScript only) + * class Example { + * @Reflect.metadata(key, value) + * static staticProperty; + * } + * + * // property (on prototype, TypeScript only) + * class Example { + * @Reflect.metadata(key, value) + * property; + * } + * + * // method (on constructor) + * class Example { + * @Reflect.metadata(key, value) + * static staticMethod() { } + * } + * + * // method (on prototype) + * class Example { + * @Reflect.metadata(key, value) + * method() { } + * } + * + */ + export declare function metadata(metadataKey: any, metadataValue: any): { (target: Function): void; (target: any, propertyKey: string | symbol): void; }; + + /** + * Define a unique metadata entry on the target. + * @param metadataKey A key used to store and retrieve metadata. + * @param metadataValue A value that contains attached metadata. + * @param target The target object on which to define metadata. + * @example + * + * class Example { + * } + * + * // constructor + * Reflect.defineMetadata("custom:annotation", options, Example); + * + * // decorator factory as metadata-producing annotation. + * function MyAnnotation(options): ClassDecorator { + * return target => Reflect.defineMetadata("custom:annotation", options, target); + * } + * + */ + export declare function defineMetadata(metadataKey: any, metadataValue: any, target: any): void; + + /** + * Define a unique metadata entry on the target. + * @param metadataKey A key used to store and retrieve metadata. + * @param metadataValue A value that contains attached metadata. + * @param target The target object on which to define metadata. + * @param propertyKey The property key for the target. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * Reflect.defineMetadata("custom:annotation", Number, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.defineMetadata("custom:annotation", Number, Example.prototype, "property"); + * + * // method (on constructor) + * Reflect.defineMetadata("custom:annotation", Number, Example, "staticMethod"); + * + * // method (on prototype) + * Reflect.defineMetadata("custom:annotation", Number, Example.prototype, "method"); + * + * // decorator factory as metadata-producing annotation. + * function MyAnnotation(options): PropertyDecorator { + * return (target, key) => Reflect.defineMetadata("custom:annotation", options, target, key); + * } + * + */ + export declare function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey: string | symbol): void; + + /** + * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.hasMetadata("custom:annotation", Example); + * + */ + export declare function hasMetadata(metadataKey: any, target: any): boolean; + + /** + * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.hasMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.hasMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "method"); + * + */ + export declare function hasMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; + + /** + * Gets a value indicating whether the target object has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.hasOwnMetadata("custom:annotation", Example); + * + */ + export declare function hasOwnMetadata(metadataKey: any, target: any): boolean; + + /** + * Gets a value indicating whether the target object has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "method"); + * + */ + export declare function hasOwnMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; + + /** + * Gets the metadata value for the provided metadata key on the target object or its prototype chain. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getMetadata("custom:annotation", Example); + * + */ + export declare function getMetadata(metadataKey: any, target: any): any; + + /** + * Gets the metadata value for the provided metadata key on the target object or its prototype chain. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getMetadata("custom:annotation", Example.prototype, "method"); + * + */ + export declare function getMetadata(metadataKey: any, target: any, propertyKey: string | symbol): any; + + /** + * Gets the metadata value for the provided metadata key on the target object. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getOwnMetadata("custom:annotation", Example); + * + */ + export declare function getOwnMetadata(metadataKey: any, target: any): any; + + /** + * Gets the metadata value for the provided metadata key on the target object. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "method"); + * + */ + export declare function getOwnMetadata(metadataKey: any, target: any, propertyKey: string | symbol): any; + + /** + * Gets the metadata keys defined on the target object or its prototype chain. + * @param target The target object on which the metadata is defined. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getMetadataKeys(Example); + * + */ + export declare function getMetadataKeys(target: any): any[]; + + /** + * Gets the metadata keys defined on the target object or its prototype chain. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getMetadataKeys(Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getMetadataKeys(Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getMetadataKeys(Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getMetadataKeys(Example.prototype, "method"); + * + */ + export declare function getMetadataKeys(target: any, propertyKey: string | symbol): any[]; + + /** + * Gets the unique metadata keys defined on the target object. + * @param target The target object on which the metadata is defined. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getOwnMetadataKeys(Example); + * + */ + export declare function getOwnMetadataKeys(target: any): any[]; + + /** + * Gets the unique metadata keys defined on the target object. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getOwnMetadataKeys(Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getOwnMetadataKeys(Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getOwnMetadataKeys(Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getOwnMetadataKeys(Example.prototype, "method"); + * + */ + export declare function getOwnMetadataKeys(target: any, propertyKey: string | symbol): any[]; + + /** + * Deletes the metadata entry from the target object with the provided key. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns `true` if the metadata entry was found and deleted; otherwise, false. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.deleteMetadata("custom:annotation", Example); + * + */ + export declare function deleteMetadata(metadataKey: any, target: any): boolean; + + /** + * Deletes the metadata entry from the target object with the provided key. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns `true` if the metadata entry was found and deleted; otherwise, false. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.deleteMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.deleteMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "method"); + * + */ + export declare function deleteMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; + + (function (this: any, factory: (exporter: (key: K, value: typeof Reflect[K]) => void) => void) { + const root = + typeof globalThis === "object" ? globalThis : + typeof global === "object" ? global : + typeof self === "object" ? self : + typeof this === "object" ? this : + sloppyModeThis(); + + let exporter = makeExporter(Reflect); + if (typeof root.Reflect === "undefined") { + root.Reflect = Reflect; + } + else { + exporter = makeExporter(root.Reflect, exporter); + } + + factory(exporter); + + function makeExporter(target: typeof Reflect, previous?: (key: K, value: typeof Reflect[K]) => void) { + return (key: K, value: typeof Reflect[K]) => { + if (typeof target[key] !== "function") { + Object.defineProperty(target, key, { configurable: true, writable: true, value }); + } + if (previous) previous(key, value); + }; + } + + function functionThis() { + try { return Function("return this;")(); } catch (_) { } + } + + function indirectEvalThis() { + try { return (void 0, eval)("(function() { return this; })()"); } catch (_) { } + } + + function sloppyModeThis() { + return functionThis() || indirectEvalThis(); + } + }) + (function (exporter) { + // feature test for Symbol support + const supportsSymbol = typeof Symbol === "function"; + const toPrimitiveSymbol = supportsSymbol && typeof Symbol.toPrimitive !== "undefined" ? Symbol.toPrimitive : fail("Symbol.toPrimitive not found."); + const iteratorSymbol = supportsSymbol && typeof Symbol.iterator !== "undefined" ? Symbol.iterator : fail("Symbol.iterator not found."); + + // Load global or shim versions of Map, Set, and WeakMap + const functionPrototype = Object.getPrototypeOf(Function); + const _Map: typeof Map = typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : fail("A valid Map constructor could not be found."); + const _Set: typeof Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : fail("A valid Set constructor could not be found."); + const _WeakMap: typeof WeakMap = typeof WeakMap === "function" ? WeakMap : fail("A valid WeakMap constructor could not be found."); + + // [[Metadata]] internal slot + // https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots + const Metadata = new _WeakMap>>(); + + function decorate(decorators: ClassDecorator[], target: Function): Function; + function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined; + function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes: PropertyDescriptor): PropertyDescriptor; + + /** + * Applies a set of decorators to a property of a target object. + * @param decorators An array of decorators. + * @param target The target object. + * @param propertyKey (Optional) The property key to decorate. + * @param attributes (Optional) The property descriptor for the target key. + * @remarks Decorators are applied in reverse order. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * Example = Reflect.decorate(decoratorsArray, Example); + * + * // property (on constructor) + * Reflect.decorate(decoratorsArray, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.decorate(decoratorsArray, Example.prototype, "property"); + * + * // method (on constructor) + * Object.defineProperty(Example, "staticMethod", + * Reflect.decorate(decoratorsArray, Example, "staticMethod", + * Object.getOwnPropertyDescriptor(Example, "staticMethod"))); + * + * // method (on prototype) + * Object.defineProperty(Example.prototype, "method", + * Reflect.decorate(decoratorsArray, Example.prototype, "method", + * Object.getOwnPropertyDescriptor(Example.prototype, "method"))); + * + */ + function decorate(decorators: (ClassDecorator | MemberDecorator)[], target: any, propertyKey?: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | Function | undefined { + if (!IsUndefined(propertyKey)) { + if (!IsArray(decorators)) throw new TypeError(); + if (!IsObject(target)) throw new TypeError(); + if (!IsObject(attributes) && !IsUndefined(attributes) && !IsNull(attributes)) throw new TypeError(); + if (IsNull(attributes)) attributes = undefined; + propertyKey = ToPropertyKey(propertyKey); + return DecorateProperty(decorators, target, propertyKey, attributes); + } + else { + if (!IsArray(decorators)) throw new TypeError(); + if (!IsConstructor(target)) throw new TypeError(); + return DecorateConstructor(decorators, target); + } + } + + exporter("decorate", decorate); + + // 4.1.2 Reflect.metadata(metadataKey, metadataValue) + // https://rbuckton.github.io/reflect-metadata/#reflect.metadata + + /** + * A default metadata decorator factory that can be used on a class, class member, or parameter. + * @param metadataKey The key for the metadata entry. + * @param metadataValue The value for the metadata entry. + * @returns A decorator function. + * @remarks + * If `metadataKey` is already defined for the target and target key, the + * metadataValue for that key will be overwritten. + * @example + * + * // constructor + * @Reflect.metadata(key, value) + * class Example { + * } + * + * // property (on constructor, TypeScript only) + * class Example { + * @Reflect.metadata(key, value) + * static staticProperty; + * } + * + * // property (on prototype, TypeScript only) + * class Example { + * @Reflect.metadata(key, value) + * property; + * } + * + * // method (on constructor) + * class Example { + * @Reflect.metadata(key, value) + * static staticMethod() { } + * } + * + * // method (on prototype) + * class Example { + * @Reflect.metadata(key, value) + * method() { } + * } + * + */ + function metadata(metadataKey: any, metadataValue: any) { + function decorator(target: Function): void; + function decorator(target: any, propertyKey: string | symbol): void; + function decorator(target: any, propertyKey?: string | symbol): void { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey) && !IsPropertyKey(propertyKey)) throw new TypeError(); + OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey); + } + return decorator; + } + + exporter("metadata", metadata); + + // 4.1.3 Reflect.defineMetadata(metadataKey, metadataValue, target [, propertyKey]) + // https://rbuckton.github.io/reflect-metadata/#reflect.definemetadata + + function defineMetadata(metadataKey: any, metadataValue: any, target: any): void; + function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey: string | symbol): void; + + /** + * Define a unique metadata entry on the target. + * @param metadataKey A key used to store and retrieve metadata. + * @param metadataValue A value that contains attached metadata. + * @param target The target object on which to define metadata. + * @param propertyKey (Optional) The property key for the target. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * Reflect.defineMetadata("custom:annotation", options, Example); + * + * // property (on constructor) + * Reflect.defineMetadata("custom:annotation", options, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.defineMetadata("custom:annotation", options, Example.prototype, "property"); + * + * // method (on constructor) + * Reflect.defineMetadata("custom:annotation", options, Example, "staticMethod"); + * + * // method (on prototype) + * Reflect.defineMetadata("custom:annotation", options, Example.prototype, "method"); + * + * // decorator factory as metadata-producing annotation. + * function MyAnnotation(options): Decorator { + * return (target, key?) => Reflect.defineMetadata("custom:annotation", options, target, key); + * } + * + */ + function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey?: string | symbol): void { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey); + } + + exporter("defineMetadata", defineMetadata); + + // 4.1.4 Reflect.hasMetadata(metadataKey, target [, propertyKey]) + // https://rbuckton.github.io/reflect-metadata/#reflect.hasmetadata + + function hasMetadata(metadataKey: any, target: any): boolean; + function hasMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; + + /** + * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.hasMetadata("custom:annotation", Example); + * + * // property (on constructor) + * result = Reflect.hasMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.hasMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "method"); + * + */ + function hasMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryHasMetadata(metadataKey, target, propertyKey); + } + + exporter("hasMetadata", hasMetadata); + + // 4.1.5 Reflect.hasOwnMetadata(metadataKey, target [, propertyKey]) + // https://rbuckton.github.io/reflect-metadata/#reflect-hasownmetadata + + function hasOwnMetadata(metadataKey: any, target: any): boolean; + function hasOwnMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; + + /** + * Gets a value indicating whether the target object has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.hasOwnMetadata("custom:annotation", Example); + * + * // property (on constructor) + * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "method"); + * + */ + function hasOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryHasOwnMetadata(metadataKey, target, propertyKey); + } + + exporter("hasOwnMetadata", hasOwnMetadata); + + // 4.1.6 Reflect.getMetadata(metadataKey, target [, propertyKey]) + // https://rbuckton.github.io/reflect-metadata/#reflect-getmetadata + + function getMetadata(metadataKey: any, target: any): any; + function getMetadata(metadataKey: any, target: any, propertyKey: string | symbol): any; + + /** + * Gets the metadata value for the provided metadata key on the target object or its prototype chain. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.getMetadata("custom:annotation", Example); + * + * // property (on constructor) + * result = Reflect.getMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getMetadata("custom:annotation", Example.prototype, "method"); + * + */ + function getMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryGetMetadata(metadataKey, target, propertyKey); + } + + exporter("getMetadata", getMetadata); + + // 4.1.7 Reflect.getOwnMetadata(metadataKey, target [, propertyKey]) + // https://rbuckton.github.io/reflect-metadata/#reflect-getownmetadata + + function getOwnMetadata(metadataKey: any, target: any): any; + function getOwnMetadata(metadataKey: any, target: any, propertyKey: string | symbol): any; + + /** + * Gets the metadata value for the provided metadata key on the target object. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.getOwnMetadata("custom:annotation", Example); + * + * // property (on constructor) + * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "method"); + * + */ + function getOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryGetOwnMetadata(metadataKey, target, propertyKey); + } + + exporter("getOwnMetadata", getOwnMetadata); + + // 4.1.8 Reflect.getMetadataKeys(target [, propertyKey]) + // https://rbuckton.github.io/reflect-metadata/#reflect-getmetadatakeys + + function getMetadataKeys(target: any): any[]; + function getMetadataKeys(target: any, propertyKey: string | symbol): any[]; + + /** + * Gets the metadata keys defined on the target object or its prototype chain. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.getMetadataKeys(Example); + * + * // property (on constructor) + * result = Reflect.getMetadataKeys(Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getMetadataKeys(Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getMetadataKeys(Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getMetadataKeys(Example.prototype, "method"); + * + */ + function getMetadataKeys(target: any, propertyKey?: string | symbol): any[] { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryMetadataKeys(target, propertyKey); + } + + exporter("getMetadataKeys", getMetadataKeys); + + // 4.1.9 Reflect.getOwnMetadataKeys(target [, propertyKey]) + // https://rbuckton.github.io/reflect-metadata/#reflect-getownmetadata + + function getOwnMetadataKeys(target: any): any[]; + function getOwnMetadataKeys(target: any, propertyKey: string | symbol): any[]; + + /** + * Gets the unique metadata keys defined on the target object. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.getOwnMetadataKeys(Example); + * + * // property (on constructor) + * result = Reflect.getOwnMetadataKeys(Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getOwnMetadataKeys(Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getOwnMetadataKeys(Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getOwnMetadataKeys(Example.prototype, "method"); + * + */ + function getOwnMetadataKeys(target: any, propertyKey?: string | symbol): any[] { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryOwnMetadataKeys(target, propertyKey); + } + + exporter("getOwnMetadataKeys", getOwnMetadataKeys); + + // 4.1.10 Reflect.deleteMetadata(metadataKey, target [, propertyKey]) + // https://rbuckton.github.io/reflect-metadata/#reflect-deletemetadata + + function deleteMetadata(metadataKey: any, target: any): boolean; + function deleteMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; + + /** + * Deletes the metadata entry from the target object with the provided key. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns `true` if the metadata entry was found and deleted; otherwise, false. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.deleteMetadata("custom:annotation", Example); + * + * // property (on constructor) + * result = Reflect.deleteMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.deleteMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "method"); + * + */ + function deleteMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + const metadataMap = GetOrCreateMetadataMap(target, propertyKey, /*Create*/ false); + if (IsUndefined(metadataMap)) return false; + if (!metadataMap.delete(metadataKey)) return false; + if (metadataMap.size > 0) return true; + const targetMetadata = Metadata.get(target); + targetMetadata.delete(propertyKey); + if (targetMetadata.size > 0) return true; + Metadata.delete(target); + return true; + } + + exporter("deleteMetadata", deleteMetadata); + + function DecorateConstructor(decorators: ClassDecorator[], target: Function): Function { + for (let i = decorators.length - 1; i >= 0; --i) { + const decorator = decorators[i]; + const decorated = decorator(target); + if (!IsUndefined(decorated) && !IsNull(decorated)) { + if (!IsConstructor(decorated)) throw new TypeError(); + target = decorated; + } + } + return target; + } + + function DecorateProperty(decorators: MemberDecorator[], target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor | undefined): PropertyDescriptor | undefined { + for (let i = decorators.length - 1; i >= 0; --i) { + const decorator = decorators[i]; + const decorated = decorator(target, propertyKey, descriptor); + if (!IsUndefined(decorated) && !IsNull(decorated)) { + if (!IsObject(decorated)) throw new TypeError(); + descriptor = decorated; + } + } + return descriptor; + } + + // 2.1.1 GetOrCreateMetadataMap(O, P, Create) + // https://rbuckton.github.io/reflect-metadata/#getorcreatemetadatamap + function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: true): Map; + function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: false): Map | undefined; + function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: boolean): Map | undefined { + let targetMetadata = Metadata.get(O); + if (IsUndefined(targetMetadata)) { + if (!Create) return undefined; + targetMetadata = new _Map>(); + Metadata.set(O, targetMetadata); + } + let metadataMap = targetMetadata.get(P); + if (IsUndefined(metadataMap)) { + if (!Create) return undefined; + metadataMap = new _Map(); + targetMetadata.set(P, metadataMap); + } + return metadataMap; + } + + // 3.1.1.1 OrdinaryHasMetadata(MetadataKey, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinaryhasmetadata + function OrdinaryHasMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean { + const hasOwn = OrdinaryHasOwnMetadata(MetadataKey, O, P); + if (hasOwn) return true; + const parent = OrdinaryGetPrototypeOf(O); + if (!IsNull(parent)) return OrdinaryHasMetadata(MetadataKey, parent, P); + return false; + } + + // 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata + function OrdinaryHasOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return false; + return ToBoolean(metadataMap.has(MetadataKey)); + } + + // 3.1.3.1 OrdinaryGetMetadata(MetadataKey, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinarygetmetadata + function OrdinaryGetMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): any { + const hasOwn = OrdinaryHasOwnMetadata(MetadataKey, O, P); + if (hasOwn) return OrdinaryGetOwnMetadata(MetadataKey, O, P); + const parent = OrdinaryGetPrototypeOf(O); + if (!IsNull(parent)) return OrdinaryGetMetadata(MetadataKey, parent, P); + return undefined; + } + + // 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata + function OrdinaryGetOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): any { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return undefined; + return metadataMap.get(MetadataKey); + } + + // 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata + function OrdinaryDefineOwnMetadata(MetadataKey: any, MetadataValue: any, O: any, P: string | symbol | undefined): void { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ true); + metadataMap.set(MetadataKey, MetadataValue); + } + + // 3.1.6.1 OrdinaryMetadataKeys(O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinarymetadatakeys + function OrdinaryMetadataKeys(O: any, P: string | symbol | undefined): any[] { + const ownKeys = OrdinaryOwnMetadataKeys(O, P); + const parent = OrdinaryGetPrototypeOf(O); + if (parent === null) return ownKeys; + const parentKeys = OrdinaryMetadataKeys(parent, P); + if (parentKeys.length <= 0) return ownKeys; + if (ownKeys.length <= 0) return parentKeys; + const set = new _Set(); + const keys: any[] = []; + for (const key of ownKeys) { + const hasKey = set.has(key); + if (!hasKey) { + set.add(key); + keys.push(key); + } + } + for (const key of parentKeys) { + const hasKey = set.has(key); + if (!hasKey) { + set.add(key); + keys.push(key); + } + } + return keys; + } + + // 3.1.7.1 OrdinaryOwnMetadataKeys(O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys + function OrdinaryOwnMetadataKeys(O: any, P: string | symbol | undefined): any[] { + const keys: any[] = []; + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return keys; + const keysObj = metadataMap.keys(); + const iterator = GetIterator(keysObj); + let k = 0; + while (true) { + const next = IteratorStep(iterator); + if (!next) { + keys.length = k; + return keys; + } + const nextValue = IteratorValue(next); + try { + keys[k] = nextValue; + } + catch (e) { + try { + IteratorClose(iterator); + } + finally { + throw e; + } + } + k++; + } + } + + // 6 ECMAScript Data Typ0es and Values + // https://tc39.github.io/ecma262/#sec-ecmascript-data-types-and-values + function Type(x: any): Tag { + if (x === null) return Tag.Null; + switch (typeof x) { + case "undefined": return Tag.Undefined; + case "boolean": return Tag.Boolean; + case "string": return Tag.String; + case "symbol": return Tag.Symbol; + case "number": return Tag.Number; + case "object": return x === null ? Tag.Null : Tag.Object; + default: return Tag.Object; + } + } + + // 6.1 ECMAScript Language Types + // https://tc39.github.io/ecma262/#sec-ecmascript-language-types + const enum Tag { + Undefined, + Null, + Boolean, + String, + Symbol, + Number, + Object + } + + // 6.1.1 The Undefined Type + // https://tc39.github.io/ecma262/#sec-ecmascript-language-types-undefined-type + function IsUndefined(x: any): x is undefined { + return x === undefined; + } + + // 6.1.2 The Null Type + // https://tc39.github.io/ecma262/#sec-ecmascript-language-types-null-type + function IsNull(x: any): x is null { + return x === null; + } + + // 6.1.5 The Symbol Type + // https://tc39.github.io/ecma262/#sec-ecmascript-language-types-symbol-type + function IsSymbol(x: any): x is symbol { + return typeof x === "symbol"; + } + + // 6.1.7 The Object Type + // https://tc39.github.io/ecma262/#sec-object-type + function IsObject(x: T | undefined | null | boolean | string | symbol | number): x is T { + return typeof x === "object" ? x !== null : typeof x === "function"; + } + + // 7.1 Type Conversion + // https://tc39.github.io/ecma262/#sec-type-conversion + + // 7.1.1 ToPrimitive(input [, PreferredType]) + // https://tc39.github.io/ecma262/#sec-toprimitive + function ToPrimitive(input: any, PreferredType?: Tag): undefined | null | boolean | string | symbol | number { + switch (Type(input)) { + case Tag.Undefined: return input; + case Tag.Null: return input; + case Tag.Boolean: return input; + case Tag.String: return input; + case Tag.Symbol: return input; + case Tag.Number: return input; + } + const hint: "string" | "number" | "default" = PreferredType === Tag.String ? "string" : PreferredType === Tag.Number ? "number" : "default"; + const exoticToPrim = GetMethod(input, toPrimitiveSymbol); + if (exoticToPrim !== undefined) { + const result = exoticToPrim.call(input, hint); + if (IsObject(result)) throw new TypeError(); + return result; + } + return OrdinaryToPrimitive(input, hint === "default" ? "number" : hint); + } + + // 7.1.1.1 OrdinaryToPrimitive(O, hint) + // https://tc39.github.io/ecma262/#sec-ordinarytoprimitive + function OrdinaryToPrimitive(O: any, hint: "string" | "number"): undefined | null | boolean | string | symbol | number { + if (hint === "string") { + const toString = O.toString; + if (IsCallable(toString)) { + const result = toString.call(O); + if (!IsObject(result)) return result; + } + const valueOf = O.valueOf; + if (IsCallable(valueOf)) { + const result = valueOf.call(O); + if (!IsObject(result)) return result; + } + } + else { + const valueOf = O.valueOf; + if (IsCallable(valueOf)) { + const result = valueOf.call(O); + if (!IsObject(result)) return result; + } + const toString = O.toString; + if (IsCallable(toString)) { + const result = toString.call(O); + if (!IsObject(result)) return result; + } + } + throw new TypeError(); + } + + // 7.1.2 ToBoolean(argument) + // https://tc39.github.io/ecma262/2016/#sec-toboolean + function ToBoolean(argument: any): boolean { + return !!argument; + } + + // 7.1.12 ToString(argument) + // https://tc39.github.io/ecma262/#sec-tostring + function ToString(argument: any): string { + return "" + argument; + } + + // 7.1.14 ToPropertyKey(argument) + // https://tc39.github.io/ecma262/#sec-topropertykey + function ToPropertyKey(argument: any): string | symbol { + const key = ToPrimitive(argument, Tag.String); + if (IsSymbol(key)) return key; + return ToString(key); + } + + // 7.2 Testing and Comparison Operations + // https://tc39.github.io/ecma262/#sec-testing-and-comparison-operations + + // 7.2.2 IsArray(argument) + // https://tc39.github.io/ecma262/#sec-isarray + function IsArray(argument: any): argument is any[] { + return Array.isArray + ? Array.isArray(argument) + : argument instanceof Object + ? argument instanceof Array + : Object.prototype.toString.call(argument) === "[object Array]"; + } + + // 7.2.3 IsCallable(argument) + // https://tc39.github.io/ecma262/#sec-iscallable + function IsCallable(argument: any): argument is Function { + // NOTE: This is an approximation as we cannot check for [[Call]] internal method. + return typeof argument === "function"; + } + + // 7.2.4 IsConstructor(argument) + // https://tc39.github.io/ecma262/#sec-isconstructor + function IsConstructor(argument: any): argument is Function { + // NOTE: This is an approximation as we cannot check for [[Construct]] internal method. + return typeof argument === "function"; + } + + // 7.2.7 IsPropertyKey(argument) + // https://tc39.github.io/ecma262/#sec-ispropertykey + function IsPropertyKey(argument: any): argument is string | symbol { + switch (Type(argument)) { + case Tag.String: return true; + case Tag.Symbol: return true; + default: return false; + } + } + + // 7.3 Operations on Objects + // https://tc39.github.io/ecma262/#sec-operations-on-objects + + // 7.3.9 GetMethod(V, P) + // https://tc39.github.io/ecma262/#sec-getmethod + function GetMethod(V: any, P: any): Function | undefined { + const func = V[P]; + if (func === undefined || func === null) return undefined; + if (!IsCallable(func)) throw new TypeError(); + return func; + } + + // 7.4 Operations on Iterator Objects + // https://tc39.github.io/ecma262/#sec-operations-on-iterator-objects + + function GetIterator(obj: Iterable): Iterator { + const method = GetMethod(obj, iteratorSymbol); + if (!IsCallable(method)) throw new TypeError(); // from Call + const iterator = method.call(obj); + if (!IsObject(iterator)) throw new TypeError(); + return iterator; + } + + // 7.4.4 IteratorValue(iterResult) + // https://tc39.github.io/ecma262/2016/#sec-iteratorvalue + function IteratorValue(iterResult: __IteratorResult): T { + return iterResult.value; + } + + // 7.4.5 IteratorStep(iterator) + // https://tc39.github.io/ecma262/#sec-iteratorstep + function IteratorStep(iterator: Iterator): __IteratorResult | false { + const result = iterator.next(); + return result.done ? false : result; + } + + // 7.4.6 IteratorClose(iterator, completion) + // https://tc39.github.io/ecma262/#sec-iteratorclose + function IteratorClose(iterator: Iterator) { + const f = iterator["return"]; + if (f) f.call(iterator); + } + + // 9.1 Ordinary Object Internal Methods and Internal Slots + // https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots + + // 9.1.1.1 OrdinaryGetPrototypeOf(O) + // https://tc39.github.io/ecma262/#sec-ordinarygetprototypeof + function OrdinaryGetPrototypeOf(O: any): any { + const proto = Object.getPrototypeOf(O); + if (typeof O !== "function" || O === functionPrototype) return proto; + + // TypeScript doesn't set __proto__ in ES5, as it's non-standard. + // Try to determine the superclass constructor. Compatible implementations + // must either set __proto__ on a subclass constructor to the superclass constructor, + // or ensure each class has a valid `constructor` property on its prototype that + // points back to the constructor. + + // If this is not the same as Function.[[Prototype]], then this is definately inherited. + // This is the case when in ES6 or when using __proto__ in a compatible browser. + if (proto !== functionPrototype) return proto; + + // If the super prototype is Object.prototype, null, or undefined, then we cannot determine the heritage. + const prototype = O.prototype; + const prototypeProto = prototype && Object.getPrototypeOf(prototype); + if (prototypeProto == null || prototypeProto === Object.prototype) return proto; + + // If the constructor was not a function, then we cannot determine the heritage. + const constructor = prototypeProto.constructor; + if (typeof constructor !== "function") return proto; + + // If we have some kind of self-reference, then we cannot determine the heritage. + if (constructor === O) return proto; + + // we have a pretty good guess at the heritage. + return constructor; + } + + function fail(e: any): never { + throw e; + } + }); +} diff --git a/ReflectNoConflict.ts b/ReflectNoConflict.ts new file mode 100644 index 0000000..1010f56 --- /dev/null +++ b/ReflectNoConflict.ts @@ -0,0 +1,1368 @@ +/*! ***************************************************************************** +Copyright (C) Microsoft. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + +// Metadata Proposal +// https://rbuckton.github.io/reflect-metadata/ + +type MemberDecorator = (target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor) => PropertyDescriptor | void; + +// feature test for Symbol support +const supportsSymbol = typeof Symbol === "function"; +const toPrimitiveSymbol = supportsSymbol && typeof Symbol.toPrimitive !== "undefined" ? Symbol.toPrimitive : fail("Symbol.toPrimitive not found."); +const iteratorSymbol = supportsSymbol && typeof Symbol.iterator !== "undefined" ? Symbol.iterator : fail("Symbol.iterator not found."); + +// Load global or shim versions of Map, Set, and WeakMap +const functionPrototype = Object.getPrototypeOf(Function); +const _Map: typeof Map = typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : fail("A valid Map constructor could not be found."); +const _Set: typeof Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : fail("A valid Set constructor could not be found."); +const _WeakMap: typeof WeakMap = typeof WeakMap === "function" ? WeakMap : fail("A valid WeakMap constructor could not be found."); + +// [[Metadata]] internal slot +// https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots +const Metadata = new _WeakMap>>(); + +/** + * Applies a set of decorators to a target object. + * @param decorators An array of decorators. + * @param target The target object. + * @returns The result of applying the provided decorators. + * @remarks Decorators are applied in reverse order of their positions in the array. + * @example + * + * class Example { } + * + * // constructor + * Example = Reflect.decorate(decoratorsArray, Example); + * + */ +export function decorate(decorators: ClassDecorator[], target: Function): Function; + +/** + * Applies a set of decorators to a property of a target object. + * @param decorators An array of decorators. + * @param target The target object. + * @param propertyKey The property key to decorate. + * @param attributes A property descriptor. + * @remarks Decorators are applied in reverse order. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod() { } + * method() { } + * } + * + * // property (on constructor) + * Reflect.decorate(decoratorsArray, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.decorate(decoratorsArray, Example.prototype, "property"); + * + * // method (on constructor) + * Object.defineProperty(Example, "staticMethod", + * Reflect.decorate(decoratorsArray, Example, "staticMethod", + * Object.getOwnPropertyDescriptor(Example, "staticMethod"))); + * + * // method (on prototype) + * Object.defineProperty(Example.prototype, "method", + * Reflect.decorate(decoratorsArray, Example.prototype, "method", + * Object.getOwnPropertyDescriptor(Example.prototype, "method"))); + * + */ +export function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined; + +/** + * Applies a set of decorators to a property of a target object. + * @param decorators An array of decorators. + * @param target The target object. + * @param propertyKey The property key to decorate. + * @param attributes A property descriptor. + * @remarks Decorators are applied in reverse order. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod() { } + * method() { } + * } + * + * // property (on constructor) + * Reflect.decorate(decoratorsArray, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.decorate(decoratorsArray, Example.prototype, "property"); + * + * // method (on constructor) + * Object.defineProperty(Example, "staticMethod", + * Reflect.decorate(decoratorsArray, Example, "staticMethod", + * Object.getOwnPropertyDescriptor(Example, "staticMethod"))); + * + * // method (on prototype) + * Object.defineProperty(Example.prototype, "method", + * Reflect.decorate(decoratorsArray, Example.prototype, "method", + * Object.getOwnPropertyDescriptor(Example.prototype, "method"))); + * + */ +export function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes: PropertyDescriptor): PropertyDescriptor; + +/** + * Applies a set of decorators to a property of a target object. + * @param decorators An array of decorators. + * @param target The target object. + * @param propertyKey (Optional) The property key to decorate. + * @param attributes (Optional) The property descriptor for the target key. + * @remarks Decorators are applied in reverse order. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * Example = Reflect.decorate(decoratorsArray, Example); + * + * // property (on constructor) + * Reflect.decorate(decoratorsArray, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.decorate(decoratorsArray, Example.prototype, "property"); + * + * // method (on constructor) + * Object.defineProperty(Example, "staticMethod", + * Reflect.decorate(decoratorsArray, Example, "staticMethod", + * Object.getOwnPropertyDescriptor(Example, "staticMethod"))); + * + * // method (on prototype) + * Object.defineProperty(Example.prototype, "method", + * Reflect.decorate(decoratorsArray, Example.prototype, "method", + * Object.getOwnPropertyDescriptor(Example.prototype, "method"))); + * + */ +export function decorate(decorators: (ClassDecorator | MemberDecorator)[], target: any, propertyKey?: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | Function | undefined { + if (!IsUndefined(propertyKey)) { + if (!IsArray(decorators)) throw new TypeError(); + if (!IsObject(target)) throw new TypeError(); + if (!IsObject(attributes) && !IsUndefined(attributes) && !IsNull(attributes)) throw new TypeError(); + if (IsNull(attributes)) attributes = undefined; + propertyKey = ToPropertyKey(propertyKey); + return DecorateProperty(decorators, target, propertyKey, attributes); + } + else { + if (!IsArray(decorators)) throw new TypeError(); + if (!IsConstructor(target)) throw new TypeError(); + return DecorateConstructor(decorators, target); + } +} + +// 4.1.2 Reflect.metadata(metadataKey, metadataValue) +// https://rbuckton.github.io/reflect-metadata/#reflect.metadata + +/** + * A default metadata decorator factory that can be used on a class, class member, or parameter. + * @param metadataKey The key for the metadata entry. + * @param metadataValue The value for the metadata entry. + * @returns A decorator function. + * @remarks + * If `metadataKey` is already defined for the target and target key, the + * metadataValue for that key will be overwritten. + * @example + * + * // constructor + * @Reflect.metadata(key, value) + * class Example { + * } + * + * // property (on constructor, TypeScript only) + * class Example { + * @Reflect.metadata(key, value) + * static staticProperty; + * } + * + * // property (on prototype, TypeScript only) + * class Example { + * @Reflect.metadata(key, value) + * property; + * } + * + * // method (on constructor) + * class Example { + * @Reflect.metadata(key, value) + * static staticMethod() { } + * } + * + * // method (on prototype) + * class Example { + * @Reflect.metadata(key, value) + * method() { } + * } + * + */ +export function metadata(metadataKey: any, metadataValue: any): { (target: Function): void; (target: any, propertyKey: string | symbol): void; } { + function decorator(target: Function): void; + function decorator(target: any, propertyKey: string | symbol): void; + function decorator(target: any, propertyKey?: string | symbol): void { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey) && !IsPropertyKey(propertyKey)) throw new TypeError(); + OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey); + } + return decorator; +} + +// 4.1.3 Reflect.defineMetadata(metadataKey, metadataValue, target [, propertyKey]) +// https://rbuckton.github.io/reflect-metadata/#reflect.definemetadata + +/** + * Define a unique metadata entry on the target. + * @param metadataKey A key used to store and retrieve metadata. + * @param metadataValue A value that contains attached metadata. + * @param target The target object on which to define metadata. + * @example + * + * class Example { + * } + * + * // constructor + * Reflect.defineMetadata("custom:annotation", options, Example); + * + * // decorator factory as metadata-producing annotation. + * function MyAnnotation(options): ClassDecorator { + * return target => Reflect.defineMetadata("custom:annotation", options, target); + * } + * + */ +export function defineMetadata(metadataKey: any, metadataValue: any, target: any): void; + +/** + * Define a unique metadata entry on the target. + * @param metadataKey A key used to store and retrieve metadata. + * @param metadataValue A value that contains attached metadata. + * @param target The target object on which to define metadata. + * @param propertyKey The property key for the target. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * Reflect.defineMetadata("custom:annotation", Number, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.defineMetadata("custom:annotation", Number, Example.prototype, "property"); + * + * // method (on constructor) + * Reflect.defineMetadata("custom:annotation", Number, Example, "staticMethod"); + * + * // method (on prototype) + * Reflect.defineMetadata("custom:annotation", Number, Example.prototype, "method"); + * + * // decorator factory as metadata-producing annotation. + * function MyAnnotation(options): PropertyDecorator { + * return (target, key) => Reflect.defineMetadata("custom:annotation", options, target, key); + * } + * + */ +export function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey: string | symbol): void; + +/** + * Define a unique metadata entry on the target. + * @param metadataKey A key used to store and retrieve metadata. + * @param metadataValue A value that contains attached metadata. + * @param target The target object on which to define metadata. + * @param propertyKey (Optional) The property key for the target. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * Reflect.defineMetadata("custom:annotation", options, Example); + * + * // property (on constructor) + * Reflect.defineMetadata("custom:annotation", options, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.defineMetadata("custom:annotation", options, Example.prototype, "property"); + * + * // method (on constructor) + * Reflect.defineMetadata("custom:annotation", options, Example, "staticMethod"); + * + * // method (on prototype) + * Reflect.defineMetadata("custom:annotation", options, Example.prototype, "method"); + * + * // decorator factory as metadata-producing annotation. + * function MyAnnotation(options): Decorator { + * return (target, key?) => Reflect.defineMetadata("custom:annotation", options, target, key); + * } + * + */ +export function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey?: string | symbol): void { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey); +} + +// 4.1.4 Reflect.hasMetadata(metadataKey, target [, propertyKey]) +// https://rbuckton.github.io/reflect-metadata/#reflect.hasmetadata + +/** + * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.hasMetadata("custom:annotation", Example); + * + */ +export function hasMetadata(metadataKey: any, target: any): boolean; + +/** + * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.hasMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.hasMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export function hasMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; + +/** + * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.hasMetadata("custom:annotation", Example); + * + * // property (on constructor) + * result = Reflect.hasMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.hasMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export function hasMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryHasMetadata(metadataKey, target, propertyKey); +} + +// 4.1.5 Reflect.hasOwnMetadata(metadataKey, target [, propertyKey]) +// https://rbuckton.github.io/reflect-metadata/#reflect-hasownmetadata + +/** + * Gets a value indicating whether the target object has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.hasOwnMetadata("custom:annotation", Example); + * + */ +export function hasOwnMetadata(metadataKey: any, target: any): boolean; + +/** + * Gets a value indicating whether the target object has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export function hasOwnMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; + +/** + * Gets a value indicating whether the target object has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.hasOwnMetadata("custom:annotation", Example); + * + * // property (on constructor) + * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export function hasOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryHasOwnMetadata(metadataKey, target, propertyKey); +} + +// 4.1.6 Reflect.getMetadata(metadataKey, target [, propertyKey]) +// https://rbuckton.github.io/reflect-metadata/#reflect-getmetadata + +/** + * Gets the metadata value for the provided metadata key on the target object or its prototype chain. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getMetadata("custom:annotation", Example); + * + */ +export function getMetadata(metadataKey: any, target: any): any; + +/** + * Gets the metadata value for the provided metadata key on the target object or its prototype chain. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export function getMetadata(metadataKey: any, target: any, propertyKey: string | symbol): any; + +/** + * Gets the metadata value for the provided metadata key on the target object or its prototype chain. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.getMetadata("custom:annotation", Example); + * + * // property (on constructor) + * result = Reflect.getMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export function getMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryGetMetadata(metadataKey, target, propertyKey); +} + +// 4.1.7 Reflect.getOwnMetadata(metadataKey, target [, propertyKey]) +// https://rbuckton.github.io/reflect-metadata/#reflect-getownmetadata + +/** + * Gets the metadata value for the provided metadata key on the target object. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getOwnMetadata("custom:annotation", Example); + * + */ +export function getOwnMetadata(metadataKey: any, target: any): any; + +/** + * Gets the metadata value for the provided metadata key on the target object. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export function getOwnMetadata(metadataKey: any, target: any, propertyKey: string | symbol): any; + +/** + * Gets the metadata value for the provided metadata key on the target object. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.getOwnMetadata("custom:annotation", Example); + * + * // property (on constructor) + * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export function getOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryGetOwnMetadata(metadataKey, target, propertyKey); +} + +// 4.1.8 Reflect.getMetadataKeys(target [, propertyKey]) +// https://rbuckton.github.io/reflect-metadata/#reflect-getmetadatakeys + +/** + * Gets the metadata keys defined on the target object or its prototype chain. + * @param target The target object on which the metadata is defined. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getMetadataKeys(Example); + * + */ +export function getMetadataKeys(target: any): any[]; + +/** + * Gets the metadata keys defined on the target object or its prototype chain. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getMetadataKeys(Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getMetadataKeys(Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getMetadataKeys(Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getMetadataKeys(Example.prototype, "method"); + * + */ +export function getMetadataKeys(target: any, propertyKey: string | symbol): any[]; + +/** + * Gets the metadata keys defined on the target object or its prototype chain. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.getMetadataKeys(Example); + * + * // property (on constructor) + * result = Reflect.getMetadataKeys(Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getMetadataKeys(Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getMetadataKeys(Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getMetadataKeys(Example.prototype, "method"); + * + */ +export function getMetadataKeys(target: any, propertyKey?: string | symbol): any[] { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryMetadataKeys(target, propertyKey); +} + +// 4.1.9 Reflect.getOwnMetadataKeys(target [, propertyKey]) +// https://rbuckton.github.io/reflect-metadata/#reflect-getownmetadata + +/** + * Gets the unique metadata keys defined on the target object. + * @param target The target object on which the metadata is defined. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getOwnMetadataKeys(Example); + * + */ +export function getOwnMetadataKeys(target: any): any[]; + +/** + * Gets the unique metadata keys defined on the target object. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getOwnMetadataKeys(Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getOwnMetadataKeys(Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getOwnMetadataKeys(Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getOwnMetadataKeys(Example.prototype, "method"); + * + */ +export function getOwnMetadataKeys(target: any, propertyKey: string | symbol): any[]; + +/** + * Gets the unique metadata keys defined on the target object. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.getOwnMetadataKeys(Example); + * + * // property (on constructor) + * result = Reflect.getOwnMetadataKeys(Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getOwnMetadataKeys(Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getOwnMetadataKeys(Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getOwnMetadataKeys(Example.prototype, "method"); + * + */ +export function getOwnMetadataKeys(target: any, propertyKey?: string | symbol): any[] { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + return OrdinaryOwnMetadataKeys(target, propertyKey); +} + +// 4.1.10 Reflect.deleteMetadata(metadataKey, target [, propertyKey]) +// https://rbuckton.github.io/reflect-metadata/#reflect-deletemetadata + +/** + * Deletes the metadata entry from the target object with the provided key. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns `true` if the metadata entry was found and deleted; otherwise, false. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.deleteMetadata("custom:annotation", Example); + * + */ +export function deleteMetadata(metadataKey: any, target: any): boolean; + +/** + * Deletes the metadata entry from the target object with the provided key. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns `true` if the metadata entry was found and deleted; otherwise, false. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.deleteMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.deleteMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export function deleteMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; + +/** + * Deletes the metadata entry from the target object with the provided key. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey (Optional) The property key for the target. + * @returns `true` if the metadata entry was found and deleted; otherwise, false. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * constructor(p) { } + * static staticMethod(p) { } + * method(p) { } + * } + * + * // constructor + * result = Reflect.deleteMetadata("custom:annotation", Example); + * + * // property (on constructor) + * result = Reflect.deleteMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.deleteMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export function deleteMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + const metadataMap = GetOrCreateMetadataMap(target, propertyKey, /*Create*/ false); + if (IsUndefined(metadataMap)) return false; + if (!metadataMap.delete(metadataKey)) return false; + if (metadataMap.size > 0) return true; + const targetMetadata = Metadata.get(target); + targetMetadata.delete(propertyKey); + if (targetMetadata.size > 0) return true; + Metadata.delete(target); + return true; +} + +function DecorateConstructor(decorators: ClassDecorator[], target: Function): Function { + for (let i = decorators.length - 1; i >= 0; --i) { + const decorator = decorators[i]; + const decorated = decorator(target); + if (!IsUndefined(decorated) && !IsNull(decorated)) { + if (!IsConstructor(decorated)) throw new TypeError(); + target = decorated; + } + } + return target; +} + +function DecorateProperty(decorators: MemberDecorator[], target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor | undefined): PropertyDescriptor | undefined { + for (let i = decorators.length - 1; i >= 0; --i) { + const decorator = decorators[i]; + const decorated = decorator(target, propertyKey, descriptor); + if (!IsUndefined(decorated) && !IsNull(decorated)) { + if (!IsObject(decorated)) throw new TypeError(); + descriptor = decorated; + } + } + return descriptor; +} + +// 2.1.1 GetOrCreateMetadataMap(O, P, Create) +// https://rbuckton.github.io/reflect-metadata/#getorcreatemetadatamap +function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: true): Map; +function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: false): Map | undefined; +function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: boolean): Map | undefined { + let targetMetadata = Metadata.get(O); + if (IsUndefined(targetMetadata)) { + if (!Create) return undefined; + targetMetadata = new _Map>(); + Metadata.set(O, targetMetadata); + } + let metadataMap = targetMetadata.get(P); + if (IsUndefined(metadataMap)) { + if (!Create) return undefined; + metadataMap = new _Map(); + targetMetadata.set(P, metadataMap); + } + return metadataMap; +} + +// 3.1.1.1 OrdinaryHasMetadata(MetadataKey, O, P) +// https://rbuckton.github.io/reflect-metadata/#ordinaryhasmetadata +function OrdinaryHasMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean { + const hasOwn = OrdinaryHasOwnMetadata(MetadataKey, O, P); + if (hasOwn) return true; + const parent = OrdinaryGetPrototypeOf(O); + if (!IsNull(parent)) return OrdinaryHasMetadata(MetadataKey, parent, P); + return false; +} + +// 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P) +// https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata +function OrdinaryHasOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return false; + return ToBoolean(metadataMap.has(MetadataKey)); +} + +// 3.1.3.1 OrdinaryGetMetadata(MetadataKey, O, P) +// https://rbuckton.github.io/reflect-metadata/#ordinarygetmetadata +function OrdinaryGetMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): any { + const hasOwn = OrdinaryHasOwnMetadata(MetadataKey, O, P); + if (hasOwn) return OrdinaryGetOwnMetadata(MetadataKey, O, P); + const parent = OrdinaryGetPrototypeOf(O); + if (!IsNull(parent)) return OrdinaryGetMetadata(MetadataKey, parent, P); + return undefined; +} + +// 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P) +// https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata +function OrdinaryGetOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): any { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return undefined; + return metadataMap.get(MetadataKey); +} + +// 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) +// https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata +function OrdinaryDefineOwnMetadata(MetadataKey: any, MetadataValue: any, O: any, P: string | symbol | undefined): void { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ true); + metadataMap.set(MetadataKey, MetadataValue); +} + +// 3.1.6.1 OrdinaryMetadataKeys(O, P) +// https://rbuckton.github.io/reflect-metadata/#ordinarymetadatakeys +function OrdinaryMetadataKeys(O: any, P: string | symbol | undefined): any[] { + const ownKeys = OrdinaryOwnMetadataKeys(O, P); + const parent = OrdinaryGetPrototypeOf(O); + if (parent === null) return ownKeys; + const parentKeys = OrdinaryMetadataKeys(parent, P); + if (parentKeys.length <= 0) return ownKeys; + if (ownKeys.length <= 0) return parentKeys; + const set = new _Set(); + const keys: any[] = []; + for (const key of ownKeys) { + const hasKey = set.has(key); + if (!hasKey) { + set.add(key); + keys.push(key); + } + } + for (const key of parentKeys) { + const hasKey = set.has(key); + if (!hasKey) { + set.add(key); + keys.push(key); + } + } + return keys; +} + +// 3.1.7.1 OrdinaryOwnMetadataKeys(O, P) +// https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys +function OrdinaryOwnMetadataKeys(O: any, P: string | symbol | undefined): any[] { + const keys: any[] = []; + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return keys; + const keysObj = metadataMap.keys(); + const iterator = GetIterator(keysObj); + let k = 0; + while (true) { + const next = IteratorStep(iterator); + if (!next) { + keys.length = k; + return keys; + } + const nextValue = IteratorValue(next); + try { + keys[k] = nextValue; + } + catch (e) { + try { + IteratorClose(iterator); + } + finally { + throw e; + } + } + k++; + } +} + +// 6 ECMAScript Data Typ0es and Values +// https://tc39.github.io/ecma262/#sec-ecmascript-data-types-and-values +function Type(x: any): Tag { + if (x === null) return Tag.Null; + switch (typeof x) { + case "undefined": return Tag.Undefined; + case "boolean": return Tag.Boolean; + case "string": return Tag.String; + case "symbol": return Tag.Symbol; + case "number": return Tag.Number; + case "object": return x === null ? Tag.Null : Tag.Object; + default: return Tag.Object; + } +} + +// 6.1 ECMAScript Language Types +// https://tc39.github.io/ecma262/#sec-ecmascript-language-types +const enum Tag { + Undefined, + Null, + Boolean, + String, + Symbol, + Number, + Object +} + +// 6.1.1 The Undefined Type +// https://tc39.github.io/ecma262/#sec-ecmascript-language-types-undefined-type +function IsUndefined(x: any): x is undefined { + return x === undefined; +} + +// 6.1.2 The Null Type +// https://tc39.github.io/ecma262/#sec-ecmascript-language-types-null-type +function IsNull(x: any): x is null { + return x === null; +} + +// 6.1.5 The Symbol Type +// https://tc39.github.io/ecma262/#sec-ecmascript-language-types-symbol-type +function IsSymbol(x: any): x is symbol { + return typeof x === "symbol"; +} + +// 6.1.7 The Object Type +// https://tc39.github.io/ecma262/#sec-object-type +function IsObject(x: T | undefined | null | boolean | string | symbol | number): x is T { + return typeof x === "object" ? x !== null : typeof x === "function"; +} + +// 7.1 Type Conversion +// https://tc39.github.io/ecma262/#sec-type-conversion + +// 7.1.1 ToPrimitive(input [, PreferredType]) +// https://tc39.github.io/ecma262/#sec-toprimitive +function ToPrimitive(input: any, PreferredType?: Tag): undefined | null | boolean | string | symbol | number { + switch (Type(input)) { + case Tag.Undefined: return input; + case Tag.Null: return input; + case Tag.Boolean: return input; + case Tag.String: return input; + case Tag.Symbol: return input; + case Tag.Number: return input; + } + const hint: "string" | "number" | "default" = PreferredType === Tag.String ? "string" : PreferredType === Tag.Number ? "number" : "default"; + const exoticToPrim = GetMethod(input, toPrimitiveSymbol); + if (exoticToPrim !== undefined) { + const result = exoticToPrim.call(input, hint); + if (IsObject(result)) throw new TypeError(); + return result; + } + return OrdinaryToPrimitive(input, hint === "default" ? "number" : hint); +} + +// 7.1.1.1 OrdinaryToPrimitive(O, hint) +// https://tc39.github.io/ecma262/#sec-ordinarytoprimitive +function OrdinaryToPrimitive(O: any, hint: "string" | "number"): undefined | null | boolean | string | symbol | number { + if (hint === "string") { + const toString = O.toString; + if (IsCallable(toString)) { + const result = toString.call(O); + if (!IsObject(result)) return result; + } + const valueOf = O.valueOf; + if (IsCallable(valueOf)) { + const result = valueOf.call(O); + if (!IsObject(result)) return result; + } + } + else { + const valueOf = O.valueOf; + if (IsCallable(valueOf)) { + const result = valueOf.call(O); + if (!IsObject(result)) return result; + } + const toString = O.toString; + if (IsCallable(toString)) { + const result = toString.call(O); + if (!IsObject(result)) return result; + } + } + throw new TypeError(); +} + +// 7.1.2 ToBoolean(argument) +// https://tc39.github.io/ecma262/2016/#sec-toboolean +function ToBoolean(argument: any): boolean { + return !!argument; +} + +// 7.1.12 ToString(argument) +// https://tc39.github.io/ecma262/#sec-tostring +function ToString(argument: any): string { + return "" + argument; +} + +// 7.1.14 ToPropertyKey(argument) +// https://tc39.github.io/ecma262/#sec-topropertykey +function ToPropertyKey(argument: any): string | symbol { + const key = ToPrimitive(argument, Tag.String); + if (IsSymbol(key)) return key; + return ToString(key); +} + +// 7.2 Testing and Comparison Operations +// https://tc39.github.io/ecma262/#sec-testing-and-comparison-operations + +// 7.2.2 IsArray(argument) +// https://tc39.github.io/ecma262/#sec-isarray +function IsArray(argument: any): argument is any[] { + return Array.isArray + ? Array.isArray(argument) + : argument instanceof Object + ? argument instanceof Array + : Object.prototype.toString.call(argument) === "[object Array]"; +} + +// 7.2.3 IsCallable(argument) +// https://tc39.github.io/ecma262/#sec-iscallable +function IsCallable(argument: any): argument is Function { + // NOTE: This is an approximation as we cannot check for [[Call]] internal method. + return typeof argument === "function"; +} + +// 7.2.4 IsConstructor(argument) +// https://tc39.github.io/ecma262/#sec-isconstructor +function IsConstructor(argument: any): argument is Function { + // NOTE: This is an approximation as we cannot check for [[Construct]] internal method. + return typeof argument === "function"; +} + +// 7.2.7 IsPropertyKey(argument) +// https://tc39.github.io/ecma262/#sec-ispropertykey +function IsPropertyKey(argument: any): argument is string | symbol { + switch (Type(argument)) { + case Tag.String: return true; + case Tag.Symbol: return true; + default: return false; + } +} + +// 7.3 Operations on Objects +// https://tc39.github.io/ecma262/#sec-operations-on-objects + +// 7.3.9 GetMethod(V, P) +// https://tc39.github.io/ecma262/#sec-getmethod +function GetMethod(V: any, P: any): Function | undefined { + const func = V[P]; + if (func === undefined || func === null) return undefined; + if (!IsCallable(func)) throw new TypeError(); + return func; +} + +// 7.4 Operations on Iterator Objects +// https://tc39.github.io/ecma262/#sec-operations-on-iterator-objects + +function GetIterator(obj: Iterable): Iterator { + const method = GetMethod(obj, iteratorSymbol); + if (!IsCallable(method)) throw new TypeError(); // from Call + const iterator = method.call(obj); + if (!IsObject(iterator)) throw new TypeError(); + return iterator; +} + +// 7.4.4 IteratorValue(iterResult) +// https://tc39.github.io/ecma262/2016/#sec-iteratorvalue +function IteratorValue(iterResult: __IteratorResult): T { + return iterResult.value; +} + +// 7.4.5 IteratorStep(iterator) +// https://tc39.github.io/ecma262/#sec-iteratorstep +function IteratorStep(iterator: Iterator): __IteratorResult | false { + const result = iterator.next(); + return result.done ? false : result; +} + +// 7.4.6 IteratorClose(iterator, completion) +// https://tc39.github.io/ecma262/#sec-iteratorclose +function IteratorClose(iterator: Iterator) { + const f = iterator["return"]; + if (f) f.call(iterator); +} + +// 9.1 Ordinary Object Internal Methods and Internal Slots +// https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots + +// 9.1.1.1 OrdinaryGetPrototypeOf(O) +// https://tc39.github.io/ecma262/#sec-ordinarygetprototypeof +function OrdinaryGetPrototypeOf(O: any): any { + const proto = Object.getPrototypeOf(O); + if (typeof O !== "function" || O === functionPrototype) return proto; + + // TypeScript doesn't set __proto__ in ES5, as it's non-standard. + // Try to determine the superclass constructor. Compatible implementations + // must either set __proto__ on a subclass constructor to the superclass constructor, + // or ensure each class has a valid `constructor` property on its prototype that + // points back to the constructor. + + // If this is not the same as Function.[[Prototype]], then this is definately inherited. + // This is the case when in ES6 or when using __proto__ in a compatible browser. + if (proto !== functionPrototype) return proto; + + // If the super prototype is Object.prototype, null, or undefined, then we cannot determine the heritage. + const prototype = O.prototype; + const prototypeProto = prototype && Object.getPrototypeOf(prototype); + if (prototypeProto == null || prototypeProto === Object.prototype) return proto; + + // If the constructor was not a function, then we cannot determine the heritage. + const constructor = prototypeProto.constructor; + if (typeof constructor !== "function") return proto; + + // If we have some kind of self-reference, then we cannot determine the heritage. + if (constructor === O) return proto; + + // we have a pretty good guess at the heritage. + return constructor; +} + +function fail(e: any): never { + throw e; +} diff --git a/bower.json b/bower.json deleted file mode 100644 index 04a6b1b..0000000 --- a/bower.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "reflect-metadata", - "version": "0.1.12", - "description": "Polyfill for Metadata Reflection API", - "homepage": "https://github.com/rbuckton/reflect-metadata", - "authors": [ - "Ron Buckton " - ], - "main": "Reflect.js", - "types": "index.d.ts", - "moduleType": [ - "globals", - "node" - ], - "keywords": [ - "decorator", - "metadata", - "javascript", - "reflect" - ], - "license": "Apache-2.0", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ], - "devDependencies": { - "typescript": "^2.1.4" - }, - "repository": { - "type": "git", - "url": "https://github.com/rbuckton/reflect-metadata.git" - } -} diff --git a/globals.d.ts b/globals.d.ts new file mode 100644 index 0000000..403f574 --- /dev/null +++ b/globals.d.ts @@ -0,0 +1,91 @@ +/*! ***************************************************************************** +Copyright (C) Microsoft. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + +interface SymbolConstructor { + (description?: string): symbol; + readonly iterator: symbol; + readonly toPrimitive: symbol; +} + +declare var Symbol: SymbolConstructor; + +interface Iterator { + next(value?: any): __IteratorResult; + throw?(value: any): __IteratorResult; + return?(value?: T): __IteratorResult; +} + +type __IteratorResult = { value: T, done: false } | { value: never, done: true }; + +interface Iterable { + [Symbol.iterator](): Iterator; +} + +interface IterableIterator extends Iterator { + [Symbol.iterator](): IterableIterator; +} + +interface Map extends Iterable<[K, V]> { + readonly size: number; + has(key: K): boolean; + get(key: K): V; + set(key: K, value?: V): this; + delete(key: K): boolean; + clear(): void; + keys(): IterableIterator; + values(): IterableIterator; + entries(): IterableIterator<[K, V]>; +} + +interface MapConstructor { + new (): Map; + new (): Map; + readonly prototype: Map; +} + +interface Set extends Iterable { + readonly size: number; + has(value: T): boolean; + add(value: T): this; + delete(value: T): boolean; + clear(): void; + keys(): IterableIterator; + values(): IterableIterator; + entries(): IterableIterator<[T, T]>; +} + +interface SetConstructor { + new (): Set; + new (): Set; + readonly prototype: Set; +} + +interface WeakMap { + clear(): void; + delete(key: K): boolean; + get(key: K): V; + has(key: K): boolean; + set(key: K, value?: V): WeakMap; +} + +interface WeakMapConstructor { + new (): WeakMap; + new (): WeakMap; + readonly prototype: WeakMap; +} + +declare var Map: MapConstructor; +declare var Set: SetConstructor; +declare var WeakMap: WeakMapConstructor; diff --git a/gulpfile.js b/gulpfile.js index 76f754f..8539258 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -14,14 +14,33 @@ const tests = tsb.create("test/tsconfig.json"); let project = debugProject; gulp.task("release", () => { project = releaseProject; }); -gulp.task("clean", () => del(["Reflect.js", "Reflect.js.map", "test/**/*.js", "test/**/*.js.map"])); +gulp.task("clean", () => del([ + "Reflect.js", + "Reflect.js.map", + "Reflect.mjs", + "ReflectLite.js", + "ReflectLite.js.map", + "ReflectLite.mjs", + "ReflectNoConflict.js", + "ReflectNoConflict.js.map", + "ReflectNoConflict.mjs", + "index.d.mts", + "no-conflict.d.mts", + "test/**/*.js", + "test/**/*.js.map" +])); gulp.task("build:reflect", () => gulp - .src(["Reflect.ts"]) + .src(["globals.d.ts", "Reflect.ts", "ReflectLite.ts", "ReflectNoConflict.ts"]) .pipe(project()) .pipe(gulp.dest("."))); -gulp.task("build:tests", ["build:reflect"], () => gulp +gulp.task("build:mjs", ["build:reflect"], () => gulp + .src(["Reflect.js", "ReflectLite.js", "ReflectNoConflict.js", "index.d.ts", "no-conflict.d.ts"]) + .pipe(rename(path => path.extname = path.extname === ".ts" ? ".mts" : ".mjs")) + .pipe(gulp.dest("."))); + +gulp.task("build:tests", ["build:mjs"], () => gulp .src(["test/**/*.ts"]) .pipe(tests()) .pipe(gulp.dest("test"))); @@ -36,27 +55,54 @@ gulp.task("build:spec", () => gulp })) .pipe(gulp.dest("docs"))); -gulp.task("build", ["build:tests", "build:spec"]); +gulp.task("build", ["build:reflect", "build:mjs", "build:tests", "build:spec"]); + +gulp.task("no-polyfill", () => { + process.env["REFLECT_METADATA_USE_MAP_POLYFILL"] = ""; +}); gulp.task("use-polyfill", () => { process.env["REFLECT_METADATA_USE_MAP_POLYFILL"] = "true"; }); -gulp.task("test", ["build:tests"], () => { +gulp.task("test:full", ["build:tests", "no-polyfill"], () => { console.log("Running tests w/o polyfill..."); return gulp - .src(["test/**/*.js"], { read: false }) + .src(["test/full/**/*.js"], { read: false }) + .pipe(mocha({ reporter: "dot" })); +}); +gulp.task("test:lite", ["build:tests", "no-polyfill"], () => { + console.log("Running lite-mode tests w/o polyfill..."); + return gulp + .src(["test/lite/**/*.js"], { read: false }) + .pipe(mocha({ reporter: "dot" })); +}); +gulp.task("test:no-conflict", ["build:tests", "no-polyfill"], () => { + console.log("Running no-conflict-mode tests w/o polyfill..."); + return gulp + .src(["test/no-conflict/**/*.js"], { read: false }) .pipe(mocha({ reporter: "dot" })); }); - gulp.task("test:use-polyfill", ["build:tests", "use-polyfill"], () => { console.log("Running tests w/ polyfill..."); return gulp - .src(["test/**/*.js"], { read: false }) + .src(["test/full/**/*.js"], { read: false }) .pipe(mocha({ reporter: "dot" })); }); +gulp.task("test", sequence("test:full", "test:lite", "test:no-conflict", "test:use-polyfill")); + -gulp.task("watch:reflect", () => gulp.watch(["Reflect.ts", "tsconfig.json", "test/**/*.ts", "test/**/tsconfig.json"], ["test"])); +gulp.task("watch:reflect", () => gulp.watch([ + "index.d.ts", + "no-conflict.d.ts", + "globals.d.ts", + "Reflect.ts", + "ReflectLite.ts", + "ReflectNoConflict.ts", + "tsconfig.json", + "test/**/*.ts", + "test/**/tsconfig.json" +], ["test"])); gulp.task("watch:spec", () => gulp.watch(["spec.html"], ["build:spec"])); gulp.task("watch", ["watch:reflect", "watch:spec"], () => { const server = gls.static("docs", 8080); @@ -65,7 +111,7 @@ gulp.task("watch", ["watch:reflect", "watch:spec"], () => { return promise; }); -gulp.task("prepublish", sequence("release", "clean", "test", "test:use-polyfill")); +gulp.task("prepublish", sequence("release", "clean", "test")); gulp.task("reflect", ["build:reflect"]); gulp.task("tests", ["build:tests"]); gulp.task("spec", ["build:spec"]); diff --git a/no-conflict.d.ts b/no-conflict.d.ts new file mode 100644 index 0000000..475780f --- /dev/null +++ b/no-conflict.d.ts @@ -0,0 +1,484 @@ +/*! ***************************************************************************** +Copyright (C) Microsoft. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + +/** + * Applies a set of decorators to a target object. + * @param decorators An array of decorators. + * @param target The target object. + * @returns The result of applying the provided decorators. + * @remarks Decorators are applied in reverse order of their positions in the array. + * @example + * + * class Example { } + * + * // constructor + * Example = Reflect.decorate(decoratorsArray, Example); + * + */ +export declare function decorate(decorators: ClassDecorator[], target: Function): Function; +/** + * Applies a set of decorators to a property of a target object. + * @param decorators An array of decorators. + * @param target The target object. + * @param propertyKey The property key to decorate. + * @param attributes A property descriptor. + * @remarks Decorators are applied in reverse order. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod() { } + * method() { } + * } + * + * // property (on constructor) + * Reflect.decorate(decoratorsArray, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.decorate(decoratorsArray, Example.prototype, "property"); + * + * // method (on constructor) + * Object.defineProperty(Example, "staticMethod", + * Reflect.decorate(decoratorsArray, Example, "staticMethod", + * Object.getOwnPropertyDescriptor(Example, "staticMethod"))); + * + * // method (on prototype) + * Object.defineProperty(Example.prototype, "method", + * Reflect.decorate(decoratorsArray, Example.prototype, "method", + * Object.getOwnPropertyDescriptor(Example.prototype, "method"))); + * + */ +export declare function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: Object, propertyKey: string | symbol, attributes?: PropertyDescriptor): PropertyDescriptor; +/** + * A default metadata decorator factory that can be used on a class, class member, or parameter. + * @param metadataKey The key for the metadata entry. + * @param metadataValue The value for the metadata entry. + * @returns A decorator function. + * @remarks + * If `metadataKey` is already defined for the target and target key, the + * metadataValue for that key will be overwritten. + * @example + * + * // constructor + * @Reflect.metadata(key, value) + * class Example { + * } + * + * // property (on constructor, TypeScript only) + * class Example { + * @Reflect.metadata(key, value) + * static staticProperty; + * } + * + * // property (on prototype, TypeScript only) + * class Example { + * @Reflect.metadata(key, value) + * property; + * } + * + * // method (on constructor) + * class Example { + * @Reflect.metadata(key, value) + * static staticMethod() { } + * } + * + * // method (on prototype) + * class Example { + * @Reflect.metadata(key, value) + * method() { } + * } + * + */ +export declare function metadata(metadataKey: any, metadataValue: any): { + (target: Function): void; + (target: Object, propertyKey: string | symbol): void; +}; +/** + * Define a unique metadata entry on the target. + * @param metadataKey A key used to store and retrieve metadata. + * @param metadataValue A value that contains attached metadata. + * @param target The target object on which to define metadata. + * @example + * + * class Example { + * } + * + * // constructor + * Reflect.defineMetadata("custom:annotation", options, Example); + * + * // decorator factory as metadata-producing annotation. + * function MyAnnotation(options): ClassDecorator { + * return target => Reflect.defineMetadata("custom:annotation", options, target); + * } + * + */ +export declare function defineMetadata(metadataKey: any, metadataValue: any, target: Object): void; +/** + * Define a unique metadata entry on the target. + * @param metadataKey A key used to store and retrieve metadata. + * @param metadataValue A value that contains attached metadata. + * @param target The target object on which to define metadata. + * @param propertyKey The property key for the target. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * Reflect.defineMetadata("custom:annotation", Number, Example, "staticProperty"); + * + * // property (on prototype) + * Reflect.defineMetadata("custom:annotation", Number, Example.prototype, "property"); + * + * // method (on constructor) + * Reflect.defineMetadata("custom:annotation", Number, Example, "staticMethod"); + * + * // method (on prototype) + * Reflect.defineMetadata("custom:annotation", Number, Example.prototype, "method"); + * + * // decorator factory as metadata-producing annotation. + * function MyAnnotation(options): PropertyDecorator { + * return (target, key) => Reflect.defineMetadata("custom:annotation", options, target, key); + * } + * + */ +export declare function defineMetadata(metadataKey: any, metadataValue: any, target: Object, propertyKey: string | symbol): void; +/** + * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.hasMetadata("custom:annotation", Example); + * + */ +export declare function hasMetadata(metadataKey: any, target: Object): boolean; +/** + * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.hasMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.hasMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export declare function hasMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): boolean; +/** + * Gets a value indicating whether the target object has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.hasOwnMetadata("custom:annotation", Example); + * + */ +export declare function hasOwnMetadata(metadataKey: any, target: Object): boolean; +/** + * Gets a value indicating whether the target object has the provided metadata key defined. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns `true` if the metadata key was defined on the target object; otherwise, `false`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export declare function hasOwnMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): boolean; +/** + * Gets the metadata value for the provided metadata key on the target object or its prototype chain. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getMetadata("custom:annotation", Example); + * + */ +export declare function getMetadata(metadataKey: any, target: Object): any; +/** + * Gets the metadata value for the provided metadata key on the target object or its prototype chain. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export declare function getMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): any; +/** + * Gets the metadata value for the provided metadata key on the target object. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getOwnMetadata("custom:annotation", Example); + * + */ +export declare function getOwnMetadata(metadataKey: any, target: Object): any; +/** + * Gets the metadata value for the provided metadata key on the target object. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns The metadata value for the metadata key if found; otherwise, `undefined`. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export declare function getOwnMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): any; +/** + * Gets the metadata keys defined on the target object or its prototype chain. + * @param target The target object on which the metadata is defined. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getMetadataKeys(Example); + * + */ +export declare function getMetadataKeys(target: Object): any[]; +/** + * Gets the metadata keys defined on the target object or its prototype chain. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getMetadataKeys(Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getMetadataKeys(Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getMetadataKeys(Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getMetadataKeys(Example.prototype, "method"); + * + */ +export declare function getMetadataKeys(target: Object, propertyKey: string | symbol): any[]; +/** + * Gets the unique metadata keys defined on the target object. + * @param target The target object on which the metadata is defined. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.getOwnMetadataKeys(Example); + * + */ +export declare function getOwnMetadataKeys(target: Object): any[]; +/** + * Gets the unique metadata keys defined on the target object. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns An array of unique metadata keys. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.getOwnMetadataKeys(Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.getOwnMetadataKeys(Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.getOwnMetadataKeys(Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.getOwnMetadataKeys(Example.prototype, "method"); + * + */ +export declare function getOwnMetadataKeys(target: Object, propertyKey: string | symbol): any[]; +/** + * Deletes the metadata entry from the target object with the provided key. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @returns `true` if the metadata entry was found and deleted; otherwise, false. + * @example + * + * class Example { + * } + * + * // constructor + * result = Reflect.deleteMetadata("custom:annotation", Example); + * + */ +export declare function deleteMetadata(metadataKey: any, target: Object): boolean; +/** + * Deletes the metadata entry from the target object with the provided key. + * @param metadataKey A key used to store and retrieve metadata. + * @param target The target object on which the metadata is defined. + * @param propertyKey The property key for the target. + * @returns `true` if the metadata entry was found and deleted; otherwise, false. + * @example + * + * class Example { + * // property declarations are not part of ES6, though they are valid in TypeScript: + * // static staticProperty; + * // property; + * + * static staticMethod(p) { } + * method(p) { } + * } + * + * // property (on constructor) + * result = Reflect.deleteMetadata("custom:annotation", Example, "staticProperty"); + * + * // property (on prototype) + * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "property"); + * + * // method (on constructor) + * result = Reflect.deleteMetadata("custom:annotation", Example, "staticMethod"); + * + * // method (on prototype) + * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "method"); + * + */ +export declare function deleteMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): boolean; diff --git a/package.json b/package.json index a620727..8ee989f 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,45 @@ { "name": "reflect-metadata", - "version": "0.1.14", + "version": "0.2.0", "description": "Polyfill for Metadata Reflection API", + "type": "commonjs", "main": "Reflect.js", "types": "index.d.ts", "typescript": { "definition": "Reflect.d.ts" }, + "exports": { + ".": { + "import": { + "types": "./index.d.mts", + "default": "./Reflect.mjs" + }, + "default": { + "types": "./index.d.ts", + "default": "./Reflect.js" + } + }, + "./lite": { + "import": { + "types": "./index.d.mts", + "default": "./ReflectLite.mjs" + }, + "default": { + "types": "./index.d.ts", + "default": "./ReflectLite.js" + } + }, + "./no-conflict": { + "import": { + "types": "./no-conflict.d.mts", + "default": "./ReflectNoConflict.mjs" + }, + "default": { + "types": "./no-conflict.d.ts", + "default": "./ReflectNoConflict.js" + } + } + }, "scripts": { "prepublishOnly": "gulp prepublish", "build": "gulp build", @@ -37,7 +70,7 @@ "devDependencies": { "@types/chai": "^3.4.34", "@types/mocha": "^2.2.34", - "@types/node": "^6.0.52", + "@types/node": "6.0.52", "chai": "^3.5.0", "del": "^2.2.2", "ecmarkup": "^3.9.3", diff --git a/reflect-metadata.d.ts b/reflect-metadata.d.ts deleted file mode 100644 index 2f342ce..0000000 --- a/reflect-metadata.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*! ***************************************************************************** -Copyright (C) Microsoft. All rights reserved. -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ - -// NOTE: This file is obsolete and may be removed in a later release. -// For CommonJS/AMD/UMD/SystemJS declarations please use 'index.d.ts'. -// For standalone browser declarations, please use 'standalone.d.ts'. - -/// \ No newline at end of file diff --git a/test/full/reflect-decorate.ts b/test/full/reflect-decorate.ts new file mode 100644 index 0000000..2c45264 --- /dev/null +++ b/test/full/reflect-decorate.ts @@ -0,0 +1,211 @@ +// Reflect.decorate ( decorators, target [, propertyKey [, descriptor] ] ) + +/// +require("../../Reflect"); +import { assert } from "chai"; + +describe("Reflect.decorate", () => { + it("ThrowsIfDecoratorsArgumentNotArrayForFunctionOverload", () => { + let target = function() { }; + assert.throws(() => Reflect.decorate(undefined!, target, undefined!, undefined), TypeError); + }); + + it("ThrowsIfTargetArgumentNotFunctionForFunctionOverload", () => { + let decorators: (MethodDecorator | PropertyDecorator)[] = []; + let target = {}; + assert.throws(() => Reflect.decorate(decorators, target, undefined!, undefined), TypeError); + }); + + it("ThrowsIfDecoratorsArgumentNotArrayForPropertyOverload", () => { + let target = {}; + let name = "name"; + assert.throws(() => Reflect.decorate(undefined!, target, name, undefined), TypeError); + }); + + it("ThrowsIfTargetArgumentNotObjectForPropertyOverload", () => { + let decorators: (MethodDecorator | PropertyDecorator)[] = []; + let target = 1; + let name = "name"; + assert.throws(() => Reflect.decorate(decorators, target, name, undefined), TypeError); + }); + + it("ThrowsIfDecoratorsArgumentNotArrayForPropertyDescriptorOverload", () => { + let target = {}; + let name = "name"; + let descriptor = {}; + assert.throws(() => Reflect.decorate(undefined!, target, name, descriptor), TypeError); + }); + + it("ThrowsIfTargetArgumentNotObjectForPropertyDescriptorOverload", () => { + let decorators: (MethodDecorator | PropertyDecorator)[] = []; + let target = 1; + let name = "name"; + let descriptor = {}; + assert.throws(() => Reflect.decorate(decorators, target, name, descriptor), TypeError); + }); + + it("ExecutesDecoratorsInReverseOrderForFunctionOverload", () => { + let order: number[] = []; + let decorators = [ + (_target: Function): void => { order.push(0); }, + (_target: Function): void => { order.push(1); } + ]; + let target = function() { }; + Reflect.decorate(decorators, target); + assert.deepEqual(order, [1, 0]); + }); + + it("ExecutesDecoratorsInReverseOrderForPropertyOverload", () => { + let order: number[] = []; + let decorators = [ + (_target: Object, _name: string | symbol): void => { order.push(0); }, + (_target: Object, _name: string | symbol): void => { order.push(1); } + ]; + let target = {}; + let name = "name"; + Reflect.decorate(decorators, target, name, undefined); + assert.deepEqual(order, [1, 0]); + }); + + it("ExecutesDecoratorsInReverseOrderForPropertyDescriptorOverload", () => { + let order: number[] = []; + let decorators = [ + (_target: Object, _name: string | symbol): void => { order.push(0); }, + (_target: Object, _name: string | symbol): void => { order.push(1); } + ]; + let target = {}; + let name = "name"; + let descriptor = {}; + Reflect.decorate(decorators, target, name, descriptor); + assert.deepEqual(order, [1, 0]); + }); + + it("DecoratorPipelineForFunctionOverload", () => { + let A = function A(): void { }; + let B = function B(): void { }; + let decorators = [ + (_target: Function): any => { return undefined; }, + (_target: Function): any => { return A; }, + (_target: Function): any => { return B; } + ]; + let target = function (): void { }; + let result = Reflect.decorate(decorators, target); + assert.strictEqual(result, A); + }); + + it("DecoratorPipelineForPropertyOverload", () => { + let A = {}; + let B = {}; + let decorators = [ + (_target: Object, _name: string | symbol): any => { return undefined; }, + (_target: Object, _name: string | symbol): any => { return A; }, + (_target: Object, _name: string | symbol): any => { return B; } + ]; + let target = {}; + let result = Reflect.decorate(decorators, target, "name", undefined); + assert.strictEqual(result, A); + }); + + it("DecoratorPipelineForPropertyDescriptorOverload", () => { + let A = {}; + let B = {}; + let C = {}; + let decorators = [ + (_target: Object, _name: string | symbol): any => { return undefined; }, + (_target: Object, _name: string | symbol): any => { return A; }, + (_target: Object, _name: string | symbol): any => { return B; } + ]; + let target = {}; + let result = Reflect.decorate(decorators, target, "name", C); + assert.strictEqual(result, A); + }); + + it("DecoratorCorrectTargetInPipelineForFunctionOverload", () => { + let sent: Function[] = []; + let A = function A(): void { }; + let B = function B(): void { }; + let decorators = [ + (target: Function): any => { sent.push(target); return undefined; }, + (target: Function): any => { sent.push(target); return undefined; }, + (target: Function): any => { sent.push(target); return A; }, + (target: Function): any => { sent.push(target); return B; } + ]; + let target = function (): void { }; + Reflect.decorate(decorators, target); + assert.deepEqual(sent, [target, B, A, A]); + }); + + it("DecoratorCorrectTargetInPipelineForPropertyOverload", () => { + let sent: Object[] = []; + let decorators = [ + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name"); + assert.deepEqual(sent, [target, target, target, target]); + }); + + it("DecoratorCorrectNameInPipelineForPropertyOverload", () => { + let sent: (symbol | string)[] = []; + let decorators = [ + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name"); + assert.deepEqual(sent, ["name", "name", "name", "name"]); + }); + + it("DecoratorCorrectTargetInPipelineForPropertyDescriptorOverload", () => { + let sent: Object[] = []; + let A = { }; + let B = { }; + let C = { }; + let decorators = [ + (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return A; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return B; } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name", C); + assert.deepEqual(sent, [target, target, target, target]); + }); + + it("DecoratorCorrectNameInPipelineForPropertyDescriptorOverload", () => { + let sent: (symbol | string)[] = []; + let A = { }; + let B = { }; + let C = { }; + let decorators = [ + (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return A; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return B; } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name", C); + assert.deepEqual(sent, ["name", "name", "name", "name"]); + }); + + it("DecoratorCorrectDescriptorInPipelineForPropertyDescriptorOverload", () => { + let sent: PropertyDescriptor[] = []; + let A = { }; + let B = { }; + let C = { }; + let decorators = [ + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return A; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return B; } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name", C); + assert.deepEqual(sent, [C, B, A, A]); + }); +}); diff --git a/test/full/reflect-definemetadata.ts b/test/full/reflect-definemetadata.ts new file mode 100644 index 0000000..54ecc37 --- /dev/null +++ b/test/full/reflect-definemetadata.ts @@ -0,0 +1,20 @@ +// 4.1.2 Reflect.defineMetadata ( metadataKey, metadataValue, target, propertyKey ) +// https://rbuckton.github.io/reflect-metadata/#reflect.definemetadata + +/// +require("../../Reflect"); +import { assert } from "chai"; + +describe("Reflect.defineMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.defineMetadata("key", "value", undefined, undefined!), TypeError); + }); + + it("ValidTargetWithoutTargetKey", () => { + assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, undefined!)); + }); + + it("ValidTargetWithTargetKey", () => { + assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, "name")); + }); +}); \ No newline at end of file diff --git a/test/full/reflect-deletemetadata.ts b/test/full/reflect-deletemetadata.ts new file mode 100644 index 0000000..326cd46 --- /dev/null +++ b/test/full/reflect-deletemetadata.ts @@ -0,0 +1,41 @@ +// 4.1.10 Reflect.deleteMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.deletemetadata + +/// +require("../../Reflect"); +import { assert } from "chai"; + +describe("Reflect.deleteMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.deleteMetadata("key", undefined, undefined!), TypeError); + }); + + it("WhenNotDefinedWithoutTargetKey", () => { + let obj = {}; + let result = Reflect.deleteMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WhenDefinedWithoutTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.deleteMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WhenDefinedOnPrototypeWithoutTargetKey", () => { + let prototype = {}; + Reflect.defineMetadata("key", "value", prototype, undefined!); + let obj = Object.create(prototype); + let result = Reflect.deleteMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("AfterDeleteMetadata", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + Reflect.deleteMetadata("key", obj, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, false); + }); +}); \ No newline at end of file diff --git a/test/full/reflect-getmetadata.ts b/test/full/reflect-getmetadata.ts new file mode 100644 index 0000000..78e9713 --- /dev/null +++ b/test/full/reflect-getmetadata.ts @@ -0,0 +1,54 @@ +// 4.1.5 Reflect.getMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadata + +/// +require("../../Reflect"); +import { assert } from "chai"; + +describe("Reflect.getMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.getMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getMetadata("key", obj, undefined!); + assert.equal(result, undefined); + }); + + it("WithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getMetadata("key", obj, undefined!); + assert.equal(result, "value"); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getMetadata("key", obj, undefined!); + assert.equal(result, "value"); + }); + + it("WithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getMetadata("key", obj, "name"); + assert.equal(result, undefined); + }); + + it("WithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getMetadata("key", obj, "name"); + assert.equal(result, "value"); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getMetadata("key", obj, "name"); + assert.equal(result, "value"); + }); +}); \ No newline at end of file diff --git a/test/full/reflect-getmetadatakeys.ts b/test/full/reflect-getmetadatakeys.ts new file mode 100644 index 0000000..45003d4 --- /dev/null +++ b/test/full/reflect-getmetadatakeys.ts @@ -0,0 +1,101 @@ +// 4.1.8 Reflect.getMetadataKeys ( target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadatakeys + +/// +require("../../Reflect"); +import { assert } from "chai"; + +describe("Reflect.getMetadataKeys", () => { + it("KeysInvalidTarget", () => { + // 1. If Type(target) is not Object, throw a TypeError exception. + assert.throws(() => Reflect.getMetadataKeys(undefined, undefined!), TypeError); + }); + + it("KeysWithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, []); + }); + + it("KeysWithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key"]); + }); + + it("KeysOrderWithoutTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderAfterRedefineWithoutTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + Reflect.defineMetadata("key1", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderWithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + Reflect.defineMetadata("key2", "value", prototype, undefined!); + let obj = Object.create(prototype); + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0", "key2"]); + }); + + it("KeysWithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, []); + }); + + it("KeysWithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key"]); + }); + + it("KeysOrderAfterRedefineWithTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, "name"); + Reflect.defineMetadata("key0", "value", obj, "name"); + Reflect.defineMetadata("key1", "value", obj, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderWithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + Reflect.defineMetadata("key2", "value", prototype, "name"); + let obj = Object.create(prototype); + Reflect.defineMetadata("key1", "value", obj, "name"); + Reflect.defineMetadata("key0", "value", obj, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key1", "key0", "key2"]); + }); +}); \ No newline at end of file diff --git a/test/full/reflect-getownmetadata.ts b/test/full/reflect-getownmetadata.ts new file mode 100644 index 0000000..de05797 --- /dev/null +++ b/test/full/reflect-getownmetadata.ts @@ -0,0 +1,54 @@ +// 4.1.7 Reflect.getOwnMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadata + +/// +require("../../Reflect"); +import { assert } from "chai"; + +describe("Reflect.getOwnMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.getOwnMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getOwnMetadata("key", obj, undefined!); + assert.equal(result, undefined); + }); + + it("WithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getOwnMetadata("key", obj, undefined!); + assert.equal(result, "value"); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getOwnMetadata("key", obj, undefined!); + assert.equal(result, undefined); + }); + + it("WithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getOwnMetadata("key", obj, "name"); + assert.equal(result, undefined); + }); + + it("WithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getOwnMetadata("key", obj, "name"); + assert.equal(result, "value"); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getOwnMetadata("key", obj, "name"); + assert.equal(result, undefined); + }); +}); \ No newline at end of file diff --git a/test/full/reflect-getownmetadatakeys.ts b/test/full/reflect-getownmetadatakeys.ts new file mode 100644 index 0000000..eb5bce9 --- /dev/null +++ b/test/full/reflect-getownmetadatakeys.ts @@ -0,0 +1,81 @@ +// 4.1.9 Reflect.getOwnMetadataKeysKeys ( target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadatakeys + +/// +require("../../Reflect"); +import { assert } from "chai"; + +describe("Reflect.getOwnMetadataKeys", () => { + it("KeysKeysInvalidTarget", () => { + // 1. If Type(target) is not Object, throw a TypeError exception. + assert.throws(() => Reflect.getOwnMetadataKeys(undefined, undefined!), TypeError); + }); + + it("KeysWithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, []); + }); + + it("KeysWithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, []); + }); + + it("KeysOrderWithoutTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderAfterRedefineWithoutTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + Reflect.defineMetadata("key1", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysWithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, []); + }); + + it("KeysWithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, []); + }); + + it("KeysOrderAfterRedefineWithTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, "name"); + Reflect.defineMetadata("key0", "value", obj, "name"); + Reflect.defineMetadata("key1", "value", obj, "name"); + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key1", "key0"]); + }); +}); \ No newline at end of file diff --git a/test/full/reflect-hasmetadata.ts b/test/full/reflect-hasmetadata.ts new file mode 100644 index 0000000..eae3213 --- /dev/null +++ b/test/full/reflect-hasmetadata.ts @@ -0,0 +1,54 @@ +// 4.1.4 Reflect.hasMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.hasmetadata + +/// +require("../../Reflect"); +import { assert } from "chai"; + +describe("Reflect.hasMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.hasMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.hasMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.hasMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.hasMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.hasMetadata("key", obj, "name"); + assert.equal(result, false); + }); + + it("WithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.hasMetadata("key", obj, "name"); + assert.equal(result, true); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.hasMetadata("key", obj, "name"); + assert.equal(result, true); + }); +}); \ No newline at end of file diff --git a/test/full/reflect-hasownmetadata.ts b/test/full/reflect-hasownmetadata.ts new file mode 100644 index 0000000..22c6fdb --- /dev/null +++ b/test/full/reflect-hasownmetadata.ts @@ -0,0 +1,54 @@ +// 4.1.5 Reflect.hasOwnMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.hasownmetadata + +/// +require("../../Reflect"); +import { assert } from "chai"; + +describe("Reflect.hasOwnMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.hasOwnMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.hasOwnMetadata("key", obj, "name"); + assert.equal(result, false); + }); + + it("WithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.hasOwnMetadata("key", obj, "name"); + assert.equal(result, true); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.hasOwnMetadata("key", obj, "name"); + assert.equal(result, false); + }); +}); \ No newline at end of file diff --git a/test/reflect-metadata.ts b/test/full/reflect-metadata.ts similarity index 91% rename from test/reflect-metadata.ts rename to test/full/reflect-metadata.ts index 27dc9dd..1542a43 100644 --- a/test/reflect-metadata.ts +++ b/test/full/reflect-metadata.ts @@ -1,7 +1,8 @@ // 4.1.2 Reflect.metadata ( metadataKey, metadataValue ) // https://rbuckton.github.io/reflect-metadata/#reflect.metadata -import "../Reflect"; +/// +require("../../Reflect"); import { assert } from "chai"; describe("Reflect.metadata", () => { @@ -25,7 +26,7 @@ describe("Reflect.metadata", () => { let target = function () {} decorator(target); - let result = Reflect.hasOwnMetadata("key", target, undefined); + let result = Reflect.hasOwnMetadata("key", target, undefined!); assert.equal(result, true); }); diff --git a/test/reflect-other.ts b/test/full/reflect-other.ts similarity index 84% rename from test/reflect-other.ts rename to test/full/reflect-other.ts index 059ca47..c164cbb 100644 --- a/test/reflect-other.ts +++ b/test/full/reflect-other.ts @@ -5,7 +5,7 @@ describe("Reflect", () => { it("does not overwrite existing implementation", () => { const defineMetadata = Reflect.defineMetadata; - const reflectPath = require.resolve("../Reflect.js"); + const reflectPath = require.resolve("../../Reflect.js"); const reflectContent = fs.readFileSync(reflectPath, "utf8"); const reflectFunction = Function(reflectContent); reflectFunction(); diff --git a/test/lite/reflect-decorate.ts b/test/lite/reflect-decorate.ts new file mode 100644 index 0000000..7e89179 --- /dev/null +++ b/test/lite/reflect-decorate.ts @@ -0,0 +1,211 @@ +// Reflect.decorate ( decorators, target [, propertyKey [, descriptor] ] ) + +/// +require("../../ReflectLite"); +import { assert } from "chai"; + +describe("Reflect.decorate", () => { + it("ThrowsIfDecoratorsArgumentNotArrayForFunctionOverload", () => { + let target = function() { }; + assert.throws(() => Reflect.decorate(undefined!, target, undefined!, undefined), TypeError); + }); + + it("ThrowsIfTargetArgumentNotFunctionForFunctionOverload", () => { + let decorators: (MethodDecorator | PropertyDecorator)[] = []; + let target = {}; + assert.throws(() => Reflect.decorate(decorators, target, undefined!, undefined), TypeError); + }); + + it("ThrowsIfDecoratorsArgumentNotArrayForPropertyOverload", () => { + let target = {}; + let name = "name"; + assert.throws(() => Reflect.decorate(undefined!, target, name, undefined), TypeError); + }); + + it("ThrowsIfTargetArgumentNotObjectForPropertyOverload", () => { + let decorators: (MethodDecorator | PropertyDecorator)[] = []; + let target = 1; + let name = "name"; + assert.throws(() => Reflect.decorate(decorators, target, name, undefined), TypeError); + }); + + it("ThrowsIfDecoratorsArgumentNotArrayForPropertyDescriptorOverload", () => { + let target = {}; + let name = "name"; + let descriptor = {}; + assert.throws(() => Reflect.decorate(undefined!, target, name, descriptor), TypeError); + }); + + it("ThrowsIfTargetArgumentNotObjectForPropertyDescriptorOverload", () => { + let decorators: (MethodDecorator | PropertyDecorator)[] = []; + let target = 1; + let name = "name"; + let descriptor = {}; + assert.throws(() => Reflect.decorate(decorators, target, name, descriptor), TypeError); + }); + + it("ExecutesDecoratorsInReverseOrderForFunctionOverload", () => { + let order: number[] = []; + let decorators = [ + (_target: Function): void => { order.push(0); }, + (_target: Function): void => { order.push(1); } + ]; + let target = function() { }; + Reflect.decorate(decorators, target); + assert.deepEqual(order, [1, 0]); + }); + + it("ExecutesDecoratorsInReverseOrderForPropertyOverload", () => { + let order: number[] = []; + let decorators = [ + (_target: Object, _name: string | symbol): void => { order.push(0); }, + (_target: Object, _name: string | symbol): void => { order.push(1); } + ]; + let target = {}; + let name = "name"; + Reflect.decorate(decorators, target, name, undefined); + assert.deepEqual(order, [1, 0]); + }); + + it("ExecutesDecoratorsInReverseOrderForPropertyDescriptorOverload", () => { + let order: number[] = []; + let decorators = [ + (_target: Object, _name: string | symbol): void => { order.push(0); }, + (_target: Object, _name: string | symbol): void => { order.push(1); } + ]; + let target = {}; + let name = "name"; + let descriptor = {}; + Reflect.decorate(decorators, target, name, descriptor); + assert.deepEqual(order, [1, 0]); + }); + + it("DecoratorPipelineForFunctionOverload", () => { + let A = function A(): void { }; + let B = function B(): void { }; + let decorators = [ + (_target: Function): any => { return undefined; }, + (_target: Function): any => { return A; }, + (_target: Function): any => { return B; } + ]; + let target = function (): void { }; + let result = Reflect.decorate(decorators, target); + assert.strictEqual(result, A); + }); + + it("DecoratorPipelineForPropertyOverload", () => { + let A = {}; + let B = {}; + let decorators = [ + (_target: Object, _name: string | symbol): any => { return undefined; }, + (_target: Object, _name: string | symbol): any => { return A; }, + (_target: Object, _name: string | symbol): any => { return B; } + ]; + let target = {}; + let result = Reflect.decorate(decorators, target, "name", undefined); + assert.strictEqual(result, A); + }); + + it("DecoratorPipelineForPropertyDescriptorOverload", () => { + let A = {}; + let B = {}; + let C = {}; + let decorators = [ + (_target: Object, _name: string | symbol): any => { return undefined; }, + (_target: Object, _name: string | symbol): any => { return A; }, + (_target: Object, _name: string | symbol): any => { return B; } + ]; + let target = {}; + let result = Reflect.decorate(decorators, target, "name", C); + assert.strictEqual(result, A); + }); + + it("DecoratorCorrectTargetInPipelineForFunctionOverload", () => { + let sent: Function[] = []; + let A = function A(): void { }; + let B = function B(): void { }; + let decorators = [ + (target: Function): any => { sent.push(target); return undefined; }, + (target: Function): any => { sent.push(target); return undefined; }, + (target: Function): any => { sent.push(target); return A; }, + (target: Function): any => { sent.push(target); return B; } + ]; + let target = function (): void { }; + Reflect.decorate(decorators, target); + assert.deepEqual(sent, [target, B, A, A]); + }); + + it("DecoratorCorrectTargetInPipelineForPropertyOverload", () => { + let sent: Object[] = []; + let decorators = [ + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name"); + assert.deepEqual(sent, [target, target, target, target]); + }); + + it("DecoratorCorrectNameInPipelineForPropertyOverload", () => { + let sent: (symbol | string)[] = []; + let decorators = [ + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name"); + assert.deepEqual(sent, ["name", "name", "name", "name"]); + }); + + it("DecoratorCorrectTargetInPipelineForPropertyDescriptorOverload", () => { + let sent: Object[] = []; + let A = { }; + let B = { }; + let C = { }; + let decorators = [ + (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return A; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return B; } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name", C); + assert.deepEqual(sent, [target, target, target, target]); + }); + + it("DecoratorCorrectNameInPipelineForPropertyDescriptorOverload", () => { + let sent: (symbol | string)[] = []; + let A = { }; + let B = { }; + let C = { }; + let decorators = [ + (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return A; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return B; } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name", C); + assert.deepEqual(sent, ["name", "name", "name", "name"]); + }); + + it("DecoratorCorrectDescriptorInPipelineForPropertyDescriptorOverload", () => { + let sent: PropertyDescriptor[] = []; + let A = { }; + let B = { }; + let C = { }; + let decorators = [ + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return A; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return B; } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name", C); + assert.deepEqual(sent, [C, B, A, A]); + }); +}); diff --git a/test/lite/reflect-definemetadata.ts b/test/lite/reflect-definemetadata.ts new file mode 100644 index 0000000..7e8d01d --- /dev/null +++ b/test/lite/reflect-definemetadata.ts @@ -0,0 +1,20 @@ +// 4.1.2 Reflect.defineMetadata ( metadataKey, metadataValue, target, propertyKey ) +// https://rbuckton.github.io/reflect-metadata/#reflect.definemetadata + +/// +require("../../ReflectLite"); +import { assert } from "chai"; + +describe("Reflect.defineMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.defineMetadata("key", "value", undefined, undefined!), TypeError); + }); + + it("ValidTargetWithoutTargetKey", () => { + assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, undefined!)); + }); + + it("ValidTargetWithTargetKey", () => { + assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, "name")); + }); +}); \ No newline at end of file diff --git a/test/lite/reflect-deletemetadata.ts b/test/lite/reflect-deletemetadata.ts new file mode 100644 index 0000000..a54405c --- /dev/null +++ b/test/lite/reflect-deletemetadata.ts @@ -0,0 +1,41 @@ +// 4.1.10 Reflect.deleteMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.deletemetadata + +/// +require("../../ReflectLite"); +import { assert } from "chai"; + +describe("Reflect.deleteMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.deleteMetadata("key", undefined, undefined!), TypeError); + }); + + it("WhenNotDefinedWithoutTargetKey", () => { + let obj = {}; + let result = Reflect.deleteMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WhenDefinedWithoutTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.deleteMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WhenDefinedOnPrototypeWithoutTargetKey", () => { + let prototype = {}; + Reflect.defineMetadata("key", "value", prototype, undefined!); + let obj = Object.create(prototype); + let result = Reflect.deleteMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("AfterDeleteMetadata", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + Reflect.deleteMetadata("key", obj, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, false); + }); +}); \ No newline at end of file diff --git a/test/lite/reflect-getmetadata.ts b/test/lite/reflect-getmetadata.ts new file mode 100644 index 0000000..32af3b6 --- /dev/null +++ b/test/lite/reflect-getmetadata.ts @@ -0,0 +1,54 @@ +// 4.1.5 Reflect.getMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadata + +/// +require("../../ReflectLite"); +import { assert } from "chai"; + +describe("Reflect.getMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.getMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getMetadata("key", obj, undefined!); + assert.equal(result, undefined); + }); + + it("WithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getMetadata("key", obj, undefined!); + assert.equal(result, "value"); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getMetadata("key", obj, undefined!); + assert.equal(result, "value"); + }); + + it("WithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getMetadata("key", obj, "name"); + assert.equal(result, undefined); + }); + + it("WithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getMetadata("key", obj, "name"); + assert.equal(result, "value"); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getMetadata("key", obj, "name"); + assert.equal(result, "value"); + }); +}); \ No newline at end of file diff --git a/test/lite/reflect-getmetadatakeys.ts b/test/lite/reflect-getmetadatakeys.ts new file mode 100644 index 0000000..dda97fd --- /dev/null +++ b/test/lite/reflect-getmetadatakeys.ts @@ -0,0 +1,101 @@ +// 4.1.8 Reflect.getMetadataKeys ( target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadatakeys + +/// +require("../../ReflectLite"); +import { assert } from "chai"; + +describe("Reflect.getMetadataKeys", () => { + it("KeysInvalidTarget", () => { + // 1. If Type(target) is not Object, throw a TypeError exception. + assert.throws(() => Reflect.getMetadataKeys(undefined, undefined!), TypeError); + }); + + it("KeysWithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, []); + }); + + it("KeysWithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key"]); + }); + + it("KeysOrderWithoutTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderAfterRedefineWithoutTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + Reflect.defineMetadata("key1", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderWithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + Reflect.defineMetadata("key2", "value", prototype, undefined!); + let obj = Object.create(prototype); + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0", "key2"]); + }); + + it("KeysWithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, []); + }); + + it("KeysWithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key"]); + }); + + it("KeysOrderAfterRedefineWithTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, "name"); + Reflect.defineMetadata("key0", "value", obj, "name"); + Reflect.defineMetadata("key1", "value", obj, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderWithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + Reflect.defineMetadata("key2", "value", prototype, "name"); + let obj = Object.create(prototype); + Reflect.defineMetadata("key1", "value", obj, "name"); + Reflect.defineMetadata("key0", "value", obj, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key1", "key0", "key2"]); + }); +}); \ No newline at end of file diff --git a/test/lite/reflect-getownmetadata.ts b/test/lite/reflect-getownmetadata.ts new file mode 100644 index 0000000..f7df4eb --- /dev/null +++ b/test/lite/reflect-getownmetadata.ts @@ -0,0 +1,54 @@ +// 4.1.7 Reflect.getOwnMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadata + +/// +require("../../ReflectLite"); +import { assert } from "chai"; + +describe("Reflect.getOwnMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.getOwnMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getOwnMetadata("key", obj, undefined!); + assert.equal(result, undefined); + }); + + it("WithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getOwnMetadata("key", obj, undefined!); + assert.equal(result, "value"); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getOwnMetadata("key", obj, undefined!); + assert.equal(result, undefined); + }); + + it("WithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getOwnMetadata("key", obj, "name"); + assert.equal(result, undefined); + }); + + it("WithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getOwnMetadata("key", obj, "name"); + assert.equal(result, "value"); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getOwnMetadata("key", obj, "name"); + assert.equal(result, undefined); + }); +}); \ No newline at end of file diff --git a/test/lite/reflect-getownmetadatakeys.ts b/test/lite/reflect-getownmetadatakeys.ts new file mode 100644 index 0000000..fdc6a25 --- /dev/null +++ b/test/lite/reflect-getownmetadatakeys.ts @@ -0,0 +1,81 @@ +// 4.1.9 Reflect.getOwnMetadataKeysKeys ( target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadatakeys + +/// +require("../../ReflectLite"); +import { assert } from "chai"; + +describe("Reflect.getOwnMetadataKeys", () => { + it("KeysKeysInvalidTarget", () => { + // 1. If Type(target) is not Object, throw a TypeError exception. + assert.throws(() => Reflect.getOwnMetadataKeys(undefined, undefined!), TypeError); + }); + + it("KeysWithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, []); + }); + + it("KeysWithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, []); + }); + + it("KeysOrderWithoutTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderAfterRedefineWithoutTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + Reflect.defineMetadata("key1", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysWithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, []); + }); + + it("KeysWithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, []); + }); + + it("KeysOrderAfterRedefineWithTargetKey", () => { + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, "name"); + Reflect.defineMetadata("key0", "value", obj, "name"); + Reflect.defineMetadata("key1", "value", obj, "name"); + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key1", "key0"]); + }); +}); \ No newline at end of file diff --git a/test/lite/reflect-hasmetadata.ts b/test/lite/reflect-hasmetadata.ts new file mode 100644 index 0000000..2083196 --- /dev/null +++ b/test/lite/reflect-hasmetadata.ts @@ -0,0 +1,54 @@ +// 4.1.4 Reflect.hasMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.hasmetadata + +/// +require("../../ReflectLite"); +import { assert } from "chai"; + +describe("Reflect.hasMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.hasMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.hasMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.hasMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.hasMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.hasMetadata("key", obj, "name"); + assert.equal(result, false); + }); + + it("WithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.hasMetadata("key", obj, "name"); + assert.equal(result, true); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.hasMetadata("key", obj, "name"); + assert.equal(result, true); + }); +}); \ No newline at end of file diff --git a/test/lite/reflect-hasownmetadata.ts b/test/lite/reflect-hasownmetadata.ts new file mode 100644 index 0000000..d54b25c --- /dev/null +++ b/test/lite/reflect-hasownmetadata.ts @@ -0,0 +1,54 @@ +// 4.1.5 Reflect.hasOwnMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.hasownmetadata + +/// +require("../../ReflectLite"); +import { assert } from "chai"; + +describe("Reflect.hasOwnMetadata", () => { + it("InvalidTarget", () => { + assert.throws(() => Reflect.hasOwnMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WithoutTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WithTargetKeyWhenNotDefined", () => { + let obj = {}; + let result = Reflect.hasOwnMetadata("key", obj, "name"); + assert.equal(result, false); + }); + + it("WithTargetKeyWhenDefined", () => { + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.hasOwnMetadata("key", obj, "name"); + assert.equal(result, true); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.hasOwnMetadata("key", obj, "name"); + assert.equal(result, false); + }); +}); \ No newline at end of file diff --git a/test/lite/reflect-metadata.ts b/test/lite/reflect-metadata.ts new file mode 100644 index 0000000..90b8d0f --- /dev/null +++ b/test/lite/reflect-metadata.ts @@ -0,0 +1,41 @@ +// 4.1.2 Reflect.metadata ( metadataKey, metadataValue ) +// https://rbuckton.github.io/reflect-metadata/#reflect.metadata + +/// +require("../../ReflectLite"); +import { assert } from "chai"; + +describe("Reflect.metadata", () => { + it("ReturnsDecoratorFunction", () => { + let result = Reflect.metadata("key", "value"); + assert.equal(typeof result, "function"); + }); + + it("DecoratorThrowsWithInvalidTargetWithTargetKey", () => { + let decorator = Reflect.metadata("key", "value"); + assert.throws(() => decorator(undefined, "name"), TypeError); + }); + + it("DecoratorThrowsWithInvalidTargetKey", () => { + let decorator = Reflect.metadata("key", "value"); + assert.throws(() => decorator({}, {}), TypeError); + }); + + it("OnTargetWithoutTargetKey", () => { + let decorator = Reflect.metadata("key", "value"); + let target = function () {} + decorator(target); + + let result = Reflect.hasOwnMetadata("key", target, undefined!); + assert.equal(result, true); + }); + + it("OnTargetWithTargetKey", () => { + let decorator = Reflect.metadata("key", "value"); + let target = {} + decorator(target, "name"); + + let result = Reflect.hasOwnMetadata("key", target, "name"); + assert.equal(result, true); + }); +}); \ No newline at end of file diff --git a/test/lite/reflect-other.ts b/test/lite/reflect-other.ts new file mode 100644 index 0000000..878a1a8 --- /dev/null +++ b/test/lite/reflect-other.ts @@ -0,0 +1,17 @@ +/// + +import * as fs from "fs"; +import { assert } from "chai"; + +describe("Reflect", () => { + it("does not overwrite existing implementation", () => { + const defineMetadata = Reflect.defineMetadata; + + const reflectPath = require.resolve("../../ReflectLite.js"); + const reflectContent = fs.readFileSync(reflectPath, "utf8"); + const reflectFunction = Function(reflectContent); + reflectFunction(); + + assert.strictEqual(Reflect.defineMetadata, defineMetadata); + }); +}); \ No newline at end of file diff --git a/test/reflect-decorate.ts b/test/no-conflict/reflect-decorate.ts similarity index 58% rename from test/reflect-decorate.ts rename to test/no-conflict/reflect-decorate.ts index 4189e43..01d4c3b 100644 --- a/test/reflect-decorate.ts +++ b/test/no-conflict/reflect-decorate.ts @@ -1,28 +1,28 @@ // Reflect.decorate ( decorators, target [, propertyKey [, descriptor] ] ) -import "../Reflect"; +const Reflect = require("../../ReflectNoConflict"); import { assert } from "chai"; describe("Reflect.decorate", () => { it("ThrowsIfDecoratorsArgumentNotArrayForFunctionOverload", () => { let target = function() { }; - assert.throws(() => Reflect.decorate(undefined, target, undefined, undefined), TypeError); + assert.throws(() => Reflect.decorate(undefined!, target, undefined!, undefined), TypeError); }); it("ThrowsIfTargetArgumentNotFunctionForFunctionOverload", () => { - let decorators: (ClassDecorator | MethodDecorator | PropertyDecorator)[] = []; + let decorators: (MethodDecorator | PropertyDecorator)[] = []; let target = {}; - assert.throws(() => Reflect.decorate(decorators, target, undefined, undefined), TypeError); + assert.throws(() => Reflect.decorate(decorators, target, undefined!, undefined), TypeError); }); it("ThrowsIfDecoratorsArgumentNotArrayForPropertyOverload", () => { let target = {}; let name = "name"; - assert.throws(() => Reflect.decorate(undefined, target, name, undefined), TypeError); + assert.throws(() => Reflect.decorate(undefined!, target, name, undefined), TypeError); }); it("ThrowsIfTargetArgumentNotObjectForPropertyOverload", () => { - let decorators: (ClassDecorator | MethodDecorator | PropertyDecorator)[] = []; + let decorators: (MethodDecorator | PropertyDecorator)[] = []; let target = 1; let name = "name"; assert.throws(() => Reflect.decorate(decorators, target, name, undefined), TypeError); @@ -32,11 +32,11 @@ describe("Reflect.decorate", () => { let target = {}; let name = "name"; let descriptor = {}; - assert.throws(() => Reflect.decorate(undefined, target, name, descriptor), TypeError); + assert.throws(() => Reflect.decorate(undefined!, target, name, descriptor), TypeError); }); it("ThrowsIfTargetArgumentNotObjectForPropertyDescriptorOverload", () => { - let decorators: (ClassDecorator | MethodDecorator | PropertyDecorator)[] = []; + let decorators: (MethodDecorator | PropertyDecorator)[] = []; let target = 1; let name = "name"; let descriptor = {}; @@ -46,8 +46,8 @@ describe("Reflect.decorate", () => { it("ExecutesDecoratorsInReverseOrderForFunctionOverload", () => { let order: number[] = []; let decorators = [ - (target: Function): void => { order.push(0); }, - (target: Function): void => { order.push(1); } + (_target: Function): void => { order.push(0); }, + (_target: Function): void => { order.push(1); } ]; let target = function() { }; Reflect.decorate(decorators, target); @@ -57,8 +57,8 @@ describe("Reflect.decorate", () => { it("ExecutesDecoratorsInReverseOrderForPropertyOverload", () => { let order: number[] = []; let decorators = [ - (target: Object, name: string | symbol): void => { order.push(0); }, - (target: Object, name: string | symbol): void => { order.push(1); } + (_target: Object, _name: string | symbol): void => { order.push(0); }, + (_target: Object, _name: string | symbol): void => { order.push(1); } ]; let target = {}; let name = "name"; @@ -69,8 +69,8 @@ describe("Reflect.decorate", () => { it("ExecutesDecoratorsInReverseOrderForPropertyDescriptorOverload", () => { let order: number[] = []; let decorators = [ - (target: Object, name: string | symbol): void => { order.push(0); }, - (target: Object, name: string | symbol): void => { order.push(1); } + (_target: Object, _name: string | symbol): void => { order.push(0); }, + (_target: Object, _name: string | symbol): void => { order.push(1); } ]; let target = {}; let name = "name"; @@ -83,9 +83,9 @@ describe("Reflect.decorate", () => { let A = function A(): void { }; let B = function B(): void { }; let decorators = [ - (target: Function): any => { return undefined; }, - (target: Function): any => { return A; }, - (target: Function): any => { return B; } + (_target: Function): any => { return undefined; }, + (_target: Function): any => { return A; }, + (_target: Function): any => { return B; } ]; let target = function (): void { }; let result = Reflect.decorate(decorators, target); @@ -96,9 +96,9 @@ describe("Reflect.decorate", () => { let A = {}; let B = {}; let decorators = [ - (target: Object, name: string | symbol): any => { return undefined; }, - (target: Object, name: string | symbol): any => { return A; }, - (target: Object, name: string | symbol): any => { return B; } + (_target: Object, _name: string | symbol): any => { return undefined; }, + (_target: Object, _name: string | symbol): any => { return A; }, + (_target: Object, _name: string | symbol): any => { return B; } ]; let target = {}; let result = Reflect.decorate(decorators, target, "name", undefined); @@ -110,9 +110,9 @@ describe("Reflect.decorate", () => { let B = {}; let C = {}; let decorators = [ - (target: Object, name: string | symbol): any => { return undefined; }, - (target: Object, name: string | symbol): any => { return A; }, - (target: Object, name: string | symbol): any => { return B; } + (_target: Object, _name: string | symbol): any => { return undefined; }, + (_target: Object, _name: string | symbol): any => { return A; }, + (_target: Object, _name: string | symbol): any => { return B; } ]; let target = {}; let result = Reflect.decorate(decorators, target, "name", C); @@ -137,10 +137,10 @@ describe("Reflect.decorate", () => { it("DecoratorCorrectTargetInPipelineForPropertyOverload", () => { let sent: Object[] = []; let decorators = [ - (target: Object, name: string | symbol): any => { sent.push(target); }, - (target: Object, name: string | symbol): any => { sent.push(target); }, - (target: Object, name: string | symbol): any => { sent.push(target); }, - (target: Object, name: string | symbol): any => { sent.push(target); } + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); } ]; let target = { }; Reflect.decorate(decorators, target, "name"); @@ -150,10 +150,10 @@ describe("Reflect.decorate", () => { it("DecoratorCorrectNameInPipelineForPropertyOverload", () => { let sent: (symbol | string)[] = []; let decorators = [ - (target: Object, name: string | symbol): any => { sent.push(name); }, - (target: Object, name: string | symbol): any => { sent.push(name); }, - (target: Object, name: string | symbol): any => { sent.push(name); }, - (target: Object, name: string | symbol): any => { sent.push(name); } + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); } ]; let target = { }; Reflect.decorate(decorators, target, "name"); @@ -166,10 +166,10 @@ describe("Reflect.decorate", () => { let B = { }; let C = { }; let decorators = [ - (target: Object, name: string | symbol): any => { sent.push(target); return undefined; }, - (target: Object, name: string | symbol): any => { sent.push(target); return undefined; }, - (target: Object, name: string | symbol): any => { sent.push(target); return A; }, - (target: Object, name: string | symbol): any => { sent.push(target); return B; } + (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return A; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return B; } ]; let target = { }; Reflect.decorate(decorators, target, "name", C); @@ -182,10 +182,10 @@ describe("Reflect.decorate", () => { let B = { }; let C = { }; let decorators = [ - (target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, - (target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, - (target: Object, name: string | symbol): any => { sent.push(name); return A; }, - (target: Object, name: string | symbol): any => { sent.push(name); return B; } + (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return A; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return B; } ]; let target = { }; Reflect.decorate(decorators, target, "name", C); @@ -198,10 +198,10 @@ describe("Reflect.decorate", () => { let B = { }; let C = { }; let decorators = [ - (target: Object, name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, - (target: Object, name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, - (target: Object, name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return A; }, - (target: Object, name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return B; } + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return A; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return B; } ]; let target = { }; Reflect.decorate(decorators, target, "name", C); diff --git a/test/reflect-definemetadata.ts b/test/no-conflict/reflect-definemetadata.ts similarity index 81% rename from test/reflect-definemetadata.ts rename to test/no-conflict/reflect-definemetadata.ts index 320b1f6..5f98e2e 100644 --- a/test/reflect-definemetadata.ts +++ b/test/no-conflict/reflect-definemetadata.ts @@ -1,16 +1,16 @@ // 4.1.2 Reflect.defineMetadata ( metadataKey, metadataValue, target, propertyKey ) // https://rbuckton.github.io/reflect-metadata/#reflect.definemetadata -import "../Reflect"; +const Reflect = require("../../ReflectNoConflict"); import { assert } from "chai"; describe("Reflect.defineMetadata", () => { it("InvalidTarget", () => { - assert.throws(() => Reflect.defineMetadata("key", "value", undefined, undefined), TypeError); + assert.throws(() => Reflect.defineMetadata("key", "value", undefined, undefined!), TypeError); }); it("ValidTargetWithoutTargetKey", () => { - assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, undefined)); + assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, undefined!)); }); it("ValidTargetWithTargetKey", () => { diff --git a/test/reflect-deletemetadata.ts b/test/no-conflict/reflect-deletemetadata.ts similarity index 77% rename from test/reflect-deletemetadata.ts rename to test/no-conflict/reflect-deletemetadata.ts index 3612e51..cd704ce 100644 --- a/test/reflect-deletemetadata.ts +++ b/test/no-conflict/reflect-deletemetadata.ts @@ -1,40 +1,40 @@ // 4.1.10 Reflect.deleteMetadata ( metadataKey, target [, propertyKey] ) // https://rbuckton.github.io/reflect-metadata/#reflect.deletemetadata -import "../Reflect"; +const Reflect = require("../../ReflectNoConflict"); import { assert } from "chai"; describe("Reflect.deleteMetadata", () => { it("InvalidTarget", () => { - assert.throws(() => Reflect.deleteMetadata("key", undefined, undefined), TypeError); + assert.throws(() => Reflect.deleteMetadata("key", undefined, undefined!), TypeError); }); it("WhenNotDefinedWithoutTargetKey", () => { let obj = {}; - let result = Reflect.deleteMetadata("key", obj, undefined); + let result = Reflect.deleteMetadata("key", obj, undefined!); assert.equal(result, false); }); it("WhenDefinedWithoutTargetKey", () => { let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined); - let result = Reflect.deleteMetadata("key", obj, undefined); + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.deleteMetadata("key", obj, undefined!); assert.equal(result, true); }); it("WhenDefinedOnPrototypeWithoutTargetKey", () => { let prototype = {}; - Reflect.defineMetadata("key", "value", prototype, undefined); + Reflect.defineMetadata("key", "value", prototype, undefined!); let obj = Object.create(prototype); - let result = Reflect.deleteMetadata("key", obj, undefined); + let result = Reflect.deleteMetadata("key", obj, undefined!); assert.equal(result, false); }); it("AfterDeleteMetadata", () => { let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined); - Reflect.deleteMetadata("key", obj, undefined); - let result = Reflect.hasOwnMetadata("key", obj, undefined); + Reflect.defineMetadata("key", "value", obj, undefined!); + Reflect.deleteMetadata("key", obj, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); assert.equal(result, false); }); }); \ No newline at end of file diff --git a/test/reflect-getmetadata.ts b/test/no-conflict/reflect-getmetadata.ts similarity index 80% rename from test/reflect-getmetadata.ts rename to test/no-conflict/reflect-getmetadata.ts index 5b85635..7c3ef9b 100644 --- a/test/reflect-getmetadata.ts +++ b/test/no-conflict/reflect-getmetadata.ts @@ -1,32 +1,32 @@ // 4.1.5 Reflect.getMetadata ( metadataKey, target [, propertyKey] ) // https://rbuckton.github.io/reflect-metadata/#reflect.getmetadata -import "../Reflect"; +const Reflect = require("../../ReflectNoConflict"); import { assert } from "chai"; describe("Reflect.getMetadata", () => { it("InvalidTarget", () => { - assert.throws(() => Reflect.getMetadata("key", undefined, undefined), TypeError); + assert.throws(() => Reflect.getMetadata("key", undefined, undefined!), TypeError); }); it("WithoutTargetKeyWhenNotDefined", () => { let obj = {}; - let result = Reflect.getMetadata("key", obj, undefined); + let result = Reflect.getMetadata("key", obj, undefined!); assert.equal(result, undefined); }); it("WithoutTargetKeyWhenDefined", () => { let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined); - let result = Reflect.getMetadata("key", obj, undefined); + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getMetadata("key", obj, undefined!); assert.equal(result, "value"); }); it("WithoutTargetKeyWhenDefinedOnPrototype", () => { let prototype = {}; let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined); - let result = Reflect.getMetadata("key", obj, undefined); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getMetadata("key", obj, undefined!); assert.equal(result, "value"); }); diff --git a/test/reflect-getmetadatakeys.ts b/test/no-conflict/reflect-getmetadatakeys.ts similarity index 73% rename from test/reflect-getmetadatakeys.ts rename to test/no-conflict/reflect-getmetadatakeys.ts index 7a8bb30..f07cf39 100644 --- a/test/reflect-getmetadatakeys.ts +++ b/test/no-conflict/reflect-getmetadatakeys.ts @@ -1,60 +1,60 @@ // 4.1.8 Reflect.getMetadataKeys ( target [, propertyKey] ) // https://rbuckton.github.io/reflect-metadata/#reflect.getmetadatakeys -import "../Reflect"; +const Reflect = require("../../ReflectNoConflict"); import { assert } from "chai"; describe("Reflect.getMetadataKeys", () => { it("KeysInvalidTarget", () => { // 1. If Type(target) is not Object, throw a TypeError exception. - assert.throws(() => Reflect.getMetadataKeys(undefined, undefined), TypeError); + assert.throws(() => Reflect.getMetadataKeys(undefined, undefined!), TypeError); }); it("KeysWithoutTargetKeyWhenNotDefined", () => { let obj = {}; - let result = Reflect.getMetadataKeys(obj, undefined); + let result = Reflect.getMetadataKeys(obj, undefined!); assert.deepEqual(result, []); }); it("KeysWithoutTargetKeyWhenDefined", () => { let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined); - let result = Reflect.getMetadataKeys(obj, undefined); + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); assert.deepEqual(result, ["key"]); }); it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { let prototype = {}; let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined); - let result = Reflect.getMetadataKeys(obj, undefined); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); assert.deepEqual(result, ["key"]); }); it("KeysOrderWithoutTargetKey", () => { let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined); - Reflect.defineMetadata("key0", "value", obj, undefined); - let result = Reflect.getMetadataKeys(obj, undefined); + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); assert.deepEqual(result, ["key1", "key0"]); }); it("KeysOrderAfterRedefineWithoutTargetKey", () => { let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined); - Reflect.defineMetadata("key0", "value", obj, undefined); - Reflect.defineMetadata("key1", "value", obj, undefined); - let result = Reflect.getMetadataKeys(obj, undefined); + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + Reflect.defineMetadata("key1", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); assert.deepEqual(result, ["key1", "key0"]); }); it("KeysOrderWithoutTargetKeyWhenDefinedOnPrototype", () => { let prototype = {}; - Reflect.defineMetadata("key2", "value", prototype, undefined); + Reflect.defineMetadata("key2", "value", prototype, undefined!); let obj = Object.create(prototype); - Reflect.defineMetadata("key1", "value", obj, undefined); - Reflect.defineMetadata("key0", "value", obj, undefined); - let result = Reflect.getMetadataKeys(obj, undefined); + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); assert.deepEqual(result, ["key1", "key0", "key2"]); }); diff --git a/test/reflect-getownmetadata.ts b/test/no-conflict/reflect-getownmetadata.ts similarity index 88% rename from test/reflect-getownmetadata.ts rename to test/no-conflict/reflect-getownmetadata.ts index 856f2fb..496a814 100644 --- a/test/reflect-getownmetadata.ts +++ b/test/no-conflict/reflect-getownmetadata.ts @@ -1,32 +1,32 @@ // 4.1.7 Reflect.getOwnMetadata ( metadataKey, target [, propertyKey] ) // https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadata -import "../Reflect"; +const Reflect = require("../../ReflectNoConflict"); import { assert } from "chai"; describe("Reflect.getOwnMetadata", () => { it("InvalidTarget", () => { - assert.throws(() => Reflect.getOwnMetadata("key", undefined, undefined), TypeError); + assert.throws(() => Reflect.getOwnMetadata("key", undefined, undefined!), TypeError); }); it("WithoutTargetKeyWhenNotDefined", () => { let obj = {}; - let result = Reflect.getOwnMetadata("key", obj, undefined); + let result = Reflect.getOwnMetadata("key", obj, undefined!); assert.equal(result, undefined); }); it("WithoutTargetKeyWhenDefined", () => { let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined); - let result = Reflect.getOwnMetadata("key", obj, undefined); + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getOwnMetadata("key", obj, undefined!); assert.equal(result, "value"); }); it("WithoutTargetKeyWhenDefinedOnPrototype", () => { let prototype = {}; let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined); - let result = Reflect.getOwnMetadata("key", obj, undefined); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getOwnMetadata("key", obj, undefined!); assert.equal(result, undefined); }); diff --git a/test/reflect-getownmetadatakeys.ts b/test/no-conflict/reflect-getownmetadatakeys.ts similarity index 70% rename from test/reflect-getownmetadatakeys.ts rename to test/no-conflict/reflect-getownmetadatakeys.ts index 16eeb86..3af293e 100644 --- a/test/reflect-getownmetadatakeys.ts +++ b/test/no-conflict/reflect-getownmetadatakeys.ts @@ -1,50 +1,50 @@ // 4.1.9 Reflect.getOwnMetadataKeysKeys ( target [, propertyKey] ) // https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadatakeys -import "../Reflect"; +const Reflect = require("../../ReflectNoConflict"); import { assert } from "chai"; -describe("Reflect.deleteMetadata", () => { +describe("Reflect.getOwnMetadataKeys", () => { it("KeysKeysInvalidTarget", () => { // 1. If Type(target) is not Object, throw a TypeError exception. - assert.throws(() => Reflect.getOwnMetadataKeys(undefined, undefined), TypeError); + assert.throws(() => Reflect.getOwnMetadataKeys(undefined, undefined!), TypeError); }); it("KeysWithoutTargetKeyWhenNotDefined", () => { let obj = {}; - let result = Reflect.getOwnMetadataKeys(obj, undefined); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); assert.deepEqual(result, []); }); it("KeysWithoutTargetKeyWhenDefined", () => { let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined); - let result = Reflect.getOwnMetadataKeys(obj, undefined); + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); assert.deepEqual(result, ["key"]); }); it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { let prototype = {}; let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined); - let result = Reflect.getOwnMetadataKeys(obj, undefined); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); assert.deepEqual(result, []); }); it("KeysOrderWithoutTargetKey", () => { let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined); - Reflect.defineMetadata("key0", "value", obj, undefined); - let result = Reflect.getOwnMetadataKeys(obj, undefined); + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); assert.deepEqual(result, ["key1", "key0"]); }); it("KeysOrderAfterRedefineWithoutTargetKey", () => { let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined); - Reflect.defineMetadata("key0", "value", obj, undefined); - Reflect.defineMetadata("key1", "value", obj, undefined); - let result = Reflect.getOwnMetadataKeys(obj, undefined); + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + Reflect.defineMetadata("key1", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); assert.deepEqual(result, ["key1", "key0"]); }); diff --git a/test/reflect-hasmetadata.ts b/test/no-conflict/reflect-hasmetadata.ts similarity index 78% rename from test/reflect-hasmetadata.ts rename to test/no-conflict/reflect-hasmetadata.ts index 8a9825c..8d17b08 100644 --- a/test/reflect-hasmetadata.ts +++ b/test/no-conflict/reflect-hasmetadata.ts @@ -1,32 +1,32 @@ // 4.1.4 Reflect.hasMetadata ( metadataKey, target [, propertyKey] ) // https://rbuckton.github.io/reflect-metadata/#reflect.hasmetadata -import "../Reflect"; +const Reflect = require("../../ReflectNoConflict"); import { assert } from "chai"; describe("Reflect.hasMetadata", () => { it("InvalidTarget", () => { - assert.throws(() => Reflect.hasMetadata("key", undefined, undefined), TypeError); + assert.throws(() => Reflect.hasMetadata("key", undefined, undefined!), TypeError); }); it("WithoutTargetKeyWhenNotDefined", () => { let obj = {}; - let result = Reflect.hasMetadata("key", obj, undefined); + let result = Reflect.hasMetadata("key", obj, undefined!); assert.equal(result, false); }); it("WithoutTargetKeyWhenDefined", () => { let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined); - let result = Reflect.hasMetadata("key", obj, undefined); + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.hasMetadata("key", obj, undefined!); assert.equal(result, true); }); it("WithoutTargetKeyWhenDefinedOnPrototype", () => { let prototype = {}; let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined); - let result = Reflect.hasMetadata("key", obj, undefined); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.hasMetadata("key", obj, undefined!); assert.equal(result, true); }); diff --git a/test/reflect-hasownmetadata.ts b/test/no-conflict/reflect-hasownmetadata.ts similarity index 88% rename from test/reflect-hasownmetadata.ts rename to test/no-conflict/reflect-hasownmetadata.ts index 6ce4954..ace42a4 100644 --- a/test/reflect-hasownmetadata.ts +++ b/test/no-conflict/reflect-hasownmetadata.ts @@ -1,32 +1,32 @@ // 4.1.5 Reflect.hasOwnMetadata ( metadataKey, target [, propertyKey] ) // https://rbuckton.github.io/reflect-metadata/#reflect.hasownmetadata -import "../Reflect"; +const Reflect = require("../../ReflectNoConflict"); import { assert } from "chai"; describe("Reflect.hasOwnMetadata", () => { it("InvalidTarget", () => { - assert.throws(() => Reflect.hasOwnMetadata("key", undefined, undefined), TypeError); + assert.throws(() => Reflect.hasOwnMetadata("key", undefined, undefined!), TypeError); }); it("WithoutTargetKeyWhenNotDefined", () => { let obj = {}; - let result = Reflect.hasOwnMetadata("key", obj, undefined); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); assert.equal(result, false); }); it("WithoutTargetKeyWhenDefined", () => { let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined); - let result = Reflect.hasOwnMetadata("key", obj, undefined); + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); assert.equal(result, true); }); it("WithoutTargetKeyWhenDefinedOnPrototype", () => { let prototype = {}; let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined); - let result = Reflect.hasOwnMetadata("key", obj, undefined); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); assert.equal(result, false); }); diff --git a/test/no-conflict/reflect-metadata.ts b/test/no-conflict/reflect-metadata.ts new file mode 100644 index 0000000..a0014af --- /dev/null +++ b/test/no-conflict/reflect-metadata.ts @@ -0,0 +1,41 @@ +// 4.1.2 Reflect.metadata ( metadataKey, metadataValue ) +// https://rbuckton.github.io/reflect-metadata/#reflect.metadata + +/// +const Reflect_ = require("../../ReflectNoConflict") as typeof Reflect; +import { assert } from "chai"; + +describe("Reflect.metadata", () => { + it("ReturnsDecoratorFunction", () => { + let result = Reflect_.metadata("key", "value"); + assert.equal(typeof result, "function"); + }); + + it("DecoratorThrowsWithInvalidTargetWithTargetKey", () => { + let decorator = Reflect_.metadata("key", "value"); + assert.throws(() => decorator(undefined, "name"), TypeError); + }); + + it("DecoratorThrowsWithInvalidTargetKey", () => { + let decorator = Reflect_.metadata("key", "value"); + assert.throws(() => decorator({}, {}), TypeError); + }); + + it("OnTargetWithoutTargetKey", () => { + let decorator = Reflect_.metadata("key", "value"); + let target = function () {} + decorator(target); + + let result = Reflect_.hasOwnMetadata("key", target, undefined!); + assert.equal(result, true); + }); + + it("OnTargetWithTargetKey", () => { + let decorator = Reflect_.metadata("key", "value"); + let target = {} + decorator(target, "name"); + + let result = Reflect_.hasOwnMetadata("key", target, "name"); + assert.equal(result, true); + }); +}); \ No newline at end of file diff --git a/test/tsconfig.json b/test/tsconfig.json index 53e30f3..609ebe8 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -5,8 +5,7 @@ "sourceMap": true, "module": "commonjs", "types": ["node", "mocha"], - "typeRoots": ["../../node_modules/@types"], - "rootDir": "." + "typeRoots": ["../node_modules/@types"], }, "include": [ "**/*.ts" diff --git a/tsconfig-release.json b/tsconfig-release.json index 733808d..a99678e 100644 --- a/tsconfig-release.json +++ b/tsconfig-release.json @@ -1,17 +1,20 @@ { - "compilerOptions": { - "target": "es5", - "module": "commonjs", - "newLine": "LF", - "sourceMap": false, - "strictNullChecks": true, - "noImplicitAny": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noImplicitThis": true - }, - "files": [ - "Reflect.ts" - ] - } \ No newline at end of file + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "newLine": "LF", + "sourceMap": false, + "strictNullChecks": true, + "noImplicitAny": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noImplicitThis": true + }, + "files": [ + "globals.d.ts", + "Reflect.ts", + "ReflectLite.ts", + "ReflectNoConflict.ts", + ] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 30ef258..b636e9b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,9 @@ "noImplicitThis": true }, "files": [ - "Reflect.ts" + "globals.d.ts", + "Reflect.ts", + "ReflectLite.ts", + "ReflectNoConflict.ts", ] } \ No newline at end of file diff --git a/typings.d.ts b/typings.d.ts deleted file mode 100644 index d19ee2c..0000000 --- a/typings.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*! ***************************************************************************** -Copyright (C) Microsoft. All rights reserved. -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ - -// NOTE: This file is obsolete and may be removed in a later release. -// For CommonJS/AMD/UMD/SystemJS declarations please use 'index.d.ts'. -// For standalone browser declarations, please use 'standalone.d.ts'. - -import "./reflect-metadata"; \ No newline at end of file From 83fc28b93cb9a72b92691c0bd9913057699fc595 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 7 Dec 2023 17:29:38 -0500 Subject: [PATCH 2/8] Add fallback to no-conflict version --- ReflectNoConflict.ts | 27 +++++++++++++++++++++++++++ test/full/reflect-metadata.ts | 2 +- test/lite/reflect-metadata.ts | 2 +- test/no-conflict/reflect-metadata.ts | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/ReflectNoConflict.ts b/ReflectNoConflict.ts index 1010f56..819bc28 100644 --- a/ReflectNoConflict.ts +++ b/ReflectNoConflict.ts @@ -222,6 +222,9 @@ export function decorate(decorators: (ClassDecorator | MemberDecorator)[], targe * */ export function metadata(metadataKey: any, metadataValue: any): { (target: Function): void; (target: any, propertyKey: string | symbol): void; } { + if (typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata !== metadata) { + return Reflect.metadata(metadataKey, metadataValue); + } function decorator(target: Function): void; function decorator(target: any, propertyKey: string | symbol): void; function decorator(target: any, propertyKey?: string | symbol): void { @@ -333,6 +336,9 @@ export function defineMetadata(metadataKey: any, metadataValue: any, target: any * */ export function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey?: string | symbol): void { + if (typeof Reflect !== "undefined" && typeof Reflect.defineMetadata === "function" && Reflect.defineMetadata !== defineMetadata) { + return Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey!); + } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey); @@ -424,6 +430,9 @@ export function hasMetadata(metadataKey: any, target: any, propertyKey: string | * */ export function hasMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { + if (typeof Reflect !== "undefined" && typeof Reflect.hasMetadata === "function" && Reflect.hasMetadata !== hasMetadata) { + return Reflect.hasMetadata(metadataKey, target, propertyKey!); + } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryHasMetadata(metadataKey, target, propertyKey); @@ -515,6 +524,9 @@ export function hasOwnMetadata(metadataKey: any, target: any, propertyKey: strin * */ export function hasOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { + if (typeof Reflect !== "undefined" && typeof Reflect.hasOwnMetadata === "function" && Reflect.hasOwnMetadata !== hasOwnMetadata) { + return Reflect.hasOwnMetadata(metadataKey, target, propertyKey!); + } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryHasOwnMetadata(metadataKey, target, propertyKey); @@ -606,6 +618,9 @@ export function getMetadata(metadataKey: any, target: any, propertyKey: string | * */ export function getMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any { + if (typeof Reflect !== "undefined" && typeof Reflect.getMetadata === "function" && Reflect.getMetadata !== getMetadata) { + return Reflect.getMetadata(metadataKey, target, propertyKey!); + } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryGetMetadata(metadataKey, target, propertyKey); @@ -697,6 +712,9 @@ export function getOwnMetadata(metadataKey: any, target: any, propertyKey: strin * */ export function getOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any { + if (typeof Reflect !== "undefined" && typeof Reflect.getOwnMetadata === "function" && Reflect.getOwnMetadata !== getOwnMetadata) { + return Reflect.getOwnMetadata(metadataKey, target, propertyKey!); + } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryGetOwnMetadata(metadataKey, target, propertyKey); @@ -785,6 +803,9 @@ export function getMetadataKeys(target: any, propertyKey: string | symbol): any[ * */ export function getMetadataKeys(target: any, propertyKey?: string | symbol): any[] { + if (typeof Reflect !== "undefined" && typeof Reflect.getMetadataKeys === "function" && Reflect.getMetadataKeys !== getMetadataKeys) { + return Reflect.getMetadataKeys(target, propertyKey!); + } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryMetadataKeys(target, propertyKey); @@ -873,6 +894,9 @@ export function getOwnMetadataKeys(target: any, propertyKey: string | symbol): a * */ export function getOwnMetadataKeys(target: any, propertyKey?: string | symbol): any[] { + if (typeof Reflect !== "undefined" && typeof Reflect.getOwnMetadataKeys === "function" && Reflect.getOwnMetadataKeys !== getOwnMetadataKeys) { + return Reflect.getOwnMetadataKeys(target, propertyKey!); + } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryOwnMetadataKeys(target, propertyKey); @@ -964,6 +988,9 @@ export function deleteMetadata(metadataKey: any, target: any, propertyKey: strin * */ export function deleteMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { + if (typeof Reflect !== "undefined" && typeof Reflect.deleteMetadata === "function" && Reflect.deleteMetadata !== deleteMetadata) { + return Reflect.deleteMetadata(metadataKey, target, propertyKey!); + } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); const metadataMap = GetOrCreateMetadataMap(target, propertyKey, /*Create*/ false); diff --git a/test/full/reflect-metadata.ts b/test/full/reflect-metadata.ts index 1542a43..0d56ead 100644 --- a/test/full/reflect-metadata.ts +++ b/test/full/reflect-metadata.ts @@ -13,7 +13,7 @@ describe("Reflect.metadata", () => { it("DecoratorThrowsWithInvalidTargetWithTargetKey", () => { let decorator = Reflect.metadata("key", "value"); - assert.throws(() => decorator(undefined, "name"), TypeError); + assert.throws(() => decorator(undefined!, "name"), TypeError); }); it("DecoratorThrowsWithInvalidTargetKey", () => { diff --git a/test/lite/reflect-metadata.ts b/test/lite/reflect-metadata.ts index 90b8d0f..e502d9b 100644 --- a/test/lite/reflect-metadata.ts +++ b/test/lite/reflect-metadata.ts @@ -13,7 +13,7 @@ describe("Reflect.metadata", () => { it("DecoratorThrowsWithInvalidTargetWithTargetKey", () => { let decorator = Reflect.metadata("key", "value"); - assert.throws(() => decorator(undefined, "name"), TypeError); + assert.throws(() => decorator(undefined!, "name"), TypeError); }); it("DecoratorThrowsWithInvalidTargetKey", () => { diff --git a/test/no-conflict/reflect-metadata.ts b/test/no-conflict/reflect-metadata.ts index a0014af..05f133f 100644 --- a/test/no-conflict/reflect-metadata.ts +++ b/test/no-conflict/reflect-metadata.ts @@ -13,7 +13,7 @@ describe("Reflect.metadata", () => { it("DecoratorThrowsWithInvalidTargetWithTargetKey", () => { let decorator = Reflect_.metadata("key", "value"); - assert.throws(() => decorator(undefined, "name"), TypeError); + assert.throws(() => decorator(undefined!, "name"), TypeError); }); it("DecoratorThrowsWithInvalidTargetKey", () => { From bdab024135474851b88a2c32d183ec103e1890d2 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 7 Dec 2023 17:30:41 -0500 Subject: [PATCH 3/8] package.json cleanup --- package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/package.json b/package.json index 8ee989f..c5ce92b 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,6 @@ "type": "commonjs", "main": "Reflect.js", "types": "index.d.ts", - "typescript": { - "definition": "Reflect.d.ts" - }, "exports": { ".": { "import": { From 977503cedfd1ec4bce2e8e8a7defd40256c1f2c7 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 7 Dec 2023 17:40:07 -0500 Subject: [PATCH 4/8] /no-conflict only defers to global Reflect if it hasn't already been used --- ReflectNoConflict.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ReflectNoConflict.ts b/ReflectNoConflict.ts index 819bc28..86d1299 100644 --- a/ReflectNoConflict.ts +++ b/ReflectNoConflict.ts @@ -32,6 +32,7 @@ const _WeakMap: typeof WeakMap = typeof WeakMap === "function" ? WeakMap : fail( // [[Metadata]] internal slot // https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots const Metadata = new _WeakMap>>(); +let hasSetMetadata = false; /** * Applies a set of decorators to a target object. @@ -336,7 +337,7 @@ export function defineMetadata(metadataKey: any, metadataValue: any, target: any * */ export function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey?: string | symbol): void { - if (typeof Reflect !== "undefined" && typeof Reflect.defineMetadata === "function" && Reflect.defineMetadata !== defineMetadata) { + if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.defineMetadata === "function" && Reflect.defineMetadata !== defineMetadata) { return Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey!); } if (!IsObject(target)) throw new TypeError(); @@ -430,7 +431,7 @@ export function hasMetadata(metadataKey: any, target: any, propertyKey: string | * */ export function hasMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { - if (typeof Reflect !== "undefined" && typeof Reflect.hasMetadata === "function" && Reflect.hasMetadata !== hasMetadata) { + if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.hasMetadata === "function" && Reflect.hasMetadata !== hasMetadata) { return Reflect.hasMetadata(metadataKey, target, propertyKey!); } if (!IsObject(target)) throw new TypeError(); @@ -524,7 +525,7 @@ export function hasOwnMetadata(metadataKey: any, target: any, propertyKey: strin * */ export function hasOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { - if (typeof Reflect !== "undefined" && typeof Reflect.hasOwnMetadata === "function" && Reflect.hasOwnMetadata !== hasOwnMetadata) { + if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.hasOwnMetadata === "function" && Reflect.hasOwnMetadata !== hasOwnMetadata) { return Reflect.hasOwnMetadata(metadataKey, target, propertyKey!); } if (!IsObject(target)) throw new TypeError(); @@ -618,7 +619,7 @@ export function getMetadata(metadataKey: any, target: any, propertyKey: string | * */ export function getMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any { - if (typeof Reflect !== "undefined" && typeof Reflect.getMetadata === "function" && Reflect.getMetadata !== getMetadata) { + if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.getMetadata === "function" && Reflect.getMetadata !== getMetadata) { return Reflect.getMetadata(metadataKey, target, propertyKey!); } if (!IsObject(target)) throw new TypeError(); @@ -712,7 +713,7 @@ export function getOwnMetadata(metadataKey: any, target: any, propertyKey: strin * */ export function getOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any { - if (typeof Reflect !== "undefined" && typeof Reflect.getOwnMetadata === "function" && Reflect.getOwnMetadata !== getOwnMetadata) { + if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.getOwnMetadata === "function" && Reflect.getOwnMetadata !== getOwnMetadata) { return Reflect.getOwnMetadata(metadataKey, target, propertyKey!); } if (!IsObject(target)) throw new TypeError(); @@ -803,7 +804,7 @@ export function getMetadataKeys(target: any, propertyKey: string | symbol): any[ * */ export function getMetadataKeys(target: any, propertyKey?: string | symbol): any[] { - if (typeof Reflect !== "undefined" && typeof Reflect.getMetadataKeys === "function" && Reflect.getMetadataKeys !== getMetadataKeys) { + if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.getMetadataKeys === "function" && Reflect.getMetadataKeys !== getMetadataKeys) { return Reflect.getMetadataKeys(target, propertyKey!); } if (!IsObject(target)) throw new TypeError(); @@ -894,7 +895,7 @@ export function getOwnMetadataKeys(target: any, propertyKey: string | symbol): a * */ export function getOwnMetadataKeys(target: any, propertyKey?: string | symbol): any[] { - if (typeof Reflect !== "undefined" && typeof Reflect.getOwnMetadataKeys === "function" && Reflect.getOwnMetadataKeys !== getOwnMetadataKeys) { + if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.getOwnMetadataKeys === "function" && Reflect.getOwnMetadataKeys !== getOwnMetadataKeys) { return Reflect.getOwnMetadataKeys(target, propertyKey!); } if (!IsObject(target)) throw new TypeError(); @@ -988,7 +989,7 @@ export function deleteMetadata(metadataKey: any, target: any, propertyKey: strin * */ export function deleteMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { - if (typeof Reflect !== "undefined" && typeof Reflect.deleteMetadata === "function" && Reflect.deleteMetadata !== deleteMetadata) { + if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.deleteMetadata === "function" && Reflect.deleteMetadata !== deleteMetadata) { return Reflect.deleteMetadata(metadataKey, target, propertyKey!); } if (!IsObject(target)) throw new TypeError(); @@ -1038,6 +1039,7 @@ function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: if (!Create) return undefined; targetMetadata = new _Map>(); Metadata.set(O, targetMetadata); + hasSetMetadata = true; } let metadataMap = targetMetadata.get(P); if (IsUndefined(metadataMap)) { From 6227ddf59080ac402f46ca8cd0e29ba9f9a7184e Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 7 Dec 2023 18:46:47 -0500 Subject: [PATCH 5/8] drop dual CJS/ESM implementation --- gulpfile.js | 14 ++------------ package.json | 30 ++++++------------------------ 2 files changed, 8 insertions(+), 36 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 8539258..efe3851 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -17,15 +17,10 @@ gulp.task("release", () => { project = releaseProject; }); gulp.task("clean", () => del([ "Reflect.js", "Reflect.js.map", - "Reflect.mjs", "ReflectLite.js", "ReflectLite.js.map", - "ReflectLite.mjs", "ReflectNoConflict.js", "ReflectNoConflict.js.map", - "ReflectNoConflict.mjs", - "index.d.mts", - "no-conflict.d.mts", "test/**/*.js", "test/**/*.js.map" ])); @@ -35,12 +30,7 @@ gulp.task("build:reflect", () => gulp .pipe(project()) .pipe(gulp.dest("."))); -gulp.task("build:mjs", ["build:reflect"], () => gulp - .src(["Reflect.js", "ReflectLite.js", "ReflectNoConflict.js", "index.d.ts", "no-conflict.d.ts"]) - .pipe(rename(path => path.extname = path.extname === ".ts" ? ".mts" : ".mjs")) - .pipe(gulp.dest("."))); - -gulp.task("build:tests", ["build:mjs"], () => gulp +gulp.task("build:tests", ["build:reflect"], () => gulp .src(["test/**/*.ts"]) .pipe(tests()) .pipe(gulp.dest("test"))); @@ -55,7 +45,7 @@ gulp.task("build:spec", () => gulp })) .pipe(gulp.dest("docs"))); -gulp.task("build", ["build:reflect", "build:mjs", "build:tests", "build:spec"]); +gulp.task("build", ["build:reflect", "build:tests", "build:spec"]); gulp.task("no-polyfill", () => { process.env["REFLECT_METADATA_USE_MAP_POLYFILL"] = ""; diff --git a/package.json b/package.json index c5ce92b..2cc4df2 100644 --- a/package.json +++ b/package.json @@ -7,34 +7,16 @@ "types": "index.d.ts", "exports": { ".": { - "import": { - "types": "./index.d.mts", - "default": "./Reflect.mjs" - }, - "default": { - "types": "./index.d.ts", - "default": "./Reflect.js" - } + "types": "./index.d.ts", + "default": "./Reflect.js" }, "./lite": { - "import": { - "types": "./index.d.mts", - "default": "./ReflectLite.mjs" - }, - "default": { - "types": "./index.d.ts", - "default": "./ReflectLite.js" - } + "types": "./index.d.ts", + "default": "./ReflectLite.js" }, "./no-conflict": { - "import": { - "types": "./no-conflict.d.mts", - "default": "./ReflectNoConflict.mjs" - }, - "default": { - "types": "./no-conflict.d.ts", - "default": "./ReflectNoConflict.js" - } + "types": "./no-conflict.d.ts", + "default": "./ReflectNoConflict.js" } }, "scripts": { From 31dde5fba00afaea8c08bc9f13b186c069879566 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 8 Dec 2023 17:10:50 -0500 Subject: [PATCH 6/8] Add shared registry for use when multiple versions are loaded --- Reflect.ts | 354 +++++++++++++++++++++++------ ReflectLite.ts | 352 ++++++++++++++++++++++------ ReflectNoConflict.ts | 403 +++++++++++++++++++++++++-------- globals.d.ts | 18 ++ gulpfile.js | 53 ++++- test/{ => full}/tsconfig.json | 2 +- test/lite/tsconfig.json | 13 ++ test/no-conflict/tsconfig.json | 13 ++ test/registry/registry.ts | 31 +++ test/registry/tsconfig.json | 13 ++ 10 files changed, 1011 insertions(+), 241 deletions(-) rename test/{ => full}/tsconfig.json (76%) create mode 100644 test/lite/tsconfig.json create mode 100644 test/no-conflict/tsconfig.json create mode 100644 test/registry/registry.ts create mode 100644 test/registry/tsconfig.json diff --git a/Reflect.ts b/Reflect.ts index c8e1414..701c204 100644 --- a/Reflect.ts +++ b/Reflect.ts @@ -554,7 +554,7 @@ namespace Reflect { */ export declare function deleteMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; - (function (this: any, factory: (exporter: (key: K, value: typeof Reflect[K]) => void) => void) { + (function (this: any, factory: (exporter: (key: K, value: typeof Reflect[K]) => void, root: any) => void) { const root = typeof globalThis === "object" ? globalThis : typeof global === "object" ? global : @@ -570,7 +570,7 @@ namespace Reflect { exporter = makeExporter(root.Reflect, exporter); } - factory(exporter); + factory(exporter, root); function makeExporter(target: typeof Reflect, previous?: (key: K, value: typeof Reflect[K]) => void) { return (key: K, value: typeof Reflect[K]) => { @@ -593,7 +593,7 @@ namespace Reflect { return functionThis() || indirectEvalThis(); } }) - (function (exporter) { + (function (exporter, root) { const hasOwn = Object.prototype.hasOwnProperty; // feature test for Symbol support @@ -628,10 +628,6 @@ namespace Reflect { const _Set: typeof Set = !usePolyfill && typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : CreateSetPolyfill(); const _WeakMap: typeof WeakMap = !usePolyfill && typeof WeakMap === "function" ? WeakMap : CreateWeakMapPolyfill(); - // [[Metadata]] internal slot - // https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots - const Metadata = new _WeakMap>>(); - function decorate(decorators: ClassDecorator[], target: Function): Function; function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined; function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes: PropertyDescriptor): PropertyDescriptor; @@ -1131,15 +1127,11 @@ namespace Reflect { function deleteMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); - const metadataMap = GetOrCreateMetadataMap(target, propertyKey, /*Create*/ false); - if (IsUndefined(metadataMap)) return false; - if (!metadataMap.delete(metadataKey)) return false; - if (metadataMap.size > 0) return true; - const targetMetadata = Metadata.get(target); - targetMetadata.delete(propertyKey); - if (targetMetadata.size > 0) return true; - Metadata.delete(target); - return true; + if (!IsObject(target)) throw new TypeError(); + if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); + const provider = GetMetadataProvider(target, propertyKey, /*Create*/ false); + if (IsUndefined(provider)) return false; + return provider.OrdinaryDeleteMetadata(metadataKey, target, propertyKey); } exporter("deleteMetadata", deleteMetadata); @@ -1168,26 +1160,6 @@ namespace Reflect { return descriptor; } - // 2.1.1 GetOrCreateMetadataMap(O, P, Create) - // https://rbuckton.github.io/reflect-metadata/#getorcreatemetadatamap - function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: true): Map; - function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: false): Map | undefined; - function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: boolean): Map | undefined { - let targetMetadata = Metadata.get(O); - if (IsUndefined(targetMetadata)) { - if (!Create) return undefined; - targetMetadata = new _Map>(); - Metadata.set(O, targetMetadata); - } - let metadataMap = targetMetadata.get(P); - if (IsUndefined(metadataMap)) { - if (!Create) return undefined; - metadataMap = new _Map(); - targetMetadata.set(P, metadataMap); - } - return metadataMap; - } - // 3.1.1.1 OrdinaryHasMetadata(MetadataKey, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinaryhasmetadata function OrdinaryHasMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean { @@ -1201,9 +1173,9 @@ namespace Reflect { // 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata function OrdinaryHasOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean { - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) return false; - return ToBoolean(metadataMap.has(MetadataKey)); + const provider = GetMetadataProvider(O, P, /*Create*/ false); + if (IsUndefined(provider)) return false; + return ToBoolean(provider.OrdinaryHasOwnMetadata(MetadataKey, O, P)); } // 3.1.3.1 OrdinaryGetMetadata(MetadataKey, O, P) @@ -1219,16 +1191,16 @@ namespace Reflect { // 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata function OrdinaryGetOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): any { - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) return undefined; - return metadataMap.get(MetadataKey); + const provider = GetMetadataProvider(O, P, /*Create*/ false); + if (IsUndefined(provider)) return; + return provider.OrdinaryGetOwnMetadata(MetadataKey, O, P); } // 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata function OrdinaryDefineOwnMetadata(MetadataKey: any, MetadataValue: any, O: any, P: string | symbol | undefined): void { - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ true); - metadataMap.set(MetadataKey, MetadataValue); + const provider = GetMetadataProvider(O, P, /*Create*/ true); + provider.OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P); } // 3.1.6.1 OrdinaryMetadataKeys(O, P) @@ -1262,32 +1234,11 @@ namespace Reflect { // 3.1.7.1 OrdinaryOwnMetadataKeys(O, P) // https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys function OrdinaryOwnMetadataKeys(O: any, P: string | symbol | undefined): any[] { - const keys: any[] = []; - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) return keys; - const keysObj = metadataMap.keys(); - const iterator = GetIterator(keysObj); - let k = 0; - while (true) { - const next = IteratorStep(iterator); - if (!next) { - keys.length = k; - return keys; - } - const nextValue = IteratorValue(next); - try { - keys[k] = nextValue; - } - catch (e) { - try { - IteratorClose(iterator); - } - finally { - throw e; - } - } - k++; + const provider = GetMetadataProvider(O, P, /*create*/ false); + if (!provider) { + return []; } + return provider.OrdinaryOwnMetadataKeys(O, P); } // 6 ECMAScript Data Typ0es and Values @@ -1534,6 +1485,271 @@ namespace Reflect { return constructor; } + // Global metadata registry + // - Allows `import "reflect-metadata"` and `import "reflect-metadata/no-conflict"` to interoperate. + // - Uses isolated metadata if `Reflect` is frozen before the registry can be installed. + + const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined; + const metadataRegistry = GetOrCreateMetadataRegistry(); + const metadataProvider = CreateMetadataProvider(metadataRegistry); + + /** + * Creates a registry used to allow multiple `reflect-metadata` providers. + */ + function CreateMetadataRegistry(): MetadataRegistry { + let first: MetadataProvider | undefined; + let second: MetadataProvider | undefined; + let rest: Set | undefined; + const targetProviderMap = new _WeakMap>(); + const registry: MetadataRegistry = { + registerProvider, + getProvider, + setProvider, + }; + return registry; + + function registerProvider(provider: MetadataProvider) { + if (!Object.isExtensible(registry)) { + throw new Error("Cannot add provider to a frozen registry."); + } + switch (true) { + case IsUndefined(first): first = provider; break; + case first === provider: break; + case IsUndefined(second): second = provider; break; + case second === provider: break; + default: + if (rest === undefined) rest = new _Set(); + rest.add(provider); + break; + } + } + + function getProviderNoCache(O: object, P: string | symbol | undefined) { + if (IsUndefined(first)) return undefined; + if (first.isProviderFor(O, P)) return first; + if (IsUndefined(second)) return undefined; + if (second.isProviderFor(O, P)) return first; + if (IsUndefined(rest)) return undefined; + const iterator = GetIterator(rest); + while (true) { + const next = IteratorStep(iterator); + if (!next) { + return undefined; + } + const provider = IteratorValue(next); + if (provider.isProviderFor(O, P)) { + IteratorClose(iterator); + return provider; + } + } + } + + function getProvider(O: object, P: string | symbol | undefined) { + let providerMap = targetProviderMap.get(O); + let provider: MetadataProvider | undefined; + if (!IsUndefined(providerMap)) { + provider = providerMap.get(P); + } + if (!IsUndefined(provider)) { + return provider; + } + + provider = getProviderNoCache(O, P); + if (!IsUndefined(provider)) { + if (IsUndefined(providerMap)) { + providerMap = new _Map(); + targetProviderMap.set(O, providerMap); + } + providerMap.set(P, provider); + } + return provider; + } + + function hasProvider(provider: MetadataProvider) { + return first === provider || second === provider || !IsUndefined(rest) && rest.has(provider); + } + + function setProvider(O: object, P: string | symbol | undefined, provider: MetadataProvider) { + if (!hasProvider(provider)) { + throw new Error("Metadata provider not registered."); + } + const existingProvider = getProvider(O, P); + if (existingProvider !== provider) { + if (!IsUndefined(existingProvider)) { + return false; + } + let providerMap = targetProviderMap.get(O); + if (IsUndefined(providerMap)) { + providerMap = new _Map(); + targetProviderMap.set(O, providerMap); + } + providerMap.set(P, provider); + } + return true; + } + } + + /** + * Gets or creates the shared registry of metadata providers. + */ + function GetOrCreateMetadataRegistry(): MetadataRegistry { + let metadataRegistry: MetadataRegistry | undefined; + if (!IsUndefined(registrySymbol) && IsObject(root.Reflect) && Object.isExtensible(root.Reflect)) { + metadataRegistry = (root.Reflect as any)[registrySymbol] as MetadataRegistry | undefined; + } + if (IsUndefined(metadataRegistry)) { + metadataRegistry = CreateMetadataRegistry(); + } + if (!IsUndefined(registrySymbol) && IsObject(root.Reflect) && Object.isExtensible(root.Reflect)) { + Object.defineProperty(root.Reflect, registrySymbol, { + enumerable: false, + configurable: false, + writable: false, + value: metadataRegistry + }); + } + return metadataRegistry; + } + + function CreateMetadataProvider(registry: MetadataRegistry): MetadataProvider { + // [[Metadata]] internal slot + // https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots + const metadata = new _WeakMap>>(); + const provider: MetadataProvider = { + isProviderFor(O, P) { + const targetMetadata = metadata.get(O); + if (IsUndefined(targetMetadata)) return false; + return targetMetadata.has(P); + }, + OrdinaryDefineOwnMetadata: OrdinaryDefineOwnMetadata, + OrdinaryHasOwnMetadata: OrdinaryHasOwnMetadata, + OrdinaryGetOwnMetadata: OrdinaryGetOwnMetadata, + OrdinaryOwnMetadataKeys: OrdinaryOwnMetadataKeys, + OrdinaryDeleteMetadata: OrdinaryDeleteMetadata, + }; + metadataRegistry.registerProvider(provider); + return provider; + + // 2.1.1 GetOrCreateMetadataMap(O, P, Create) + // https://rbuckton.github.io/reflect-metadata/#getorcreatemetadatamap + function GetOrCreateMetadataMap(O: object, P: string | symbol | undefined, Create: true): Map; + function GetOrCreateMetadataMap(O: object, P: string | symbol | undefined, Create: false): Map | undefined; + function GetOrCreateMetadataMap(O: object, P: string | symbol | undefined, Create: boolean) { + let targetMetadata = metadata.get(O); + let createdTargetMetadata = false; + if (IsUndefined(targetMetadata)) { + if (!Create) return undefined; + targetMetadata = new _Map>(); + metadata.set(O, targetMetadata); + createdTargetMetadata = true; + } + let metadataMap = targetMetadata.get(P); + if (IsUndefined(metadataMap)) { + if (!Create) return undefined; + metadataMap = new _Map(); + targetMetadata.set(P, metadataMap); + if (!registry.setProvider(O, P, provider)) { + targetMetadata.delete(P); + if (createdTargetMetadata) { + metadata.delete(O); + } + throw new Error("Wrong provider for target."); + } + } + return metadataMap; + } + + // 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata + function OrdinaryHasOwnMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): boolean { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return false; + return ToBoolean(metadataMap.has(MetadataKey)); + } + + // 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata + function OrdinaryGetOwnMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): any { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return undefined; + return metadataMap.get(MetadataKey); + } + + // 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata + function OrdinaryDefineOwnMetadata(MetadataKey: any, MetadataValue: any, O: object, P: string | symbol | undefined): void { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ true); + metadataMap.set(MetadataKey, MetadataValue); + } + + // 3.1.7.1 OrdinaryOwnMetadataKeys(O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys + function OrdinaryOwnMetadataKeys(O: any, P: string | symbol | undefined): any[] { + const keys: any[] = []; + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return keys; + const keysObj = metadataMap.keys(); + const iterator = GetIterator(keysObj); + let k = 0; + while (true) { + const next = IteratorStep(iterator); + if (!next) { + keys.length = k; + return keys; + } + const nextValue = IteratorValue(next); + try { + keys[k] = nextValue; + } + catch (e) { + try { + IteratorClose(iterator); + } + finally { + throw e; + } + } + k++; + } + } + + function OrdinaryDeleteMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): boolean { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return false; + if (!metadataMap.delete(MetadataKey)) return false; + if (metadataMap.size === 0) { + const targetMetadata = metadata.get(O); + if (!IsUndefined(targetMetadata)) { + targetMetadata.delete(P); + if (targetMetadata.size === 0) { + metadata.delete(targetMetadata); + } + } + } + return true; + } + } + + function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: true): MetadataProvider; + function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: false): MetadataProvider | undefined; + /** + * Gets the metadata provider for an object. If the object has no metadata provider and this is for a create operation, + * then this module's metadata provider is assigned to the object. + */ + function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: boolean): MetadataProvider | undefined { + const registeredProvider = metadataRegistry.getProvider(O, P); + if (!IsUndefined(registeredProvider)) { + return registeredProvider; + } + if (Create) { + if (metadataRegistry.setProvider(O, P, metadataProvider)) { + return metadataProvider; + } + throw new Error("Illegal state."); + } + return undefined; + } + // naive Map shim function CreateMapPolyfill(): MapConstructor { const cacheSentinel = {}; diff --git a/ReflectLite.ts b/ReflectLite.ts index 78153af..51ad86d 100644 --- a/ReflectLite.ts +++ b/ReflectLite.ts @@ -545,7 +545,7 @@ namespace Reflect { */ export declare function deleteMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean; - (function (this: any, factory: (exporter: (key: K, value: typeof Reflect[K]) => void) => void) { + (function (this: any, factory: (exporter: (key: K, value: typeof Reflect[K]) => void, root: any) => void) { const root = typeof globalThis === "object" ? globalThis : typeof global === "object" ? global : @@ -561,7 +561,7 @@ namespace Reflect { exporter = makeExporter(root.Reflect, exporter); } - factory(exporter); + factory(exporter, root); function makeExporter(target: typeof Reflect, previous?: (key: K, value: typeof Reflect[K]) => void) { return (key: K, value: typeof Reflect[K]) => { @@ -584,7 +584,7 @@ namespace Reflect { return functionThis() || indirectEvalThis(); } }) - (function (exporter) { + (function (exporter, root) { // feature test for Symbol support const supportsSymbol = typeof Symbol === "function"; const toPrimitiveSymbol = supportsSymbol && typeof Symbol.toPrimitive !== "undefined" ? Symbol.toPrimitive : fail("Symbol.toPrimitive not found."); @@ -596,10 +596,6 @@ namespace Reflect { const _Set: typeof Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : fail("A valid Set constructor could not be found."); const _WeakMap: typeof WeakMap = typeof WeakMap === "function" ? WeakMap : fail("A valid WeakMap constructor could not be found."); - // [[Metadata]] internal slot - // https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots - const Metadata = new _WeakMap>>(); - function decorate(decorators: ClassDecorator[], target: Function): Function; function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined; function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes: PropertyDescriptor): PropertyDescriptor; @@ -1099,15 +1095,9 @@ namespace Reflect { function deleteMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); - const metadataMap = GetOrCreateMetadataMap(target, propertyKey, /*Create*/ false); - if (IsUndefined(metadataMap)) return false; - if (!metadataMap.delete(metadataKey)) return false; - if (metadataMap.size > 0) return true; - const targetMetadata = Metadata.get(target); - targetMetadata.delete(propertyKey); - if (targetMetadata.size > 0) return true; - Metadata.delete(target); - return true; + const provider = GetMetadataProvider(target, propertyKey, /*Create*/ false); + if (IsUndefined(provider)) return false; + return provider.OrdinaryDeleteMetadata(metadataKey, target, propertyKey); } exporter("deleteMetadata", deleteMetadata); @@ -1136,26 +1126,6 @@ namespace Reflect { return descriptor; } - // 2.1.1 GetOrCreateMetadataMap(O, P, Create) - // https://rbuckton.github.io/reflect-metadata/#getorcreatemetadatamap - function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: true): Map; - function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: false): Map | undefined; - function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: boolean): Map | undefined { - let targetMetadata = Metadata.get(O); - if (IsUndefined(targetMetadata)) { - if (!Create) return undefined; - targetMetadata = new _Map>(); - Metadata.set(O, targetMetadata); - } - let metadataMap = targetMetadata.get(P); - if (IsUndefined(metadataMap)) { - if (!Create) return undefined; - metadataMap = new _Map(); - targetMetadata.set(P, metadataMap); - } - return metadataMap; - } - // 3.1.1.1 OrdinaryHasMetadata(MetadataKey, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinaryhasmetadata function OrdinaryHasMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean { @@ -1169,9 +1139,9 @@ namespace Reflect { // 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata function OrdinaryHasOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean { - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) return false; - return ToBoolean(metadataMap.has(MetadataKey)); + const provider = GetMetadataProvider(O, P, /*Create*/ false); + if (IsUndefined(provider)) return false; + return ToBoolean(provider.OrdinaryHasOwnMetadata(MetadataKey, O, P)); } // 3.1.3.1 OrdinaryGetMetadata(MetadataKey, O, P) @@ -1187,16 +1157,16 @@ namespace Reflect { // 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata function OrdinaryGetOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): any { - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) return undefined; - return metadataMap.get(MetadataKey); + const provider = GetMetadataProvider(O, P, /*Create*/ false); + if (IsUndefined(provider)) return; + return provider.OrdinaryGetOwnMetadata(MetadataKey, O, P); } // 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata function OrdinaryDefineOwnMetadata(MetadataKey: any, MetadataValue: any, O: any, P: string | symbol | undefined): void { - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ true); - metadataMap.set(MetadataKey, MetadataValue); + const provider = GetMetadataProvider(O, P, /*Create*/ true); + provider.OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P); } // 3.1.6.1 OrdinaryMetadataKeys(O, P) @@ -1230,32 +1200,11 @@ namespace Reflect { // 3.1.7.1 OrdinaryOwnMetadataKeys(O, P) // https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys function OrdinaryOwnMetadataKeys(O: any, P: string | symbol | undefined): any[] { - const keys: any[] = []; - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) return keys; - const keysObj = metadataMap.keys(); - const iterator = GetIterator(keysObj); - let k = 0; - while (true) { - const next = IteratorStep(iterator); - if (!next) { - keys.length = k; - return keys; - } - const nextValue = IteratorValue(next); - try { - keys[k] = nextValue; - } - catch (e) { - try { - IteratorClose(iterator); - } - finally { - throw e; - } - } - k++; + const provider = GetMetadataProvider(O, P, /*create*/ false); + if (!provider) { + return []; } + return provider.OrdinaryOwnMetadataKeys(O, P); } // 6 ECMAScript Data Typ0es and Values @@ -1501,5 +1450,270 @@ namespace Reflect { function fail(e: any): never { throw e; } + + // Global metadata registry + // - Allows `import "reflect-metadata"` and `import "reflect-metadata/no-conflict"` to interoperate. + // - Uses isolated metadata if `Reflect` is frozen before the registry can be installed. + + const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined; + const metadataRegistry = GetOrCreateMetadataRegistry(); + const metadataProvider = CreateMetadataProvider(metadataRegistry); + + /** + * Creates a registry used to allow multiple `reflect-metadata` providers. + */ + function CreateMetadataRegistry(): MetadataRegistry { + let first: MetadataProvider | undefined; + let second: MetadataProvider | undefined; + let rest: Set | undefined; + const targetProviderMap = new _WeakMap>(); + const registry: MetadataRegistry = { + registerProvider, + getProvider, + setProvider, + }; + return registry; + + function registerProvider(provider: MetadataProvider) { + if (!Object.isExtensible(registry)) { + throw new Error("Cannot add provider to a frozen registry."); + } + switch (true) { + case IsUndefined(first): first = provider; break; + case first === provider: break; + case IsUndefined(second): second = provider; break; + case second === provider: break; + default: + if (rest === undefined) rest = new _Set(); + rest.add(provider); + break; + } + } + + function getProviderNoCache(O: object, P: string | symbol | undefined) { + if (IsUndefined(first)) return undefined; + if (first.isProviderFor(O, P)) return first; + if (IsUndefined(second)) return undefined; + if (second.isProviderFor(O, P)) return first; + if (IsUndefined(rest)) return undefined; + const iterator = GetIterator(rest); + while (true) { + const next = IteratorStep(iterator); + if (!next) { + return undefined; + } + const provider = IteratorValue(next); + if (provider.isProviderFor(O, P)) { + IteratorClose(iterator); + return provider; + } + } + } + + function getProvider(O: object, P: string | symbol | undefined) { + let providerMap = targetProviderMap.get(O); + let provider: MetadataProvider | undefined; + if (!IsUndefined(providerMap)) { + provider = providerMap.get(P); + } + if (!IsUndefined(provider)) { + return provider; + } + + provider = getProviderNoCache(O, P); + if (!IsUndefined(provider)) { + if (IsUndefined(providerMap)) { + providerMap = new _Map(); + targetProviderMap.set(O, providerMap); + } + providerMap.set(P, provider); + } + return provider; + } + + function hasProvider(provider: MetadataProvider) { + return first === provider || second === provider || !IsUndefined(rest) && rest.has(provider); + } + + function setProvider(O: object, P: string | symbol | undefined, provider: MetadataProvider) { + if (!hasProvider(provider)) { + throw new Error("Metadata provider not registered."); + } + const existingProvider = getProvider(O, P); + if (existingProvider !== provider) { + if (!IsUndefined(existingProvider)) { + return false; + } + let providerMap = targetProviderMap.get(O); + if (IsUndefined(providerMap)) { + providerMap = new _Map(); + targetProviderMap.set(O, providerMap); + } + providerMap.set(P, provider); + } + return true; + } + } + + /** + * Gets or creates the shared registry of metadata providers. + */ + function GetOrCreateMetadataRegistry(): MetadataRegistry { + let metadataRegistry: MetadataRegistry | undefined; + if (!IsUndefined(registrySymbol) && IsObject(root.Reflect) && Object.isExtensible(root.Reflect)) { + metadataRegistry = (root.Reflect as any)[registrySymbol] as MetadataRegistry | undefined; + } + if (IsUndefined(metadataRegistry)) { + metadataRegistry = CreateMetadataRegistry(); + } + if (!IsUndefined(registrySymbol) && IsObject(root.Reflect) && Object.isExtensible(root.Reflect)) { + Object.defineProperty(root.Reflect, registrySymbol, { + enumerable: false, + configurable: false, + writable: false, + value: metadataRegistry + }); + } + return metadataRegistry; + } + + function CreateMetadataProvider(registry: MetadataRegistry): MetadataProvider { + // [[Metadata]] internal slot + // https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots + const metadata = new _WeakMap>>(); + const provider: MetadataProvider = { + isProviderFor(O, P) { + const targetMetadata = metadata.get(O); + if (IsUndefined(targetMetadata)) return false; + return targetMetadata.has(P); + }, + OrdinaryDefineOwnMetadata: OrdinaryDefineOwnMetadata, + OrdinaryHasOwnMetadata: OrdinaryHasOwnMetadata, + OrdinaryGetOwnMetadata: OrdinaryGetOwnMetadata, + OrdinaryOwnMetadataKeys: OrdinaryOwnMetadataKeys, + OrdinaryDeleteMetadata: OrdinaryDeleteMetadata, + }; + metadataRegistry.registerProvider(provider); + return provider; + + // 2.1.1 GetOrCreateMetadataMap(O, P, Create) + // https://rbuckton.github.io/reflect-metadata/#getorcreatemetadatamap + function GetOrCreateMetadataMap(O: object, P: string | symbol | undefined, Create: true): Map; + function GetOrCreateMetadataMap(O: object, P: string | symbol | undefined, Create: false): Map | undefined; + function GetOrCreateMetadataMap(O: object, P: string | symbol | undefined, Create: boolean) { + let targetMetadata = metadata.get(O); + let createdTargetMetadata = false; + if (IsUndefined(targetMetadata)) { + if (!Create) return undefined; + targetMetadata = new _Map>(); + metadata.set(O, targetMetadata); + createdTargetMetadata = true; + } + let metadataMap = targetMetadata.get(P); + if (IsUndefined(metadataMap)) { + if (!Create) return undefined; + metadataMap = new _Map(); + targetMetadata.set(P, metadataMap); + if (!registry.setProvider(O, P, provider)) { + targetMetadata.delete(P); + if (createdTargetMetadata) { + metadata.delete(O); + } + throw new Error("Wrong provider for target."); + } + } + return metadataMap; + } + + // 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata + function OrdinaryHasOwnMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): boolean { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return false; + return ToBoolean(metadataMap.has(MetadataKey)); + } + + // 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata + function OrdinaryGetOwnMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): any { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return undefined; + return metadataMap.get(MetadataKey); + } + + // 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata + function OrdinaryDefineOwnMetadata(MetadataKey: any, MetadataValue: any, O: object, P: string | symbol | undefined): void { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ true); + metadataMap.set(MetadataKey, MetadataValue); + } + + // 3.1.7.1 OrdinaryOwnMetadataKeys(O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys + function OrdinaryOwnMetadataKeys(O: any, P: string | symbol | undefined): any[] { + const keys: any[] = []; + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return keys; + const keysObj = metadataMap.keys(); + const iterator = GetIterator(keysObj); + let k = 0; + while (true) { + const next = IteratorStep(iterator); + if (!next) { + keys.length = k; + return keys; + } + const nextValue = IteratorValue(next); + try { + keys[k] = nextValue; + } + catch (e) { + try { + IteratorClose(iterator); + } + finally { + throw e; + } + } + k++; + } + } + + function OrdinaryDeleteMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): boolean { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return false; + if (!metadataMap.delete(MetadataKey)) return false; + if (metadataMap.size === 0) { + const targetMetadata = metadata.get(O); + if (!IsUndefined(targetMetadata)) { + targetMetadata.delete(P); + if (targetMetadata.size === 0) { + metadata.delete(targetMetadata); + } + } + } + return true; + } + } + + function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: true): MetadataProvider; + function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: false): MetadataProvider | undefined; + /** + * Gets the metadata provider for an object. If the object has no metadata provider and this is for a create operation, + * then this module's metadata provider is assigned to the object. + */ + function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: boolean): MetadataProvider | undefined { + const registeredProvider = metadataRegistry.getProvider(O, P); + if (!IsUndefined(registeredProvider)) { + return registeredProvider; + } + if (Create) { + if (metadataRegistry.setProvider(O, P, metadataProvider)) { + return metadataProvider; + } + throw new Error("Illegal state."); + } + return undefined; + } }); } diff --git a/ReflectNoConflict.ts b/ReflectNoConflict.ts index 86d1299..9c648eb 100644 --- a/ReflectNoConflict.ts +++ b/ReflectNoConflict.ts @@ -29,11 +29,6 @@ const _Map: typeof Map = typeof Map === "function" && typeof Map.prototype.entri const _Set: typeof Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : fail("A valid Set constructor could not be found."); const _WeakMap: typeof WeakMap = typeof WeakMap === "function" ? WeakMap : fail("A valid WeakMap constructor could not be found."); -// [[Metadata]] internal slot -// https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots -const Metadata = new _WeakMap>>(); -let hasSetMetadata = false; - /** * Applies a set of decorators to a target object. * @param decorators An array of decorators. @@ -337,9 +332,6 @@ export function defineMetadata(metadataKey: any, metadataValue: any, target: any * */ export function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey?: string | symbol): void { - if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.defineMetadata === "function" && Reflect.defineMetadata !== defineMetadata) { - return Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey!); - } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey); @@ -431,9 +423,6 @@ export function hasMetadata(metadataKey: any, target: any, propertyKey: string | * */ export function hasMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { - if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.hasMetadata === "function" && Reflect.hasMetadata !== hasMetadata) { - return Reflect.hasMetadata(metadataKey, target, propertyKey!); - } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryHasMetadata(metadataKey, target, propertyKey); @@ -525,9 +514,6 @@ export function hasOwnMetadata(metadataKey: any, target: any, propertyKey: strin * */ export function hasOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { - if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.hasOwnMetadata === "function" && Reflect.hasOwnMetadata !== hasOwnMetadata) { - return Reflect.hasOwnMetadata(metadataKey, target, propertyKey!); - } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryHasOwnMetadata(metadataKey, target, propertyKey); @@ -619,9 +605,6 @@ export function getMetadata(metadataKey: any, target: any, propertyKey: string | * */ export function getMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any { - if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.getMetadata === "function" && Reflect.getMetadata !== getMetadata) { - return Reflect.getMetadata(metadataKey, target, propertyKey!); - } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryGetMetadata(metadataKey, target, propertyKey); @@ -713,9 +696,6 @@ export function getOwnMetadata(metadataKey: any, target: any, propertyKey: strin * */ export function getOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any { - if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.getOwnMetadata === "function" && Reflect.getOwnMetadata !== getOwnMetadata) { - return Reflect.getOwnMetadata(metadataKey, target, propertyKey!); - } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryGetOwnMetadata(metadataKey, target, propertyKey); @@ -804,9 +784,6 @@ export function getMetadataKeys(target: any, propertyKey: string | symbol): any[ * */ export function getMetadataKeys(target: any, propertyKey?: string | symbol): any[] { - if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.getMetadataKeys === "function" && Reflect.getMetadataKeys !== getMetadataKeys) { - return Reflect.getMetadataKeys(target, propertyKey!); - } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryMetadataKeys(target, propertyKey); @@ -895,9 +872,6 @@ export function getOwnMetadataKeys(target: any, propertyKey: string | symbol): a * */ export function getOwnMetadataKeys(target: any, propertyKey?: string | symbol): any[] { - if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.getOwnMetadataKeys === "function" && Reflect.getOwnMetadataKeys !== getOwnMetadataKeys) { - return Reflect.getOwnMetadataKeys(target, propertyKey!); - } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); return OrdinaryOwnMetadataKeys(target, propertyKey); @@ -989,20 +963,11 @@ export function deleteMetadata(metadataKey: any, target: any, propertyKey: strin * */ export function deleteMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean { - if (!hasSetMetadata && typeof Reflect !== "undefined" && typeof Reflect.deleteMetadata === "function" && Reflect.deleteMetadata !== deleteMetadata) { - return Reflect.deleteMetadata(metadataKey, target, propertyKey!); - } if (!IsObject(target)) throw new TypeError(); if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey); - const metadataMap = GetOrCreateMetadataMap(target, propertyKey, /*Create*/ false); - if (IsUndefined(metadataMap)) return false; - if (!metadataMap.delete(metadataKey)) return false; - if (metadataMap.size > 0) return true; - const targetMetadata = Metadata.get(target); - targetMetadata.delete(propertyKey); - if (targetMetadata.size > 0) return true; - Metadata.delete(target); - return true; + const provider = GetMetadataProvider(target, propertyKey, /*Create*/ false); + if (IsUndefined(provider)) return false; + return provider.OrdinaryDeleteMetadata(metadataKey, target, propertyKey); } function DecorateConstructor(decorators: ClassDecorator[], target: Function): Function { @@ -1029,27 +994,6 @@ function DecorateProperty(decorators: MemberDecorator[], target: any, propertyKe return descriptor; } -// 2.1.1 GetOrCreateMetadataMap(O, P, Create) -// https://rbuckton.github.io/reflect-metadata/#getorcreatemetadatamap -function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: true): Map; -function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: false): Map | undefined; -function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: boolean): Map | undefined { - let targetMetadata = Metadata.get(O); - if (IsUndefined(targetMetadata)) { - if (!Create) return undefined; - targetMetadata = new _Map>(); - Metadata.set(O, targetMetadata); - hasSetMetadata = true; - } - let metadataMap = targetMetadata.get(P); - if (IsUndefined(metadataMap)) { - if (!Create) return undefined; - metadataMap = new _Map(); - targetMetadata.set(P, metadataMap); - } - return metadataMap; -} - // 3.1.1.1 OrdinaryHasMetadata(MetadataKey, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinaryhasmetadata function OrdinaryHasMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean { @@ -1063,9 +1007,9 @@ function OrdinaryHasMetadata(MetadataKey: any, O: any, P: string | symbol | unde // 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata function OrdinaryHasOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean { - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) return false; - return ToBoolean(metadataMap.has(MetadataKey)); + const provider = GetMetadataProvider(O, P, /*Create*/ false); + if (IsUndefined(provider)) return false; + return ToBoolean(provider.OrdinaryHasOwnMetadata(MetadataKey, O, P)); } // 3.1.3.1 OrdinaryGetMetadata(MetadataKey, O, P) @@ -1081,16 +1025,16 @@ function OrdinaryGetMetadata(MetadataKey: any, O: any, P: string | symbol | unde // 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata function OrdinaryGetOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): any { - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) return undefined; - return metadataMap.get(MetadataKey); + const provider = GetMetadataProvider(O, P, /*Create*/ false); + if (IsUndefined(provider)) return; + return provider.OrdinaryGetOwnMetadata(MetadataKey, O, P); } // 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) // https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata function OrdinaryDefineOwnMetadata(MetadataKey: any, MetadataValue: any, O: any, P: string | symbol | undefined): void { - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ true); - metadataMap.set(MetadataKey, MetadataValue); + const provider = GetMetadataProvider(O, P, /*Create*/ true); + provider.OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P); } // 3.1.6.1 OrdinaryMetadataKeys(O, P) @@ -1124,32 +1068,11 @@ function OrdinaryMetadataKeys(O: any, P: string | symbol | undefined): any[] { // 3.1.7.1 OrdinaryOwnMetadataKeys(O, P) // https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys function OrdinaryOwnMetadataKeys(O: any, P: string | symbol | undefined): any[] { - const keys: any[] = []; - const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); - if (IsUndefined(metadataMap)) return keys; - const keysObj = metadataMap.keys(); - const iterator = GetIterator(keysObj); - let k = 0; - while (true) { - const next = IteratorStep(iterator); - if (!next) { - keys.length = k; - return keys; - } - const nextValue = IteratorValue(next); - try { - keys[k] = nextValue; - } - catch (e) { - try { - IteratorClose(iterator); - } - finally { - throw e; - } - } - k++; + const provider = GetMetadataProvider(O, P, /*create*/ false); + if (!provider) { + return []; } + return provider.OrdinaryOwnMetadataKeys(O, P); } // 6 ECMAScript Data Typ0es and Values @@ -1395,3 +1318,299 @@ function OrdinaryGetPrototypeOf(O: any): any { function fail(e: any): never { throw e; } + +// Global metadata registry +// - Allows `import "reflect-metadata"` and `import "reflect-metadata/no-conflict"` to interoperate. +// - Uses isolated metadata if `Reflect` is frozen before the registry can be installed. + +const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined; +const metadataRegistry = GetOrCreateMetadataRegistry(); +const metadataProvider = CreateMetadataProvider(metadataRegistry); + +/** + * Creates a registry used to allow multiple `reflect-metadata` providers. + */ +function CreateMetadataRegistry(): MetadataRegistry { + let first: MetadataProvider | undefined; + let second: MetadataProvider | undefined; + let rest: Set | undefined; + const targetProviderMap = new _WeakMap>(); + const registry: MetadataRegistry = { + registerProvider, + getProvider, + setProvider, + }; + return registry; + + function registerProvider(provider: MetadataProvider) { + if (!Object.isExtensible(registry)) { + throw new Error("Cannot add provider to a frozen registry."); + } + switch (true) { + case IsUndefined(first): first = provider; break; + case first === provider: break; + case IsUndefined(second): second = provider; break; + case second === provider: break; + default: + if (rest === undefined) rest = new _Set(); + rest.add(provider); + break; + } + } + + function getProviderNoCache(O: object, P: string | symbol | undefined) { + if (IsUndefined(first)) return undefined; + if (first.isProviderFor(O, P)) return first; + if (IsUndefined(second)) return undefined; + if (second.isProviderFor(O, P)) return first; + if (IsUndefined(rest)) return undefined; + const iterator = GetIterator(rest); + while (true) { + const next = IteratorStep(iterator); + if (!next) { + return undefined; + } + const provider = IteratorValue(next); + if (provider.isProviderFor(O, P)) { + IteratorClose(iterator); + return provider; + } + } + } + + function getProvider(O: object, P: string | symbol | undefined) { + let providerMap = targetProviderMap.get(O); + let provider: MetadataProvider | undefined; + if (!IsUndefined(providerMap)) { + provider = providerMap.get(P); + } + if (!IsUndefined(provider)) { + return provider; + } + + provider = getProviderNoCache(O, P); + if (!IsUndefined(provider)) { + if (IsUndefined(providerMap)) { + providerMap = new _Map(); + targetProviderMap.set(O, providerMap); + } + providerMap.set(P, provider); + } + return provider; + } + + function hasProvider(provider: MetadataProvider) { + return first === provider || second === provider || !IsUndefined(rest) && rest.has(provider); + } + + function setProvider(O: object, P: string | symbol | undefined, provider: MetadataProvider) { + if (!hasProvider(provider)) { + throw new Error("Metadata provider not registered."); + } + const existingProvider = getProvider(O, P); + if (existingProvider !== provider) { + if (!IsUndefined(existingProvider)) { + return false; + } + let providerMap = targetProviderMap.get(O); + if (IsUndefined(providerMap)) { + providerMap = new _Map(); + targetProviderMap.set(O, providerMap); + } + providerMap.set(P, provider); + } + return true; + } +} + +/** + * Gets or creates the shared registry of metadata providers. + */ +function GetOrCreateMetadataRegistry(): MetadataRegistry { + let metadataRegistry: MetadataRegistry | undefined; + if (!IsUndefined(registrySymbol) && IsObject(Reflect) && Object.isExtensible(Reflect)) { + metadataRegistry = (Reflect as any)[registrySymbol] as MetadataRegistry | undefined; + } + if (IsUndefined(metadataRegistry)) { + metadataRegistry = CreateMetadataRegistry(); + } + if (!IsUndefined(registrySymbol) && IsObject(Reflect) && Object.isExtensible(Reflect)) { + if (typeof Reflect.defineMetadata === "function") { + // `/no-conflict` used in an environment with an older copy of `reflect-metadata`. Add a legacy fallback. + metadataRegistry.registerProvider(CreateFallbackProvider(Reflect)); + } + Object.defineProperty(Reflect, registrySymbol, { + enumerable: false, + configurable: false, + writable: false, + value: metadataRegistry + }); + } + return metadataRegistry; +} + +function CreateMetadataProvider(registry: MetadataRegistry): MetadataProvider { + // [[Metadata]] internal slot + // https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots + const metadata = new _WeakMap>>(); + const provider: MetadataProvider = { + isProviderFor(O, P) { + const targetMetadata = metadata.get(O); + if (IsUndefined(targetMetadata)) return false; + return targetMetadata.has(P); + }, + OrdinaryDefineOwnMetadata: OrdinaryDefineOwnMetadata, + OrdinaryHasOwnMetadata: OrdinaryHasOwnMetadata, + OrdinaryGetOwnMetadata: OrdinaryGetOwnMetadata, + OrdinaryOwnMetadataKeys: OrdinaryOwnMetadataKeys, + OrdinaryDeleteMetadata: OrdinaryDeleteMetadata, + }; + metadataRegistry.registerProvider(provider); + return provider; + + // 2.1.1 GetOrCreateMetadataMap(O, P, Create) + // https://rbuckton.github.io/reflect-metadata/#getorcreatemetadatamap + function GetOrCreateMetadataMap(O: object, P: string | symbol | undefined, Create: true): Map; + function GetOrCreateMetadataMap(O: object, P: string | symbol | undefined, Create: false): Map | undefined; + function GetOrCreateMetadataMap(O: object, P: string | symbol | undefined, Create: boolean) { + let targetMetadata = metadata.get(O); + let createdTargetMetadata = false; + if (IsUndefined(targetMetadata)) { + if (!Create) return undefined; + targetMetadata = new _Map>(); + metadata.set(O, targetMetadata); + createdTargetMetadata = true; + } + let metadataMap = targetMetadata.get(P); + if (IsUndefined(metadataMap)) { + if (!Create) return undefined; + metadataMap = new _Map(); + targetMetadata.set(P, metadataMap); + if (!registry.setProvider(O, P, provider)) { + targetMetadata.delete(P); + if (createdTargetMetadata) { + metadata.delete(O); + } + throw new Error("Wrong provider for target."); + } + } + return metadataMap; + } + + // 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata + function OrdinaryHasOwnMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): boolean { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return false; + return ToBoolean(metadataMap.has(MetadataKey)); + } + + // 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata + function OrdinaryGetOwnMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): any { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return undefined; + return metadataMap.get(MetadataKey); + } + + // 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata + function OrdinaryDefineOwnMetadata(MetadataKey: any, MetadataValue: any, O: object, P: string | symbol | undefined): void { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ true); + metadataMap.set(MetadataKey, MetadataValue); + } + + // 3.1.7.1 OrdinaryOwnMetadataKeys(O, P) + // https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys + function OrdinaryOwnMetadataKeys(O: any, P: string | symbol | undefined): any[] { + const keys: any[] = []; + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return keys; + const keysObj = metadataMap.keys(); + const iterator = GetIterator(keysObj); + let k = 0; + while (true) { + const next = IteratorStep(iterator); + if (!next) { + keys.length = k; + return keys; + } + const nextValue = IteratorValue(next); + try { + keys[k] = nextValue; + } + catch (e) { + try { + IteratorClose(iterator); + } + finally { + throw e; + } + } + k++; + } + } + + function OrdinaryDeleteMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): boolean { + const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false); + if (IsUndefined(metadataMap)) return false; + if (!metadataMap.delete(MetadataKey)) return false; + if (metadataMap.size === 0) { + const targetMetadata = metadata.get(O); + if (!IsUndefined(targetMetadata)) { + targetMetadata.delete(P); + if (targetMetadata.size === 0) { + metadata.delete(targetMetadata); + } + } + } + return true; + } +} + +function CreateFallbackProvider(reflect: typeof Reflect): MetadataProvider { + const metadataOwner = new _WeakMap>(); + const provider: MetadataProvider = { + isProviderFor(O, P) { + let metadataPropertySet = metadataOwner.get(O); + if (!IsUndefined(metadataPropertySet)) { + return metadataPropertySet.has(P); + } + if (reflect.getOwnMetadataKeys(O, P!).length) { + if (IsUndefined(metadataPropertySet)) { + metadataPropertySet = new _Set(); + metadataOwner.set(O, metadataPropertySet); + } + metadataPropertySet.add(P); + return true; + } + return false; + }, + OrdinaryDefineOwnMetadata: reflect.defineMetadata, + OrdinaryHasOwnMetadata: reflect.hasOwnMetadata, + OrdinaryGetOwnMetadata: reflect.getOwnMetadata, + OrdinaryOwnMetadataKeys: reflect.getOwnMetadataKeys, + OrdinaryDeleteMetadata: reflect.deleteMetadata, + }; + return provider; +} + +function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: true): MetadataProvider; +function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: false): MetadataProvider | undefined; +/** + * Gets the metadata provider for an object. If the object has no metadata provider and this is for a create operation, + * then this module's metadata provider is assigned to the object. + */ +function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: boolean): MetadataProvider | undefined { + const registeredProvider = metadataRegistry.getProvider(O, P); + if (!IsUndefined(registeredProvider)) { + return registeredProvider; + } + if (Create) { + if (metadataRegistry.setProvider(O, P, metadataProvider)) { + return metadataProvider; + } + throw new Error("Illegal state."); + } + return undefined; +} diff --git a/globals.d.ts b/globals.d.ts index 403f574..d0b17ce 100644 --- a/globals.d.ts +++ b/globals.d.ts @@ -15,6 +15,7 @@ and limitations under the License. interface SymbolConstructor { (description?: string): symbol; + for(key: string): symbol; readonly iterator: symbol; readonly toPrimitive: symbol; } @@ -89,3 +90,20 @@ interface WeakMapConstructor { declare var Map: MapConstructor; declare var Set: SetConstructor; declare var WeakMap: WeakMapConstructor; + +// NOTE: These are not actually global, just shared between the Reflect*.ts variants + +interface MetadataRegistry { + registerProvider(provider: MetadataProvider): void; + getProvider(O: object, P: string | symbol | undefined): MetadataProvider | undefined; + setProvider(O: object, P: string | symbol | undefined, provider: MetadataProvider): boolean; +} + +interface MetadataProvider { + isProviderFor(O: object, P: string | symbol | undefined): boolean; + OrdinaryDefineOwnMetadata(MetadataKey: any, MetadataValue: any, O: object, P: string | symbol | undefined): void; + OrdinaryDeleteMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): boolean; + OrdinaryHasOwnMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): boolean; + OrdinaryGetOwnMetadata(MetadataKey: any, O: object, P: string | symbol | undefined): any; + OrdinaryOwnMetadataKeys(O: object, P: string | symbol | undefined): any[]; +} diff --git a/gulpfile.js b/gulpfile.js index efe3851..c102f7d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,7 +9,12 @@ const gls = require("gulp-live-server"); const debugProject = tsb.create("tsconfig.json"); const releaseProject = tsb.create("tsconfig-release.json"); -const tests = tsb.create("test/tsconfig.json"); +const tests = { + full: tsb.create("test/full/tsconfig.json"), + lite: tsb.create("test/lite/tsconfig.json"), + "no-conflict": tsb.create("test/no-conflict/tsconfig.json"), + registry: tsb.create("test/registry/tsconfig.json"), +}; let project = debugProject; @@ -30,10 +35,32 @@ gulp.task("build:reflect", () => gulp .pipe(project()) .pipe(gulp.dest("."))); -gulp.task("build:tests", ["build:reflect"], () => gulp - .src(["test/**/*.ts"]) - .pipe(tests()) - .pipe(gulp.dest("test"))); +gulp.task("build:tests:full", ["build:reflect"], () => gulp + .src(["test/full/**/*.ts"]) + .pipe(tests.full()) + .pipe(gulp.dest("test/full"))); + +gulp.task("build:tests:lite", ["build:reflect"], () => gulp + .src(["test/lite/**/*.ts"]) + .pipe(tests.lite()) + .pipe(gulp.dest("test/lite"))); + +gulp.task("build:tests:no-conflict", ["build:reflect"], () => gulp + .src(["test/no-conflict/**/*.ts"]) + .pipe(tests["no-conflict"]()) + .pipe(gulp.dest("test/no-conflict"))); + +gulp.task("build:tests:registry", ["build:reflect"], () => gulp + .src(["test/registry/**/*.ts"]) + .pipe(tests.registry()) + .pipe(gulp.dest("test/registry"))); + +gulp.task("build:tests", [ + "build:tests:full", + "build:tests:lite", + "build:tests:no-conflict", + "build:tests:registry" +]); gulp.task("build:spec", () => gulp .src(["spec.html"]) @@ -55,31 +82,37 @@ gulp.task("use-polyfill", () => { process.env["REFLECT_METADATA_USE_MAP_POLYFILL"] = "true"; }); -gulp.task("test:full", ["build:tests", "no-polyfill"], () => { +gulp.task("test:full", ["build:tests:full", "no-polyfill"], () => { console.log("Running tests w/o polyfill..."); return gulp .src(["test/full/**/*.js"], { read: false }) .pipe(mocha({ reporter: "dot" })); }); -gulp.task("test:lite", ["build:tests", "no-polyfill"], () => { +gulp.task("test:lite", ["build:tests:lite", "no-polyfill"], () => { console.log("Running lite-mode tests w/o polyfill..."); return gulp .src(["test/lite/**/*.js"], { read: false }) .pipe(mocha({ reporter: "dot" })); }); -gulp.task("test:no-conflict", ["build:tests", "no-polyfill"], () => { +gulp.task("test:no-conflict", ["build:tests:no-conflict", "no-polyfill"], () => { console.log("Running no-conflict-mode tests w/o polyfill..."); return gulp .src(["test/no-conflict/**/*.js"], { read: false }) .pipe(mocha({ reporter: "dot" })); }); -gulp.task("test:use-polyfill", ["build:tests", "use-polyfill"], () => { +gulp.task("test:registry", ["build:tests:registry", "no-polyfill"], () => { + console.log("Running registry..."); + return gulp + .src(["test/registry/**/*.js"], { read: false }) + .pipe(mocha({ reporter: "dot" })); +}); +gulp.task("test:use-polyfill", ["build:tests:full", "use-polyfill"], () => { console.log("Running tests w/ polyfill..."); return gulp .src(["test/full/**/*.js"], { read: false }) .pipe(mocha({ reporter: "dot" })); }); -gulp.task("test", sequence("test:full", "test:lite", "test:no-conflict", "test:use-polyfill")); +gulp.task("test", sequence("test:full", "test:lite", "test:no-conflict", "test:registry", "test:use-polyfill")); gulp.task("watch:reflect", () => gulp.watch([ diff --git a/test/tsconfig.json b/test/full/tsconfig.json similarity index 76% rename from test/tsconfig.json rename to test/full/tsconfig.json index 609ebe8..038cdd3 100644 --- a/test/tsconfig.json +++ b/test/full/tsconfig.json @@ -5,7 +5,7 @@ "sourceMap": true, "module": "commonjs", "types": ["node", "mocha"], - "typeRoots": ["../node_modules/@types"], + "typeRoots": ["../../node_modules/@types"], }, "include": [ "**/*.ts" diff --git a/test/lite/tsconfig.json b/test/lite/tsconfig.json new file mode 100644 index 0000000..038cdd3 --- /dev/null +++ b/test/lite/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es5", + "noImplicitAny": true, + "sourceMap": true, + "module": "commonjs", + "types": ["node", "mocha"], + "typeRoots": ["../../node_modules/@types"], + }, + "include": [ + "**/*.ts" + ] +} \ No newline at end of file diff --git a/test/no-conflict/tsconfig.json b/test/no-conflict/tsconfig.json new file mode 100644 index 0000000..038cdd3 --- /dev/null +++ b/test/no-conflict/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es5", + "noImplicitAny": true, + "sourceMap": true, + "module": "commonjs", + "types": ["node", "mocha"], + "typeRoots": ["../../node_modules/@types"], + }, + "include": [ + "**/*.ts" + ] +} \ No newline at end of file diff --git a/test/registry/registry.ts b/test/registry/registry.ts new file mode 100644 index 0000000..6a1d00a --- /dev/null +++ b/test/registry/registry.ts @@ -0,0 +1,31 @@ +/// +/// +const ReflectNoConflict = require("../../ReflectNoConflict"); +require("../../Reflect"); +import { assert } from "chai"; + +describe("MetadataRegistry", () => { + it("defines registry", () => { + const registrySymbol = Symbol.for("@reflect-metadata:registry"); + const registry = (Reflect as any)[registrySymbol] as MetadataRegistry; + assert.isDefined(registry); + }); + it("two registries", () => { + const registrySymbol = Symbol.for("@reflect-metadata:registry"); + const registry = (Reflect as any)[registrySymbol] as MetadataRegistry; + const obj1 = {}; + ReflectNoConflict.defineMetadata("key", "value", obj1); + const obj2 = {}; + Reflect.defineMetadata("key", "value", obj2); + const provider1 = registry.getProvider(obj1, undefined); + const provider2 = registry.getProvider(obj2, undefined); + assert.isDefined(provider1); + assert.isDefined(provider2); + assert.notStrictEqual(provider1, provider2); + }); + it("registries are shared", () => { + const obj = {}; + ReflectNoConflict.defineMetadata("key", "value", obj); + assert.isTrue(Reflect.hasOwnMetadata("key", obj)); + }); +}); diff --git a/test/registry/tsconfig.json b/test/registry/tsconfig.json new file mode 100644 index 0000000..038cdd3 --- /dev/null +++ b/test/registry/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es5", + "noImplicitAny": true, + "sourceMap": true, + "module": "commonjs", + "types": ["node", "mocha"], + "typeRoots": ["../../node_modules/@types"], + }, + "include": [ + "**/*.ts" + ] +} \ No newline at end of file From b53ea48fa3c717dc0ce61275a5e3668d7741d874 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 8 Dec 2023 20:56:38 -0500 Subject: [PATCH 7/8] Fix fallback handling, better tests, remove process.env reference --- Reflect.ts | 103 ++++-- ReflectLite.ts | 105 +++++-- ReflectNoConflict.ts | 61 ++-- gulpfile.js | 77 +---- package.json | 2 +- test/full/reflect-decorate.ts | 211 ------------- test/full/reflect-definemetadata.ts | 20 -- test/full/reflect-deletemetadata.ts | 41 --- test/full/reflect-getmetadata.ts | 54 ---- test/full/reflect-getmetadatakeys.ts | 101 ------ test/full/reflect-getownmetadata.ts | 54 ---- test/full/reflect-getownmetadatakeys.ts | 81 ----- test/full/reflect-hasmetadata.ts | 54 ---- test/full/reflect-hasownmetadata.ts | 54 ---- test/full/reflect-metadata.ts | 41 --- test/full/reflect-other.ts | 15 - test/lite/reflect-decorate.ts | 211 ------------- test/lite/reflect-definemetadata.ts | 20 -- test/lite/reflect-deletemetadata.ts | 41 --- test/lite/reflect-getmetadata.ts | 54 ---- test/lite/reflect-getmetadatakeys.ts | 101 ------ test/lite/reflect-getownmetadata.ts | 54 ---- test/lite/reflect-getownmetadatakeys.ts | 81 ----- test/lite/reflect-hasmetadata.ts | 54 ---- test/lite/reflect-hasownmetadata.ts | 54 ---- test/lite/reflect-metadata.ts | 41 --- test/lite/reflect-other.ts | 17 - test/lite/tsconfig.json | 13 - test/no-conflict/reflect-decorate.ts | 210 ------------- test/no-conflict/reflect-definemetadata.ts | 19 -- test/no-conflict/reflect-deletemetadata.ts | 40 --- test/no-conflict/reflect-getmetadata.ts | 60 ---- test/no-conflict/reflect-getmetadatakeys.ts | 100 ------ test/no-conflict/reflect-getownmetadata.ts | 53 ---- .../no-conflict/reflect-getownmetadatakeys.ts | 80 ----- test/no-conflict/reflect-hasmetadata.ts | 53 ---- test/no-conflict/reflect-hasownmetadata.ts | 53 ---- test/no-conflict/reflect-metadata.ts | 41 --- test/no-conflict/tsconfig.json | 13 - test/reflect-decorate.ts | 294 ++++++++++++++++++ test/reflect-definemetadata.ts | 39 +++ test/reflect-deletemetadata.ts | 67 ++++ test/reflect-getmetadata.ts | 88 ++++++ test/reflect-getmetadatakeys.ts | 155 +++++++++ test/reflect-getownmetadata.ts | 88 ++++++ test/reflect-getownmetadatakeys.ts | 127 ++++++++ test/reflect-hasmetadata.ts | 88 ++++++ test/reflect-hasownmetadata.ts | 88 ++++++ test/reflect-metadata.ts | 68 ++++ test/reflect-other.ts | 29 ++ test/registry.ts | 59 ++++ test/registry/registry.ts | 31 -- test/registry/tsconfig.json | 13 - test/suites.ts | 35 +++ test/{full => }/tsconfig.json | 2 +- test/vm.ts | 61 ++++ 56 files changed, 1479 insertions(+), 2390 deletions(-) delete mode 100644 test/full/reflect-decorate.ts delete mode 100644 test/full/reflect-definemetadata.ts delete mode 100644 test/full/reflect-deletemetadata.ts delete mode 100644 test/full/reflect-getmetadata.ts delete mode 100644 test/full/reflect-getmetadatakeys.ts delete mode 100644 test/full/reflect-getownmetadata.ts delete mode 100644 test/full/reflect-getownmetadatakeys.ts delete mode 100644 test/full/reflect-hasmetadata.ts delete mode 100644 test/full/reflect-hasownmetadata.ts delete mode 100644 test/full/reflect-metadata.ts delete mode 100644 test/full/reflect-other.ts delete mode 100644 test/lite/reflect-decorate.ts delete mode 100644 test/lite/reflect-definemetadata.ts delete mode 100644 test/lite/reflect-deletemetadata.ts delete mode 100644 test/lite/reflect-getmetadata.ts delete mode 100644 test/lite/reflect-getmetadatakeys.ts delete mode 100644 test/lite/reflect-getownmetadata.ts delete mode 100644 test/lite/reflect-getownmetadatakeys.ts delete mode 100644 test/lite/reflect-hasmetadata.ts delete mode 100644 test/lite/reflect-hasownmetadata.ts delete mode 100644 test/lite/reflect-metadata.ts delete mode 100644 test/lite/reflect-other.ts delete mode 100644 test/lite/tsconfig.json delete mode 100644 test/no-conflict/reflect-decorate.ts delete mode 100644 test/no-conflict/reflect-definemetadata.ts delete mode 100644 test/no-conflict/reflect-deletemetadata.ts delete mode 100644 test/no-conflict/reflect-getmetadata.ts delete mode 100644 test/no-conflict/reflect-getmetadatakeys.ts delete mode 100644 test/no-conflict/reflect-getownmetadata.ts delete mode 100644 test/no-conflict/reflect-getownmetadatakeys.ts delete mode 100644 test/no-conflict/reflect-hasmetadata.ts delete mode 100644 test/no-conflict/reflect-hasownmetadata.ts delete mode 100644 test/no-conflict/reflect-metadata.ts delete mode 100644 test/no-conflict/tsconfig.json create mode 100644 test/reflect-decorate.ts create mode 100644 test/reflect-definemetadata.ts create mode 100644 test/reflect-deletemetadata.ts create mode 100644 test/reflect-getmetadata.ts create mode 100644 test/reflect-getmetadatakeys.ts create mode 100644 test/reflect-getownmetadata.ts create mode 100644 test/reflect-getownmetadatakeys.ts create mode 100644 test/reflect-hasmetadata.ts create mode 100644 test/reflect-hasownmetadata.ts create mode 100644 test/reflect-metadata.ts create mode 100644 test/reflect-other.ts create mode 100644 test/registry.ts delete mode 100644 test/registry/registry.ts delete mode 100644 test/registry/tsconfig.json create mode 100644 test/suites.ts rename test/{full => }/tsconfig.json (76%) create mode 100644 test/vm.ts diff --git a/Reflect.ts b/Reflect.ts index 701c204..190d386 100644 --- a/Reflect.ts +++ b/Reflect.ts @@ -30,7 +30,6 @@ namespace Reflect { declare const globalThis: any; declare const crypto: Crypto; declare const msCrypto: Crypto; - declare const process: any; /** * Applies a set of decorators to a target object. @@ -563,20 +562,19 @@ namespace Reflect { sloppyModeThis(); let exporter = makeExporter(Reflect); - if (typeof root.Reflect === "undefined") { - root.Reflect = Reflect; - } - else { + if (typeof root.Reflect !== "undefined") { exporter = makeExporter(root.Reflect, exporter); } factory(exporter, root); + if (typeof root.Reflect === "undefined") { + root.Reflect = Reflect; + } + function makeExporter(target: typeof Reflect, previous?: (key: K, value: typeof Reflect[K]) => void) { return (key: K, value: typeof Reflect[K]) => { - if (typeof target[key] !== "function") { - Object.defineProperty(target, key, { configurable: true, writable: true, value }); - } + Object.defineProperty(target, key, { configurable: true, writable: true, value }); if (previous) previous(key, value); }; } @@ -623,10 +621,12 @@ namespace Reflect { // Load global or shim versions of Map, Set, and WeakMap const functionPrototype = Object.getPrototypeOf(Function); - const usePolyfill = typeof process === "object" && process["env" + ""] && process["env" + ""]["REFLECT_METADATA_USE_MAP_POLYFILL"] === "true"; - const _Map: typeof Map = !usePolyfill && typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : CreateMapPolyfill(); - const _Set: typeof Set = !usePolyfill && typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : CreateSetPolyfill(); - const _WeakMap: typeof WeakMap = !usePolyfill && typeof WeakMap === "function" ? WeakMap : CreateWeakMapPolyfill(); + const _Map: typeof Map = typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : CreateMapPolyfill(); + const _Set: typeof Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : CreateSetPolyfill(); + const _WeakMap: typeof WeakMap = typeof WeakMap === "function" ? WeakMap : CreateWeakMapPolyfill(); + const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined; + const metadataRegistry = GetOrCreateMetadataRegistry(); + const metadataProvider = CreateMetadataProvider(metadataRegistry); function decorate(decorators: ClassDecorator[], target: Function): Function; function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined; @@ -1489,14 +1489,19 @@ namespace Reflect { // - Allows `import "reflect-metadata"` and `import "reflect-metadata/no-conflict"` to interoperate. // - Uses isolated metadata if `Reflect` is frozen before the registry can be installed. - const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined; - const metadataRegistry = GetOrCreateMetadataRegistry(); - const metadataProvider = CreateMetadataProvider(metadataRegistry); - /** * Creates a registry used to allow multiple `reflect-metadata` providers. */ function CreateMetadataRegistry(): MetadataRegistry { + let fallback: MetadataProvider | undefined; + if (!IsUndefined(registrySymbol) && + typeof root.Reflect !== "undefined" && + !(registrySymbol in root.Reflect) && + typeof root.Reflect.defineMetadata === "function") { + // interoperate with older version of `reflect-metadata` that did not support a registry. + fallback = CreateFallbackProvider(root.Reflect); + } + let first: MetadataProvider | undefined; let second: MetadataProvider | undefined; let rest: Set | undefined; @@ -1513,6 +1518,7 @@ namespace Reflect { throw new Error("Cannot add provider to a frozen registry."); } switch (true) { + case fallback === provider: break; case IsUndefined(first): first = provider; break; case first === provider: break; case IsUndefined(second): second = provider; break; @@ -1525,23 +1531,30 @@ namespace Reflect { } function getProviderNoCache(O: object, P: string | symbol | undefined) { - if (IsUndefined(first)) return undefined; - if (first.isProviderFor(O, P)) return first; - if (IsUndefined(second)) return undefined; - if (second.isProviderFor(O, P)) return first; - if (IsUndefined(rest)) return undefined; - const iterator = GetIterator(rest); - while (true) { - const next = IteratorStep(iterator); - if (!next) { - return undefined; - } - const provider = IteratorValue(next); - if (provider.isProviderFor(O, P)) { - IteratorClose(iterator); - return provider; + if (!IsUndefined(first)) { + if (first.isProviderFor(O, P)) return first; + if (!IsUndefined(second)) { + if (second.isProviderFor(O, P)) return first; + if (!IsUndefined(rest)) { + const iterator = GetIterator(rest); + while (true) { + const next = IteratorStep(iterator); + if (!next) { + return undefined; + } + const provider = IteratorValue(next); + if (provider.isProviderFor(O, P)) { + IteratorClose(iterator); + return provider; + } + } + } } } + if (!IsUndefined(fallback) && fallback.isProviderFor(O, P)) { + return fallback; + } + return undefined; } function getProvider(O: object, P: string | symbol | undefined) { @@ -1566,6 +1579,7 @@ namespace Reflect { } function hasProvider(provider: MetadataProvider) { + if (IsUndefined(provider)) throw new TypeError(); return first === provider || second === provider || !IsUndefined(rest) && rest.has(provider); } @@ -1730,6 +1744,33 @@ namespace Reflect { } } + function CreateFallbackProvider(reflect: typeof Reflect): MetadataProvider { + const metadataOwner = new _WeakMap>(); + const provider: MetadataProvider = { + isProviderFor(O, P) { + let metadataPropertySet = metadataOwner.get(O); + if (!IsUndefined(metadataPropertySet)) { + return metadataPropertySet.has(P); + } + if (reflect.getOwnMetadataKeys(O, P!).length) { + if (IsUndefined(metadataPropertySet)) { + metadataPropertySet = new _Set(); + metadataOwner.set(O, metadataPropertySet); + } + metadataPropertySet.add(P); + return true; + } + return false; + }, + OrdinaryDefineOwnMetadata: reflect.defineMetadata, + OrdinaryHasOwnMetadata: reflect.hasOwnMetadata, + OrdinaryGetOwnMetadata: reflect.getOwnMetadata, + OrdinaryOwnMetadataKeys: reflect.getOwnMetadataKeys, + OrdinaryDeleteMetadata: reflect.deleteMetadata, + }; + return provider; + } + function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: true): MetadataProvider; function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: false): MetadataProvider | undefined; /** diff --git a/ReflectLite.ts b/ReflectLite.ts index 51ad86d..81f71e8 100644 --- a/ReflectLite.ts +++ b/ReflectLite.ts @@ -554,20 +554,19 @@ namespace Reflect { sloppyModeThis(); let exporter = makeExporter(Reflect); - if (typeof root.Reflect === "undefined") { - root.Reflect = Reflect; - } - else { + if (typeof root.Reflect !== "undefined") { exporter = makeExporter(root.Reflect, exporter); } factory(exporter, root); + if (typeof root.Reflect === "undefined") { + root.Reflect = Reflect; + } + function makeExporter(target: typeof Reflect, previous?: (key: K, value: typeof Reflect[K]) => void) { return (key: K, value: typeof Reflect[K]) => { - if (typeof target[key] !== "function") { - Object.defineProperty(target, key, { configurable: true, writable: true, value }); - } + Object.defineProperty(target, key, { configurable: true, writable: true, value }); if (previous) previous(key, value); }; } @@ -595,6 +594,9 @@ namespace Reflect { const _Map: typeof Map = typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : fail("A valid Map constructor could not be found."); const _Set: typeof Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : fail("A valid Set constructor could not be found."); const _WeakMap: typeof WeakMap = typeof WeakMap === "function" ? WeakMap : fail("A valid WeakMap constructor could not be found."); + const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined; + const metadataRegistry = GetOrCreateMetadataRegistry(); + const metadataProvider = CreateMetadataProvider(metadataRegistry); function decorate(decorators: ClassDecorator[], target: Function): Function; function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined; @@ -1455,14 +1457,19 @@ namespace Reflect { // - Allows `import "reflect-metadata"` and `import "reflect-metadata/no-conflict"` to interoperate. // - Uses isolated metadata if `Reflect` is frozen before the registry can be installed. - const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined; - const metadataRegistry = GetOrCreateMetadataRegistry(); - const metadataProvider = CreateMetadataProvider(metadataRegistry); - /** * Creates a registry used to allow multiple `reflect-metadata` providers. */ function CreateMetadataRegistry(): MetadataRegistry { + let fallback: MetadataProvider | undefined; + if (!IsUndefined(registrySymbol) && + typeof root.Reflect !== "undefined" && + !(registrySymbol in root.Reflect) && + typeof root.Reflect.defineMetadata === "function") { + // interoperate with older version of `reflect-metadata` that did not support a registry. + fallback = CreateFallbackProvider(root.Reflect); + } + let first: MetadataProvider | undefined; let second: MetadataProvider | undefined; let rest: Set | undefined; @@ -1479,6 +1486,7 @@ namespace Reflect { throw new Error("Cannot add provider to a frozen registry."); } switch (true) { + case fallback === provider: break; case IsUndefined(first): first = provider; break; case first === provider: break; case IsUndefined(second): second = provider; break; @@ -1489,27 +1497,34 @@ namespace Reflect { break; } } - + function getProviderNoCache(O: object, P: string | symbol | undefined) { - if (IsUndefined(first)) return undefined; - if (first.isProviderFor(O, P)) return first; - if (IsUndefined(second)) return undefined; - if (second.isProviderFor(O, P)) return first; - if (IsUndefined(rest)) return undefined; - const iterator = GetIterator(rest); - while (true) { - const next = IteratorStep(iterator); - if (!next) { - return undefined; - } - const provider = IteratorValue(next); - if (provider.isProviderFor(O, P)) { - IteratorClose(iterator); - return provider; + if (!IsUndefined(first)) { + if (first.isProviderFor(O, P)) return first; + if (!IsUndefined(second)) { + if (second.isProviderFor(O, P)) return first; + if (!IsUndefined(rest)) { + const iterator = GetIterator(rest); + while (true) { + const next = IteratorStep(iterator); + if (!next) { + return undefined; + } + const provider = IteratorValue(next); + if (provider.isProviderFor(O, P)) { + IteratorClose(iterator); + return provider; + } + } + } } } + if (!IsUndefined(fallback) && fallback.isProviderFor(O, P)) { + return fallback; + } + return undefined; } - + function getProvider(O: object, P: string | symbol | undefined) { let providerMap = targetProviderMap.get(O); let provider: MetadataProvider | undefined; @@ -1519,7 +1534,7 @@ namespace Reflect { if (!IsUndefined(provider)) { return provider; } - + provider = getProviderNoCache(O, P); if (!IsUndefined(provider)) { if (IsUndefined(providerMap)) { @@ -1530,11 +1545,12 @@ namespace Reflect { } return provider; } - + function hasProvider(provider: MetadataProvider) { + if (IsUndefined(provider)) throw new TypeError(); return first === provider || second === provider || !IsUndefined(rest) && rest.has(provider); } - + function setProvider(O: object, P: string | symbol | undefined, provider: MetadataProvider) { if (!hasProvider(provider)) { throw new Error("Metadata provider not registered."); @@ -1696,6 +1712,33 @@ namespace Reflect { } } + function CreateFallbackProvider(reflect: typeof Reflect): MetadataProvider { + const metadataOwner = new _WeakMap>(); + const provider: MetadataProvider = { + isProviderFor(O, P) { + let metadataPropertySet = metadataOwner.get(O); + if (!IsUndefined(metadataPropertySet)) { + return metadataPropertySet.has(P); + } + if (reflect.getOwnMetadataKeys(O, P!).length) { + if (IsUndefined(metadataPropertySet)) { + metadataPropertySet = new _Set(); + metadataOwner.set(O, metadataPropertySet); + } + metadataPropertySet.add(P); + return true; + } + return false; + }, + OrdinaryDefineOwnMetadata: reflect.defineMetadata, + OrdinaryHasOwnMetadata: reflect.hasOwnMetadata, + OrdinaryGetOwnMetadata: reflect.getOwnMetadata, + OrdinaryOwnMetadataKeys: reflect.getOwnMetadataKeys, + OrdinaryDeleteMetadata: reflect.deleteMetadata, + }; + return provider; + } + function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: true): MetadataProvider; function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: false): MetadataProvider | undefined; /** diff --git a/ReflectNoConflict.ts b/ReflectNoConflict.ts index 9c648eb..59e993c 100644 --- a/ReflectNoConflict.ts +++ b/ReflectNoConflict.ts @@ -28,6 +28,9 @@ const functionPrototype = Object.getPrototypeOf(Function); const _Map: typeof Map = typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : fail("A valid Map constructor could not be found."); const _Set: typeof Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : fail("A valid Set constructor could not be found."); const _WeakMap: typeof WeakMap = typeof WeakMap === "function" ? WeakMap : fail("A valid WeakMap constructor could not be found."); +const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined; +const metadataRegistry = GetOrCreateMetadataRegistry(); +const metadataProvider = CreateMetadataProvider(metadataRegistry); /** * Applies a set of decorators to a target object. @@ -1323,14 +1326,19 @@ function fail(e: any): never { // - Allows `import "reflect-metadata"` and `import "reflect-metadata/no-conflict"` to interoperate. // - Uses isolated metadata if `Reflect` is frozen before the registry can be installed. -const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined; -const metadataRegistry = GetOrCreateMetadataRegistry(); -const metadataProvider = CreateMetadataProvider(metadataRegistry); - /** * Creates a registry used to allow multiple `reflect-metadata` providers. */ function CreateMetadataRegistry(): MetadataRegistry { + let fallback: MetadataProvider | undefined; + if (!IsUndefined(registrySymbol) && + typeof Reflect !== "undefined" && + !(registrySymbol in Reflect) && + typeof Reflect.defineMetadata === "function") { + // interoperate with older version of `reflect-metadata` that did not support a registry. + fallback = CreateFallbackProvider(Reflect); + } + let first: MetadataProvider | undefined; let second: MetadataProvider | undefined; let rest: Set | undefined; @@ -1347,6 +1355,7 @@ function CreateMetadataRegistry(): MetadataRegistry { throw new Error("Cannot add provider to a frozen registry."); } switch (true) { + case fallback === provider: break; case IsUndefined(first): first = provider; break; case first === provider: break; case IsUndefined(second): second = provider; break; @@ -1359,23 +1368,30 @@ function CreateMetadataRegistry(): MetadataRegistry { } function getProviderNoCache(O: object, P: string | symbol | undefined) { - if (IsUndefined(first)) return undefined; - if (first.isProviderFor(O, P)) return first; - if (IsUndefined(second)) return undefined; - if (second.isProviderFor(O, P)) return first; - if (IsUndefined(rest)) return undefined; - const iterator = GetIterator(rest); - while (true) { - const next = IteratorStep(iterator); - if (!next) { - return undefined; - } - const provider = IteratorValue(next); - if (provider.isProviderFor(O, P)) { - IteratorClose(iterator); - return provider; + if (!IsUndefined(first)) { + if (first.isProviderFor(O, P)) return first; + if (!IsUndefined(second)) { + if (second.isProviderFor(O, P)) return first; + if (!IsUndefined(rest)) { + const iterator = GetIterator(rest); + while (true) { + const next = IteratorStep(iterator); + if (!next) { + return undefined; + } + const provider = IteratorValue(next); + if (provider.isProviderFor(O, P)) { + IteratorClose(iterator); + return provider; + } + } + } } } + if (!IsUndefined(fallback) && fallback.isProviderFor(O, P)) { + return fallback; + } + return undefined; } function getProvider(O: object, P: string | symbol | undefined) { @@ -1400,7 +1416,8 @@ function CreateMetadataRegistry(): MetadataRegistry { } function hasProvider(provider: MetadataProvider) { - return first === provider || second === provider || !IsUndefined(rest) && rest.has(provider); + if (IsUndefined(provider)) throw new TypeError(); + return fallback === provider || first === provider || second === provider || !IsUndefined(rest) && rest.has(provider); } function setProvider(O: object, P: string | symbol | undefined, provider: MetadataProvider) { @@ -1435,10 +1452,6 @@ function GetOrCreateMetadataRegistry(): MetadataRegistry { metadataRegistry = CreateMetadataRegistry(); } if (!IsUndefined(registrySymbol) && IsObject(Reflect) && Object.isExtensible(Reflect)) { - if (typeof Reflect.defineMetadata === "function") { - // `/no-conflict` used in an environment with an older copy of `reflect-metadata`. Add a legacy fallback. - metadataRegistry.registerProvider(CreateFallbackProvider(Reflect)); - } Object.defineProperty(Reflect, registrySymbol, { enumerable: false, configurable: false, diff --git a/gulpfile.js b/gulpfile.js index c102f7d..6f9fe58 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,12 +9,7 @@ const gls = require("gulp-live-server"); const debugProject = tsb.create("tsconfig.json"); const releaseProject = tsb.create("tsconfig-release.json"); -const tests = { - full: tsb.create("test/full/tsconfig.json"), - lite: tsb.create("test/lite/tsconfig.json"), - "no-conflict": tsb.create("test/no-conflict/tsconfig.json"), - registry: tsb.create("test/registry/tsconfig.json"), -}; +const tests = tsb.create("test/tsconfig.json"); let project = debugProject; @@ -35,32 +30,10 @@ gulp.task("build:reflect", () => gulp .pipe(project()) .pipe(gulp.dest("."))); -gulp.task("build:tests:full", ["build:reflect"], () => gulp - .src(["test/full/**/*.ts"]) - .pipe(tests.full()) - .pipe(gulp.dest("test/full"))); - -gulp.task("build:tests:lite", ["build:reflect"], () => gulp - .src(["test/lite/**/*.ts"]) - .pipe(tests.lite()) - .pipe(gulp.dest("test/lite"))); - -gulp.task("build:tests:no-conflict", ["build:reflect"], () => gulp - .src(["test/no-conflict/**/*.ts"]) - .pipe(tests["no-conflict"]()) - .pipe(gulp.dest("test/no-conflict"))); - -gulp.task("build:tests:registry", ["build:reflect"], () => gulp - .src(["test/registry/**/*.ts"]) - .pipe(tests.registry()) - .pipe(gulp.dest("test/registry"))); - -gulp.task("build:tests", [ - "build:tests:full", - "build:tests:lite", - "build:tests:no-conflict", - "build:tests:registry" -]); +gulp.task("build:tests", () => gulp + .src(["test/**/*.ts"]) + .pipe(tests()) + .pipe(gulp.dest("test"))); gulp.task("build:spec", () => gulp .src(["spec.html"]) @@ -74,46 +47,12 @@ gulp.task("build:spec", () => gulp gulp.task("build", ["build:reflect", "build:tests", "build:spec"]); -gulp.task("no-polyfill", () => { - process.env["REFLECT_METADATA_USE_MAP_POLYFILL"] = ""; -}); - -gulp.task("use-polyfill", () => { - process.env["REFLECT_METADATA_USE_MAP_POLYFILL"] = "true"; -}); - -gulp.task("test:full", ["build:tests:full", "no-polyfill"], () => { - console.log("Running tests w/o polyfill..."); - return gulp - .src(["test/full/**/*.js"], { read: false }) - .pipe(mocha({ reporter: "dot" })); -}); -gulp.task("test:lite", ["build:tests:lite", "no-polyfill"], () => { - console.log("Running lite-mode tests w/o polyfill..."); +gulp.task("test", ["build:reflect", "build:tests"], () => { + console.log("Running tests..."); return gulp - .src(["test/lite/**/*.js"], { read: false }) + .src(["test/**/*.js"], { read: false }) .pipe(mocha({ reporter: "dot" })); }); -gulp.task("test:no-conflict", ["build:tests:no-conflict", "no-polyfill"], () => { - console.log("Running no-conflict-mode tests w/o polyfill..."); - return gulp - .src(["test/no-conflict/**/*.js"], { read: false }) - .pipe(mocha({ reporter: "dot" })); -}); -gulp.task("test:registry", ["build:tests:registry", "no-polyfill"], () => { - console.log("Running registry..."); - return gulp - .src(["test/registry/**/*.js"], { read: false }) - .pipe(mocha({ reporter: "dot" })); -}); -gulp.task("test:use-polyfill", ["build:tests:full", "use-polyfill"], () => { - console.log("Running tests w/ polyfill..."); - return gulp - .src(["test/full/**/*.js"], { read: false }) - .pipe(mocha({ reporter: "dot" })); -}); -gulp.task("test", sequence("test:full", "test:lite", "test:no-conflict", "test:registry", "test:use-polyfill")); - gulp.task("watch:reflect", () => gulp.watch([ "index.d.ts", diff --git a/package.json b/package.json index 2cc4df2..1dd6918 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "devDependencies": { "@types/chai": "^3.4.34", "@types/mocha": "^2.2.34", - "@types/node": "6.0.52", + "@types/node": "^10.17.60", "chai": "^3.5.0", "del": "^2.2.2", "ecmarkup": "^3.9.3", diff --git a/test/full/reflect-decorate.ts b/test/full/reflect-decorate.ts deleted file mode 100644 index 2c45264..0000000 --- a/test/full/reflect-decorate.ts +++ /dev/null @@ -1,211 +0,0 @@ -// Reflect.decorate ( decorators, target [, propertyKey [, descriptor] ] ) - -/// -require("../../Reflect"); -import { assert } from "chai"; - -describe("Reflect.decorate", () => { - it("ThrowsIfDecoratorsArgumentNotArrayForFunctionOverload", () => { - let target = function() { }; - assert.throws(() => Reflect.decorate(undefined!, target, undefined!, undefined), TypeError); - }); - - it("ThrowsIfTargetArgumentNotFunctionForFunctionOverload", () => { - let decorators: (MethodDecorator | PropertyDecorator)[] = []; - let target = {}; - assert.throws(() => Reflect.decorate(decorators, target, undefined!, undefined), TypeError); - }); - - it("ThrowsIfDecoratorsArgumentNotArrayForPropertyOverload", () => { - let target = {}; - let name = "name"; - assert.throws(() => Reflect.decorate(undefined!, target, name, undefined), TypeError); - }); - - it("ThrowsIfTargetArgumentNotObjectForPropertyOverload", () => { - let decorators: (MethodDecorator | PropertyDecorator)[] = []; - let target = 1; - let name = "name"; - assert.throws(() => Reflect.decorate(decorators, target, name, undefined), TypeError); - }); - - it("ThrowsIfDecoratorsArgumentNotArrayForPropertyDescriptorOverload", () => { - let target = {}; - let name = "name"; - let descriptor = {}; - assert.throws(() => Reflect.decorate(undefined!, target, name, descriptor), TypeError); - }); - - it("ThrowsIfTargetArgumentNotObjectForPropertyDescriptorOverload", () => { - let decorators: (MethodDecorator | PropertyDecorator)[] = []; - let target = 1; - let name = "name"; - let descriptor = {}; - assert.throws(() => Reflect.decorate(decorators, target, name, descriptor), TypeError); - }); - - it("ExecutesDecoratorsInReverseOrderForFunctionOverload", () => { - let order: number[] = []; - let decorators = [ - (_target: Function): void => { order.push(0); }, - (_target: Function): void => { order.push(1); } - ]; - let target = function() { }; - Reflect.decorate(decorators, target); - assert.deepEqual(order, [1, 0]); - }); - - it("ExecutesDecoratorsInReverseOrderForPropertyOverload", () => { - let order: number[] = []; - let decorators = [ - (_target: Object, _name: string | symbol): void => { order.push(0); }, - (_target: Object, _name: string | symbol): void => { order.push(1); } - ]; - let target = {}; - let name = "name"; - Reflect.decorate(decorators, target, name, undefined); - assert.deepEqual(order, [1, 0]); - }); - - it("ExecutesDecoratorsInReverseOrderForPropertyDescriptorOverload", () => { - let order: number[] = []; - let decorators = [ - (_target: Object, _name: string | symbol): void => { order.push(0); }, - (_target: Object, _name: string | symbol): void => { order.push(1); } - ]; - let target = {}; - let name = "name"; - let descriptor = {}; - Reflect.decorate(decorators, target, name, descriptor); - assert.deepEqual(order, [1, 0]); - }); - - it("DecoratorPipelineForFunctionOverload", () => { - let A = function A(): void { }; - let B = function B(): void { }; - let decorators = [ - (_target: Function): any => { return undefined; }, - (_target: Function): any => { return A; }, - (_target: Function): any => { return B; } - ]; - let target = function (): void { }; - let result = Reflect.decorate(decorators, target); - assert.strictEqual(result, A); - }); - - it("DecoratorPipelineForPropertyOverload", () => { - let A = {}; - let B = {}; - let decorators = [ - (_target: Object, _name: string | symbol): any => { return undefined; }, - (_target: Object, _name: string | symbol): any => { return A; }, - (_target: Object, _name: string | symbol): any => { return B; } - ]; - let target = {}; - let result = Reflect.decorate(decorators, target, "name", undefined); - assert.strictEqual(result, A); - }); - - it("DecoratorPipelineForPropertyDescriptorOverload", () => { - let A = {}; - let B = {}; - let C = {}; - let decorators = [ - (_target: Object, _name: string | symbol): any => { return undefined; }, - (_target: Object, _name: string | symbol): any => { return A; }, - (_target: Object, _name: string | symbol): any => { return B; } - ]; - let target = {}; - let result = Reflect.decorate(decorators, target, "name", C); - assert.strictEqual(result, A); - }); - - it("DecoratorCorrectTargetInPipelineForFunctionOverload", () => { - let sent: Function[] = []; - let A = function A(): void { }; - let B = function B(): void { }; - let decorators = [ - (target: Function): any => { sent.push(target); return undefined; }, - (target: Function): any => { sent.push(target); return undefined; }, - (target: Function): any => { sent.push(target); return A; }, - (target: Function): any => { sent.push(target); return B; } - ]; - let target = function (): void { }; - Reflect.decorate(decorators, target); - assert.deepEqual(sent, [target, B, A, A]); - }); - - it("DecoratorCorrectTargetInPipelineForPropertyOverload", () => { - let sent: Object[] = []; - let decorators = [ - (target: Object, _name: string | symbol): any => { sent.push(target); }, - (target: Object, _name: string | symbol): any => { sent.push(target); }, - (target: Object, _name: string | symbol): any => { sent.push(target); }, - (target: Object, _name: string | symbol): any => { sent.push(target); } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name"); - assert.deepEqual(sent, [target, target, target, target]); - }); - - it("DecoratorCorrectNameInPipelineForPropertyOverload", () => { - let sent: (symbol | string)[] = []; - let decorators = [ - (_target: Object, name: string | symbol): any => { sent.push(name); }, - (_target: Object, name: string | symbol): any => { sent.push(name); }, - (_target: Object, name: string | symbol): any => { sent.push(name); }, - (_target: Object, name: string | symbol): any => { sent.push(name); } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name"); - assert.deepEqual(sent, ["name", "name", "name", "name"]); - }); - - it("DecoratorCorrectTargetInPipelineForPropertyDescriptorOverload", () => { - let sent: Object[] = []; - let A = { }; - let B = { }; - let C = { }; - let decorators = [ - (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, - (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, - (target: Object, _name: string | symbol): any => { sent.push(target); return A; }, - (target: Object, _name: string | symbol): any => { sent.push(target); return B; } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name", C); - assert.deepEqual(sent, [target, target, target, target]); - }); - - it("DecoratorCorrectNameInPipelineForPropertyDescriptorOverload", () => { - let sent: (symbol | string)[] = []; - let A = { }; - let B = { }; - let C = { }; - let decorators = [ - (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, - (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, - (_target: Object, name: string | symbol): any => { sent.push(name); return A; }, - (_target: Object, name: string | symbol): any => { sent.push(name); return B; } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name", C); - assert.deepEqual(sent, ["name", "name", "name", "name"]); - }); - - it("DecoratorCorrectDescriptorInPipelineForPropertyDescriptorOverload", () => { - let sent: PropertyDescriptor[] = []; - let A = { }; - let B = { }; - let C = { }; - let decorators = [ - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return A; }, - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return B; } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name", C); - assert.deepEqual(sent, [C, B, A, A]); - }); -}); diff --git a/test/full/reflect-definemetadata.ts b/test/full/reflect-definemetadata.ts deleted file mode 100644 index 54ecc37..0000000 --- a/test/full/reflect-definemetadata.ts +++ /dev/null @@ -1,20 +0,0 @@ -// 4.1.2 Reflect.defineMetadata ( metadataKey, metadataValue, target, propertyKey ) -// https://rbuckton.github.io/reflect-metadata/#reflect.definemetadata - -/// -require("../../Reflect"); -import { assert } from "chai"; - -describe("Reflect.defineMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.defineMetadata("key", "value", undefined, undefined!), TypeError); - }); - - it("ValidTargetWithoutTargetKey", () => { - assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, undefined!)); - }); - - it("ValidTargetWithTargetKey", () => { - assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, "name")); - }); -}); \ No newline at end of file diff --git a/test/full/reflect-deletemetadata.ts b/test/full/reflect-deletemetadata.ts deleted file mode 100644 index 326cd46..0000000 --- a/test/full/reflect-deletemetadata.ts +++ /dev/null @@ -1,41 +0,0 @@ -// 4.1.10 Reflect.deleteMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.deletemetadata - -/// -require("../../Reflect"); -import { assert } from "chai"; - -describe("Reflect.deleteMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.deleteMetadata("key", undefined, undefined!), TypeError); - }); - - it("WhenNotDefinedWithoutTargetKey", () => { - let obj = {}; - let result = Reflect.deleteMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WhenDefinedWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.deleteMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WhenDefinedOnPrototypeWithoutTargetKey", () => { - let prototype = {}; - Reflect.defineMetadata("key", "value", prototype, undefined!); - let obj = Object.create(prototype); - let result = Reflect.deleteMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("AfterDeleteMetadata", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - Reflect.deleteMetadata("key", obj, undefined!); - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, false); - }); -}); \ No newline at end of file diff --git a/test/full/reflect-getmetadata.ts b/test/full/reflect-getmetadata.ts deleted file mode 100644 index 78e9713..0000000 --- a/test/full/reflect-getmetadata.ts +++ /dev/null @@ -1,54 +0,0 @@ -// 4.1.5 Reflect.getMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadata - -/// -require("../../Reflect"); -import { assert } from "chai"; - -describe("Reflect.getMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.getMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadata("key", obj, undefined!); - assert.equal(result, undefined); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getMetadata("key", obj, undefined!); - assert.equal(result, "value"); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getMetadata("key", obj, undefined!); - assert.equal(result, "value"); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadata("key", obj, "name"); - assert.equal(result, undefined); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getMetadata("key", obj, "name"); - assert.equal(result, "value"); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getMetadata("key", obj, "name"); - assert.equal(result, "value"); - }); -}); \ No newline at end of file diff --git a/test/full/reflect-getmetadatakeys.ts b/test/full/reflect-getmetadatakeys.ts deleted file mode 100644 index 45003d4..0000000 --- a/test/full/reflect-getmetadatakeys.ts +++ /dev/null @@ -1,101 +0,0 @@ -// 4.1.8 Reflect.getMetadataKeys ( target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadatakeys - -/// -require("../../Reflect"); -import { assert } from "chai"; - -describe("Reflect.getMetadataKeys", () => { - it("KeysInvalidTarget", () => { - // 1. If Type(target) is not Object, throw a TypeError exception. - assert.throws(() => Reflect.getMetadataKeys(undefined, undefined!), TypeError); - }); - - it("KeysWithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, []); - }); - - it("KeysWithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key"]); - }); - - it("KeysOrderWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderAfterRedefineWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - Reflect.defineMetadata("key1", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderWithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - Reflect.defineMetadata("key2", "value", prototype, undefined!); - let obj = Object.create(prototype); - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0", "key2"]); - }); - - it("KeysWithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, []); - }); - - it("KeysWithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key"]); - }); - - it("KeysOrderAfterRedefineWithTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, "name"); - Reflect.defineMetadata("key0", "value", obj, "name"); - Reflect.defineMetadata("key1", "value", obj, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderWithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - Reflect.defineMetadata("key2", "value", prototype, "name"); - let obj = Object.create(prototype); - Reflect.defineMetadata("key1", "value", obj, "name"); - Reflect.defineMetadata("key0", "value", obj, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key1", "key0", "key2"]); - }); -}); \ No newline at end of file diff --git a/test/full/reflect-getownmetadata.ts b/test/full/reflect-getownmetadata.ts deleted file mode 100644 index de05797..0000000 --- a/test/full/reflect-getownmetadata.ts +++ /dev/null @@ -1,54 +0,0 @@ -// 4.1.7 Reflect.getOwnMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadata - -/// -require("../../Reflect"); -import { assert } from "chai"; - -describe("Reflect.getOwnMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.getOwnMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadata("key", obj, undefined!); - assert.equal(result, undefined); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getOwnMetadata("key", obj, undefined!); - assert.equal(result, "value"); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getOwnMetadata("key", obj, undefined!); - assert.equal(result, undefined); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadata("key", obj, "name"); - assert.equal(result, undefined); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getOwnMetadata("key", obj, "name"); - assert.equal(result, "value"); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getOwnMetadata("key", obj, "name"); - assert.equal(result, undefined); - }); -}); \ No newline at end of file diff --git a/test/full/reflect-getownmetadatakeys.ts b/test/full/reflect-getownmetadatakeys.ts deleted file mode 100644 index eb5bce9..0000000 --- a/test/full/reflect-getownmetadatakeys.ts +++ /dev/null @@ -1,81 +0,0 @@ -// 4.1.9 Reflect.getOwnMetadataKeysKeys ( target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadatakeys - -/// -require("../../Reflect"); -import { assert } from "chai"; - -describe("Reflect.getOwnMetadataKeys", () => { - it("KeysKeysInvalidTarget", () => { - // 1. If Type(target) is not Object, throw a TypeError exception. - assert.throws(() => Reflect.getOwnMetadataKeys(undefined, undefined!), TypeError); - }); - - it("KeysWithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, []); - }); - - it("KeysWithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, []); - }); - - it("KeysOrderWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderAfterRedefineWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - Reflect.defineMetadata("key1", "value", obj, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysWithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, []); - }); - - it("KeysWithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, []); - }); - - it("KeysOrderAfterRedefineWithTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, "name"); - Reflect.defineMetadata("key0", "value", obj, "name"); - Reflect.defineMetadata("key1", "value", obj, "name"); - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key1", "key0"]); - }); -}); \ No newline at end of file diff --git a/test/full/reflect-hasmetadata.ts b/test/full/reflect-hasmetadata.ts deleted file mode 100644 index eae3213..0000000 --- a/test/full/reflect-hasmetadata.ts +++ /dev/null @@ -1,54 +0,0 @@ -// 4.1.4 Reflect.hasMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.hasmetadata - -/// -require("../../Reflect"); -import { assert } from "chai"; - -describe("Reflect.hasMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.hasMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.hasMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.hasMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasMetadata("key", obj, "name"); - assert.equal(result, false); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.hasMetadata("key", obj, "name"); - assert.equal(result, true); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.hasMetadata("key", obj, "name"); - assert.equal(result, true); - }); -}); \ No newline at end of file diff --git a/test/full/reflect-hasownmetadata.ts b/test/full/reflect-hasownmetadata.ts deleted file mode 100644 index 22c6fdb..0000000 --- a/test/full/reflect-hasownmetadata.ts +++ /dev/null @@ -1,54 +0,0 @@ -// 4.1.5 Reflect.hasOwnMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.hasownmetadata - -/// -require("../../Reflect"); -import { assert } from "chai"; - -describe("Reflect.hasOwnMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.hasOwnMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasOwnMetadata("key", obj, "name"); - assert.equal(result, false); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.hasOwnMetadata("key", obj, "name"); - assert.equal(result, true); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.hasOwnMetadata("key", obj, "name"); - assert.equal(result, false); - }); -}); \ No newline at end of file diff --git a/test/full/reflect-metadata.ts b/test/full/reflect-metadata.ts deleted file mode 100644 index 0d56ead..0000000 --- a/test/full/reflect-metadata.ts +++ /dev/null @@ -1,41 +0,0 @@ -// 4.1.2 Reflect.metadata ( metadataKey, metadataValue ) -// https://rbuckton.github.io/reflect-metadata/#reflect.metadata - -/// -require("../../Reflect"); -import { assert } from "chai"; - -describe("Reflect.metadata", () => { - it("ReturnsDecoratorFunction", () => { - let result = Reflect.metadata("key", "value"); - assert.equal(typeof result, "function"); - }); - - it("DecoratorThrowsWithInvalidTargetWithTargetKey", () => { - let decorator = Reflect.metadata("key", "value"); - assert.throws(() => decorator(undefined!, "name"), TypeError); - }); - - it("DecoratorThrowsWithInvalidTargetKey", () => { - let decorator = Reflect.metadata("key", "value"); - assert.throws(() => decorator({}, {}), TypeError); - }); - - it("OnTargetWithoutTargetKey", () => { - let decorator = Reflect.metadata("key", "value"); - let target = function () {} - decorator(target); - - let result = Reflect.hasOwnMetadata("key", target, undefined!); - assert.equal(result, true); - }); - - it("OnTargetWithTargetKey", () => { - let decorator = Reflect.metadata("key", "value"); - let target = {} - decorator(target, "name"); - - let result = Reflect.hasOwnMetadata("key", target, "name"); - assert.equal(result, true); - }); -}); \ No newline at end of file diff --git a/test/full/reflect-other.ts b/test/full/reflect-other.ts deleted file mode 100644 index c164cbb..0000000 --- a/test/full/reflect-other.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as fs from "fs"; -import { assert } from "chai"; - -describe("Reflect", () => { - it("does not overwrite existing implementation", () => { - const defineMetadata = Reflect.defineMetadata; - - const reflectPath = require.resolve("../../Reflect.js"); - const reflectContent = fs.readFileSync(reflectPath, "utf8"); - const reflectFunction = Function(reflectContent); - reflectFunction(); - - assert.strictEqual(Reflect.defineMetadata, defineMetadata); - }); -}); \ No newline at end of file diff --git a/test/lite/reflect-decorate.ts b/test/lite/reflect-decorate.ts deleted file mode 100644 index 7e89179..0000000 --- a/test/lite/reflect-decorate.ts +++ /dev/null @@ -1,211 +0,0 @@ -// Reflect.decorate ( decorators, target [, propertyKey [, descriptor] ] ) - -/// -require("../../ReflectLite"); -import { assert } from "chai"; - -describe("Reflect.decorate", () => { - it("ThrowsIfDecoratorsArgumentNotArrayForFunctionOverload", () => { - let target = function() { }; - assert.throws(() => Reflect.decorate(undefined!, target, undefined!, undefined), TypeError); - }); - - it("ThrowsIfTargetArgumentNotFunctionForFunctionOverload", () => { - let decorators: (MethodDecorator | PropertyDecorator)[] = []; - let target = {}; - assert.throws(() => Reflect.decorate(decorators, target, undefined!, undefined), TypeError); - }); - - it("ThrowsIfDecoratorsArgumentNotArrayForPropertyOverload", () => { - let target = {}; - let name = "name"; - assert.throws(() => Reflect.decorate(undefined!, target, name, undefined), TypeError); - }); - - it("ThrowsIfTargetArgumentNotObjectForPropertyOverload", () => { - let decorators: (MethodDecorator | PropertyDecorator)[] = []; - let target = 1; - let name = "name"; - assert.throws(() => Reflect.decorate(decorators, target, name, undefined), TypeError); - }); - - it("ThrowsIfDecoratorsArgumentNotArrayForPropertyDescriptorOverload", () => { - let target = {}; - let name = "name"; - let descriptor = {}; - assert.throws(() => Reflect.decorate(undefined!, target, name, descriptor), TypeError); - }); - - it("ThrowsIfTargetArgumentNotObjectForPropertyDescriptorOverload", () => { - let decorators: (MethodDecorator | PropertyDecorator)[] = []; - let target = 1; - let name = "name"; - let descriptor = {}; - assert.throws(() => Reflect.decorate(decorators, target, name, descriptor), TypeError); - }); - - it("ExecutesDecoratorsInReverseOrderForFunctionOverload", () => { - let order: number[] = []; - let decorators = [ - (_target: Function): void => { order.push(0); }, - (_target: Function): void => { order.push(1); } - ]; - let target = function() { }; - Reflect.decorate(decorators, target); - assert.deepEqual(order, [1, 0]); - }); - - it("ExecutesDecoratorsInReverseOrderForPropertyOverload", () => { - let order: number[] = []; - let decorators = [ - (_target: Object, _name: string | symbol): void => { order.push(0); }, - (_target: Object, _name: string | symbol): void => { order.push(1); } - ]; - let target = {}; - let name = "name"; - Reflect.decorate(decorators, target, name, undefined); - assert.deepEqual(order, [1, 0]); - }); - - it("ExecutesDecoratorsInReverseOrderForPropertyDescriptorOverload", () => { - let order: number[] = []; - let decorators = [ - (_target: Object, _name: string | symbol): void => { order.push(0); }, - (_target: Object, _name: string | symbol): void => { order.push(1); } - ]; - let target = {}; - let name = "name"; - let descriptor = {}; - Reflect.decorate(decorators, target, name, descriptor); - assert.deepEqual(order, [1, 0]); - }); - - it("DecoratorPipelineForFunctionOverload", () => { - let A = function A(): void { }; - let B = function B(): void { }; - let decorators = [ - (_target: Function): any => { return undefined; }, - (_target: Function): any => { return A; }, - (_target: Function): any => { return B; } - ]; - let target = function (): void { }; - let result = Reflect.decorate(decorators, target); - assert.strictEqual(result, A); - }); - - it("DecoratorPipelineForPropertyOverload", () => { - let A = {}; - let B = {}; - let decorators = [ - (_target: Object, _name: string | symbol): any => { return undefined; }, - (_target: Object, _name: string | symbol): any => { return A; }, - (_target: Object, _name: string | symbol): any => { return B; } - ]; - let target = {}; - let result = Reflect.decorate(decorators, target, "name", undefined); - assert.strictEqual(result, A); - }); - - it("DecoratorPipelineForPropertyDescriptorOverload", () => { - let A = {}; - let B = {}; - let C = {}; - let decorators = [ - (_target: Object, _name: string | symbol): any => { return undefined; }, - (_target: Object, _name: string | symbol): any => { return A; }, - (_target: Object, _name: string | symbol): any => { return B; } - ]; - let target = {}; - let result = Reflect.decorate(decorators, target, "name", C); - assert.strictEqual(result, A); - }); - - it("DecoratorCorrectTargetInPipelineForFunctionOverload", () => { - let sent: Function[] = []; - let A = function A(): void { }; - let B = function B(): void { }; - let decorators = [ - (target: Function): any => { sent.push(target); return undefined; }, - (target: Function): any => { sent.push(target); return undefined; }, - (target: Function): any => { sent.push(target); return A; }, - (target: Function): any => { sent.push(target); return B; } - ]; - let target = function (): void { }; - Reflect.decorate(decorators, target); - assert.deepEqual(sent, [target, B, A, A]); - }); - - it("DecoratorCorrectTargetInPipelineForPropertyOverload", () => { - let sent: Object[] = []; - let decorators = [ - (target: Object, _name: string | symbol): any => { sent.push(target); }, - (target: Object, _name: string | symbol): any => { sent.push(target); }, - (target: Object, _name: string | symbol): any => { sent.push(target); }, - (target: Object, _name: string | symbol): any => { sent.push(target); } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name"); - assert.deepEqual(sent, [target, target, target, target]); - }); - - it("DecoratorCorrectNameInPipelineForPropertyOverload", () => { - let sent: (symbol | string)[] = []; - let decorators = [ - (_target: Object, name: string | symbol): any => { sent.push(name); }, - (_target: Object, name: string | symbol): any => { sent.push(name); }, - (_target: Object, name: string | symbol): any => { sent.push(name); }, - (_target: Object, name: string | symbol): any => { sent.push(name); } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name"); - assert.deepEqual(sent, ["name", "name", "name", "name"]); - }); - - it("DecoratorCorrectTargetInPipelineForPropertyDescriptorOverload", () => { - let sent: Object[] = []; - let A = { }; - let B = { }; - let C = { }; - let decorators = [ - (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, - (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, - (target: Object, _name: string | symbol): any => { sent.push(target); return A; }, - (target: Object, _name: string | symbol): any => { sent.push(target); return B; } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name", C); - assert.deepEqual(sent, [target, target, target, target]); - }); - - it("DecoratorCorrectNameInPipelineForPropertyDescriptorOverload", () => { - let sent: (symbol | string)[] = []; - let A = { }; - let B = { }; - let C = { }; - let decorators = [ - (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, - (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, - (_target: Object, name: string | symbol): any => { sent.push(name); return A; }, - (_target: Object, name: string | symbol): any => { sent.push(name); return B; } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name", C); - assert.deepEqual(sent, ["name", "name", "name", "name"]); - }); - - it("DecoratorCorrectDescriptorInPipelineForPropertyDescriptorOverload", () => { - let sent: PropertyDescriptor[] = []; - let A = { }; - let B = { }; - let C = { }; - let decorators = [ - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return A; }, - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return B; } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name", C); - assert.deepEqual(sent, [C, B, A, A]); - }); -}); diff --git a/test/lite/reflect-definemetadata.ts b/test/lite/reflect-definemetadata.ts deleted file mode 100644 index 7e8d01d..0000000 --- a/test/lite/reflect-definemetadata.ts +++ /dev/null @@ -1,20 +0,0 @@ -// 4.1.2 Reflect.defineMetadata ( metadataKey, metadataValue, target, propertyKey ) -// https://rbuckton.github.io/reflect-metadata/#reflect.definemetadata - -/// -require("../../ReflectLite"); -import { assert } from "chai"; - -describe("Reflect.defineMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.defineMetadata("key", "value", undefined, undefined!), TypeError); - }); - - it("ValidTargetWithoutTargetKey", () => { - assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, undefined!)); - }); - - it("ValidTargetWithTargetKey", () => { - assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, "name")); - }); -}); \ No newline at end of file diff --git a/test/lite/reflect-deletemetadata.ts b/test/lite/reflect-deletemetadata.ts deleted file mode 100644 index a54405c..0000000 --- a/test/lite/reflect-deletemetadata.ts +++ /dev/null @@ -1,41 +0,0 @@ -// 4.1.10 Reflect.deleteMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.deletemetadata - -/// -require("../../ReflectLite"); -import { assert } from "chai"; - -describe("Reflect.deleteMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.deleteMetadata("key", undefined, undefined!), TypeError); - }); - - it("WhenNotDefinedWithoutTargetKey", () => { - let obj = {}; - let result = Reflect.deleteMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WhenDefinedWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.deleteMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WhenDefinedOnPrototypeWithoutTargetKey", () => { - let prototype = {}; - Reflect.defineMetadata("key", "value", prototype, undefined!); - let obj = Object.create(prototype); - let result = Reflect.deleteMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("AfterDeleteMetadata", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - Reflect.deleteMetadata("key", obj, undefined!); - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, false); - }); -}); \ No newline at end of file diff --git a/test/lite/reflect-getmetadata.ts b/test/lite/reflect-getmetadata.ts deleted file mode 100644 index 32af3b6..0000000 --- a/test/lite/reflect-getmetadata.ts +++ /dev/null @@ -1,54 +0,0 @@ -// 4.1.5 Reflect.getMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadata - -/// -require("../../ReflectLite"); -import { assert } from "chai"; - -describe("Reflect.getMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.getMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadata("key", obj, undefined!); - assert.equal(result, undefined); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getMetadata("key", obj, undefined!); - assert.equal(result, "value"); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getMetadata("key", obj, undefined!); - assert.equal(result, "value"); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadata("key", obj, "name"); - assert.equal(result, undefined); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getMetadata("key", obj, "name"); - assert.equal(result, "value"); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getMetadata("key", obj, "name"); - assert.equal(result, "value"); - }); -}); \ No newline at end of file diff --git a/test/lite/reflect-getmetadatakeys.ts b/test/lite/reflect-getmetadatakeys.ts deleted file mode 100644 index dda97fd..0000000 --- a/test/lite/reflect-getmetadatakeys.ts +++ /dev/null @@ -1,101 +0,0 @@ -// 4.1.8 Reflect.getMetadataKeys ( target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadatakeys - -/// -require("../../ReflectLite"); -import { assert } from "chai"; - -describe("Reflect.getMetadataKeys", () => { - it("KeysInvalidTarget", () => { - // 1. If Type(target) is not Object, throw a TypeError exception. - assert.throws(() => Reflect.getMetadataKeys(undefined, undefined!), TypeError); - }); - - it("KeysWithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, []); - }); - - it("KeysWithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key"]); - }); - - it("KeysOrderWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderAfterRedefineWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - Reflect.defineMetadata("key1", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderWithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - Reflect.defineMetadata("key2", "value", prototype, undefined!); - let obj = Object.create(prototype); - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0", "key2"]); - }); - - it("KeysWithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, []); - }); - - it("KeysWithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key"]); - }); - - it("KeysOrderAfterRedefineWithTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, "name"); - Reflect.defineMetadata("key0", "value", obj, "name"); - Reflect.defineMetadata("key1", "value", obj, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderWithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - Reflect.defineMetadata("key2", "value", prototype, "name"); - let obj = Object.create(prototype); - Reflect.defineMetadata("key1", "value", obj, "name"); - Reflect.defineMetadata("key0", "value", obj, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key1", "key0", "key2"]); - }); -}); \ No newline at end of file diff --git a/test/lite/reflect-getownmetadata.ts b/test/lite/reflect-getownmetadata.ts deleted file mode 100644 index f7df4eb..0000000 --- a/test/lite/reflect-getownmetadata.ts +++ /dev/null @@ -1,54 +0,0 @@ -// 4.1.7 Reflect.getOwnMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadata - -/// -require("../../ReflectLite"); -import { assert } from "chai"; - -describe("Reflect.getOwnMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.getOwnMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadata("key", obj, undefined!); - assert.equal(result, undefined); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getOwnMetadata("key", obj, undefined!); - assert.equal(result, "value"); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getOwnMetadata("key", obj, undefined!); - assert.equal(result, undefined); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadata("key", obj, "name"); - assert.equal(result, undefined); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getOwnMetadata("key", obj, "name"); - assert.equal(result, "value"); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getOwnMetadata("key", obj, "name"); - assert.equal(result, undefined); - }); -}); \ No newline at end of file diff --git a/test/lite/reflect-getownmetadatakeys.ts b/test/lite/reflect-getownmetadatakeys.ts deleted file mode 100644 index fdc6a25..0000000 --- a/test/lite/reflect-getownmetadatakeys.ts +++ /dev/null @@ -1,81 +0,0 @@ -// 4.1.9 Reflect.getOwnMetadataKeysKeys ( target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadatakeys - -/// -require("../../ReflectLite"); -import { assert } from "chai"; - -describe("Reflect.getOwnMetadataKeys", () => { - it("KeysKeysInvalidTarget", () => { - // 1. If Type(target) is not Object, throw a TypeError exception. - assert.throws(() => Reflect.getOwnMetadataKeys(undefined, undefined!), TypeError); - }); - - it("KeysWithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, []); - }); - - it("KeysWithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, []); - }); - - it("KeysOrderWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderAfterRedefineWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - Reflect.defineMetadata("key1", "value", obj, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysWithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, []); - }); - - it("KeysWithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, []); - }); - - it("KeysOrderAfterRedefineWithTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, "name"); - Reflect.defineMetadata("key0", "value", obj, "name"); - Reflect.defineMetadata("key1", "value", obj, "name"); - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key1", "key0"]); - }); -}); \ No newline at end of file diff --git a/test/lite/reflect-hasmetadata.ts b/test/lite/reflect-hasmetadata.ts deleted file mode 100644 index 2083196..0000000 --- a/test/lite/reflect-hasmetadata.ts +++ /dev/null @@ -1,54 +0,0 @@ -// 4.1.4 Reflect.hasMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.hasmetadata - -/// -require("../../ReflectLite"); -import { assert } from "chai"; - -describe("Reflect.hasMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.hasMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.hasMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.hasMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasMetadata("key", obj, "name"); - assert.equal(result, false); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.hasMetadata("key", obj, "name"); - assert.equal(result, true); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.hasMetadata("key", obj, "name"); - assert.equal(result, true); - }); -}); \ No newline at end of file diff --git a/test/lite/reflect-hasownmetadata.ts b/test/lite/reflect-hasownmetadata.ts deleted file mode 100644 index d54b25c..0000000 --- a/test/lite/reflect-hasownmetadata.ts +++ /dev/null @@ -1,54 +0,0 @@ -// 4.1.5 Reflect.hasOwnMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.hasownmetadata - -/// -require("../../ReflectLite"); -import { assert } from "chai"; - -describe("Reflect.hasOwnMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.hasOwnMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasOwnMetadata("key", obj, "name"); - assert.equal(result, false); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.hasOwnMetadata("key", obj, "name"); - assert.equal(result, true); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.hasOwnMetadata("key", obj, "name"); - assert.equal(result, false); - }); -}); \ No newline at end of file diff --git a/test/lite/reflect-metadata.ts b/test/lite/reflect-metadata.ts deleted file mode 100644 index e502d9b..0000000 --- a/test/lite/reflect-metadata.ts +++ /dev/null @@ -1,41 +0,0 @@ -// 4.1.2 Reflect.metadata ( metadataKey, metadataValue ) -// https://rbuckton.github.io/reflect-metadata/#reflect.metadata - -/// -require("../../ReflectLite"); -import { assert } from "chai"; - -describe("Reflect.metadata", () => { - it("ReturnsDecoratorFunction", () => { - let result = Reflect.metadata("key", "value"); - assert.equal(typeof result, "function"); - }); - - it("DecoratorThrowsWithInvalidTargetWithTargetKey", () => { - let decorator = Reflect.metadata("key", "value"); - assert.throws(() => decorator(undefined!, "name"), TypeError); - }); - - it("DecoratorThrowsWithInvalidTargetKey", () => { - let decorator = Reflect.metadata("key", "value"); - assert.throws(() => decorator({}, {}), TypeError); - }); - - it("OnTargetWithoutTargetKey", () => { - let decorator = Reflect.metadata("key", "value"); - let target = function () {} - decorator(target); - - let result = Reflect.hasOwnMetadata("key", target, undefined!); - assert.equal(result, true); - }); - - it("OnTargetWithTargetKey", () => { - let decorator = Reflect.metadata("key", "value"); - let target = {} - decorator(target, "name"); - - let result = Reflect.hasOwnMetadata("key", target, "name"); - assert.equal(result, true); - }); -}); \ No newline at end of file diff --git a/test/lite/reflect-other.ts b/test/lite/reflect-other.ts deleted file mode 100644 index 878a1a8..0000000 --- a/test/lite/reflect-other.ts +++ /dev/null @@ -1,17 +0,0 @@ -/// - -import * as fs from "fs"; -import { assert } from "chai"; - -describe("Reflect", () => { - it("does not overwrite existing implementation", () => { - const defineMetadata = Reflect.defineMetadata; - - const reflectPath = require.resolve("../../ReflectLite.js"); - const reflectContent = fs.readFileSync(reflectPath, "utf8"); - const reflectFunction = Function(reflectContent); - reflectFunction(); - - assert.strictEqual(Reflect.defineMetadata, defineMetadata); - }); -}); \ No newline at end of file diff --git a/test/lite/tsconfig.json b/test/lite/tsconfig.json deleted file mode 100644 index 038cdd3..0000000 --- a/test/lite/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "noImplicitAny": true, - "sourceMap": true, - "module": "commonjs", - "types": ["node", "mocha"], - "typeRoots": ["../../node_modules/@types"], - }, - "include": [ - "**/*.ts" - ] -} \ No newline at end of file diff --git a/test/no-conflict/reflect-decorate.ts b/test/no-conflict/reflect-decorate.ts deleted file mode 100644 index 01d4c3b..0000000 --- a/test/no-conflict/reflect-decorate.ts +++ /dev/null @@ -1,210 +0,0 @@ -// Reflect.decorate ( decorators, target [, propertyKey [, descriptor] ] ) - -const Reflect = require("../../ReflectNoConflict"); -import { assert } from "chai"; - -describe("Reflect.decorate", () => { - it("ThrowsIfDecoratorsArgumentNotArrayForFunctionOverload", () => { - let target = function() { }; - assert.throws(() => Reflect.decorate(undefined!, target, undefined!, undefined), TypeError); - }); - - it("ThrowsIfTargetArgumentNotFunctionForFunctionOverload", () => { - let decorators: (MethodDecorator | PropertyDecorator)[] = []; - let target = {}; - assert.throws(() => Reflect.decorate(decorators, target, undefined!, undefined), TypeError); - }); - - it("ThrowsIfDecoratorsArgumentNotArrayForPropertyOverload", () => { - let target = {}; - let name = "name"; - assert.throws(() => Reflect.decorate(undefined!, target, name, undefined), TypeError); - }); - - it("ThrowsIfTargetArgumentNotObjectForPropertyOverload", () => { - let decorators: (MethodDecorator | PropertyDecorator)[] = []; - let target = 1; - let name = "name"; - assert.throws(() => Reflect.decorate(decorators, target, name, undefined), TypeError); - }); - - it("ThrowsIfDecoratorsArgumentNotArrayForPropertyDescriptorOverload", () => { - let target = {}; - let name = "name"; - let descriptor = {}; - assert.throws(() => Reflect.decorate(undefined!, target, name, descriptor), TypeError); - }); - - it("ThrowsIfTargetArgumentNotObjectForPropertyDescriptorOverload", () => { - let decorators: (MethodDecorator | PropertyDecorator)[] = []; - let target = 1; - let name = "name"; - let descriptor = {}; - assert.throws(() => Reflect.decorate(decorators, target, name, descriptor), TypeError); - }); - - it("ExecutesDecoratorsInReverseOrderForFunctionOverload", () => { - let order: number[] = []; - let decorators = [ - (_target: Function): void => { order.push(0); }, - (_target: Function): void => { order.push(1); } - ]; - let target = function() { }; - Reflect.decorate(decorators, target); - assert.deepEqual(order, [1, 0]); - }); - - it("ExecutesDecoratorsInReverseOrderForPropertyOverload", () => { - let order: number[] = []; - let decorators = [ - (_target: Object, _name: string | symbol): void => { order.push(0); }, - (_target: Object, _name: string | symbol): void => { order.push(1); } - ]; - let target = {}; - let name = "name"; - Reflect.decorate(decorators, target, name, undefined); - assert.deepEqual(order, [1, 0]); - }); - - it("ExecutesDecoratorsInReverseOrderForPropertyDescriptorOverload", () => { - let order: number[] = []; - let decorators = [ - (_target: Object, _name: string | symbol): void => { order.push(0); }, - (_target: Object, _name: string | symbol): void => { order.push(1); } - ]; - let target = {}; - let name = "name"; - let descriptor = {}; - Reflect.decorate(decorators, target, name, descriptor); - assert.deepEqual(order, [1, 0]); - }); - - it("DecoratorPipelineForFunctionOverload", () => { - let A = function A(): void { }; - let B = function B(): void { }; - let decorators = [ - (_target: Function): any => { return undefined; }, - (_target: Function): any => { return A; }, - (_target: Function): any => { return B; } - ]; - let target = function (): void { }; - let result = Reflect.decorate(decorators, target); - assert.strictEqual(result, A); - }); - - it("DecoratorPipelineForPropertyOverload", () => { - let A = {}; - let B = {}; - let decorators = [ - (_target: Object, _name: string | symbol): any => { return undefined; }, - (_target: Object, _name: string | symbol): any => { return A; }, - (_target: Object, _name: string | symbol): any => { return B; } - ]; - let target = {}; - let result = Reflect.decorate(decorators, target, "name", undefined); - assert.strictEqual(result, A); - }); - - it("DecoratorPipelineForPropertyDescriptorOverload", () => { - let A = {}; - let B = {}; - let C = {}; - let decorators = [ - (_target: Object, _name: string | symbol): any => { return undefined; }, - (_target: Object, _name: string | symbol): any => { return A; }, - (_target: Object, _name: string | symbol): any => { return B; } - ]; - let target = {}; - let result = Reflect.decorate(decorators, target, "name", C); - assert.strictEqual(result, A); - }); - - it("DecoratorCorrectTargetInPipelineForFunctionOverload", () => { - let sent: Function[] = []; - let A = function A(): void { }; - let B = function B(): void { }; - let decorators = [ - (target: Function): any => { sent.push(target); return undefined; }, - (target: Function): any => { sent.push(target); return undefined; }, - (target: Function): any => { sent.push(target); return A; }, - (target: Function): any => { sent.push(target); return B; } - ]; - let target = function (): void { }; - Reflect.decorate(decorators, target); - assert.deepEqual(sent, [target, B, A, A]); - }); - - it("DecoratorCorrectTargetInPipelineForPropertyOverload", () => { - let sent: Object[] = []; - let decorators = [ - (target: Object, _name: string | symbol): any => { sent.push(target); }, - (target: Object, _name: string | symbol): any => { sent.push(target); }, - (target: Object, _name: string | symbol): any => { sent.push(target); }, - (target: Object, _name: string | symbol): any => { sent.push(target); } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name"); - assert.deepEqual(sent, [target, target, target, target]); - }); - - it("DecoratorCorrectNameInPipelineForPropertyOverload", () => { - let sent: (symbol | string)[] = []; - let decorators = [ - (_target: Object, name: string | symbol): any => { sent.push(name); }, - (_target: Object, name: string | symbol): any => { sent.push(name); }, - (_target: Object, name: string | symbol): any => { sent.push(name); }, - (_target: Object, name: string | symbol): any => { sent.push(name); } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name"); - assert.deepEqual(sent, ["name", "name", "name", "name"]); - }); - - it("DecoratorCorrectTargetInPipelineForPropertyDescriptorOverload", () => { - let sent: Object[] = []; - let A = { }; - let B = { }; - let C = { }; - let decorators = [ - (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, - (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, - (target: Object, _name: string | symbol): any => { sent.push(target); return A; }, - (target: Object, _name: string | symbol): any => { sent.push(target); return B; } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name", C); - assert.deepEqual(sent, [target, target, target, target]); - }); - - it("DecoratorCorrectNameInPipelineForPropertyDescriptorOverload", () => { - let sent: (symbol | string)[] = []; - let A = { }; - let B = { }; - let C = { }; - let decorators = [ - (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, - (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, - (_target: Object, name: string | symbol): any => { sent.push(name); return A; }, - (_target: Object, name: string | symbol): any => { sent.push(name); return B; } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name", C); - assert.deepEqual(sent, ["name", "name", "name", "name"]); - }); - - it("DecoratorCorrectDescriptorInPipelineForPropertyDescriptorOverload", () => { - let sent: PropertyDescriptor[] = []; - let A = { }; - let B = { }; - let C = { }; - let decorators = [ - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return A; }, - (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return B; } - ]; - let target = { }; - Reflect.decorate(decorators, target, "name", C); - assert.deepEqual(sent, [C, B, A, A]); - }); -}); diff --git a/test/no-conflict/reflect-definemetadata.ts b/test/no-conflict/reflect-definemetadata.ts deleted file mode 100644 index 5f98e2e..0000000 --- a/test/no-conflict/reflect-definemetadata.ts +++ /dev/null @@ -1,19 +0,0 @@ -// 4.1.2 Reflect.defineMetadata ( metadataKey, metadataValue, target, propertyKey ) -// https://rbuckton.github.io/reflect-metadata/#reflect.definemetadata - -const Reflect = require("../../ReflectNoConflict"); -import { assert } from "chai"; - -describe("Reflect.defineMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.defineMetadata("key", "value", undefined, undefined!), TypeError); - }); - - it("ValidTargetWithoutTargetKey", () => { - assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, undefined!)); - }); - - it("ValidTargetWithTargetKey", () => { - assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, "name")); - }); -}); \ No newline at end of file diff --git a/test/no-conflict/reflect-deletemetadata.ts b/test/no-conflict/reflect-deletemetadata.ts deleted file mode 100644 index cd704ce..0000000 --- a/test/no-conflict/reflect-deletemetadata.ts +++ /dev/null @@ -1,40 +0,0 @@ -// 4.1.10 Reflect.deleteMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.deletemetadata - -const Reflect = require("../../ReflectNoConflict"); -import { assert } from "chai"; - -describe("Reflect.deleteMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.deleteMetadata("key", undefined, undefined!), TypeError); - }); - - it("WhenNotDefinedWithoutTargetKey", () => { - let obj = {}; - let result = Reflect.deleteMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WhenDefinedWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.deleteMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WhenDefinedOnPrototypeWithoutTargetKey", () => { - let prototype = {}; - Reflect.defineMetadata("key", "value", prototype, undefined!); - let obj = Object.create(prototype); - let result = Reflect.deleteMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("AfterDeleteMetadata", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - Reflect.deleteMetadata("key", obj, undefined!); - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, false); - }); -}); \ No newline at end of file diff --git a/test/no-conflict/reflect-getmetadata.ts b/test/no-conflict/reflect-getmetadata.ts deleted file mode 100644 index 7c3ef9b..0000000 --- a/test/no-conflict/reflect-getmetadata.ts +++ /dev/null @@ -1,60 +0,0 @@ -// 4.1.5 Reflect.getMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadata - -const Reflect = require("../../ReflectNoConflict"); -import { assert } from "chai"; - -describe("Reflect.getMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.getMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadata("key", obj, undefined!); - assert.equal(result, undefined); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getMetadata("key", obj, undefined!); - assert.equal(result, "value"); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getMetadata("key", obj, undefined!); - assert.equal(result, "value"); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadata("key", obj, "name"); - assert.equal(result, undefined); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getMetadata("key", obj, "name"); - assert.equal(result, "value"); - }); - - it("WhenKeyIsNaN", () => { - let obj = {}; - Reflect.defineMetadata(NaN, "value", obj, "name"); - let result = Reflect.getMetadata(NaN, obj, "name"); - assert.equal(result, "value"); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getMetadata("key", obj, "name"); - assert.equal(result, "value"); - }); -}); \ No newline at end of file diff --git a/test/no-conflict/reflect-getmetadatakeys.ts b/test/no-conflict/reflect-getmetadatakeys.ts deleted file mode 100644 index f07cf39..0000000 --- a/test/no-conflict/reflect-getmetadatakeys.ts +++ /dev/null @@ -1,100 +0,0 @@ -// 4.1.8 Reflect.getMetadataKeys ( target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadatakeys - -const Reflect = require("../../ReflectNoConflict"); -import { assert } from "chai"; - -describe("Reflect.getMetadataKeys", () => { - it("KeysInvalidTarget", () => { - // 1. If Type(target) is not Object, throw a TypeError exception. - assert.throws(() => Reflect.getMetadataKeys(undefined, undefined!), TypeError); - }); - - it("KeysWithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, []); - }); - - it("KeysWithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key"]); - }); - - it("KeysOrderWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderAfterRedefineWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - Reflect.defineMetadata("key1", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderWithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - Reflect.defineMetadata("key2", "value", prototype, undefined!); - let obj = Object.create(prototype); - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - let result = Reflect.getMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0", "key2"]); - }); - - it("KeysWithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, []); - }); - - it("KeysWithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key"]); - }); - - it("KeysOrderAfterRedefineWithTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, "name"); - Reflect.defineMetadata("key0", "value", obj, "name"); - Reflect.defineMetadata("key1", "value", obj, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderWithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - Reflect.defineMetadata("key2", "value", prototype, "name"); - let obj = Object.create(prototype); - Reflect.defineMetadata("key1", "value", obj, "name"); - Reflect.defineMetadata("key0", "value", obj, "name"); - let result = Reflect.getMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key1", "key0", "key2"]); - }); -}); \ No newline at end of file diff --git a/test/no-conflict/reflect-getownmetadata.ts b/test/no-conflict/reflect-getownmetadata.ts deleted file mode 100644 index 496a814..0000000 --- a/test/no-conflict/reflect-getownmetadata.ts +++ /dev/null @@ -1,53 +0,0 @@ -// 4.1.7 Reflect.getOwnMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadata - -const Reflect = require("../../ReflectNoConflict"); -import { assert } from "chai"; - -describe("Reflect.getOwnMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.getOwnMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadata("key", obj, undefined!); - assert.equal(result, undefined); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getOwnMetadata("key", obj, undefined!); - assert.equal(result, "value"); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getOwnMetadata("key", obj, undefined!); - assert.equal(result, undefined); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadata("key", obj, "name"); - assert.equal(result, undefined); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getOwnMetadata("key", obj, "name"); - assert.equal(result, "value"); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getOwnMetadata("key", obj, "name"); - assert.equal(result, undefined); - }); -}); \ No newline at end of file diff --git a/test/no-conflict/reflect-getownmetadatakeys.ts b/test/no-conflict/reflect-getownmetadatakeys.ts deleted file mode 100644 index 3af293e..0000000 --- a/test/no-conflict/reflect-getownmetadatakeys.ts +++ /dev/null @@ -1,80 +0,0 @@ -// 4.1.9 Reflect.getOwnMetadataKeysKeys ( target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadatakeys - -const Reflect = require("../../ReflectNoConflict"); -import { assert } from "chai"; - -describe("Reflect.getOwnMetadataKeys", () => { - it("KeysKeysInvalidTarget", () => { - // 1. If Type(target) is not Object, throw a TypeError exception. - assert.throws(() => Reflect.getOwnMetadataKeys(undefined, undefined!), TypeError); - }); - - it("KeysWithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, []); - }); - - it("KeysWithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, []); - }); - - it("KeysOrderWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysOrderAfterRedefineWithoutTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, undefined!); - Reflect.defineMetadata("key0", "value", obj, undefined!); - Reflect.defineMetadata("key1", "value", obj, undefined!); - let result = Reflect.getOwnMetadataKeys(obj, undefined!); - assert.deepEqual(result, ["key1", "key0"]); - }); - - it("KeysWithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, []); - }); - - it("KeysWithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key"]); - }); - - it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, []); - }); - - it("KeysOrderAfterRedefineWithTargetKey", () => { - let obj = {}; - Reflect.defineMetadata("key1", "value", obj, "name"); - Reflect.defineMetadata("key0", "value", obj, "name"); - Reflect.defineMetadata("key1", "value", obj, "name"); - let result = Reflect.getOwnMetadataKeys(obj, "name"); - assert.deepEqual(result, ["key1", "key0"]); - }); -}); \ No newline at end of file diff --git a/test/no-conflict/reflect-hasmetadata.ts b/test/no-conflict/reflect-hasmetadata.ts deleted file mode 100644 index 8d17b08..0000000 --- a/test/no-conflict/reflect-hasmetadata.ts +++ /dev/null @@ -1,53 +0,0 @@ -// 4.1.4 Reflect.hasMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.hasmetadata - -const Reflect = require("../../ReflectNoConflict"); -import { assert } from "chai"; - -describe("Reflect.hasMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.hasMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.hasMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.hasMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasMetadata("key", obj, "name"); - assert.equal(result, false); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.hasMetadata("key", obj, "name"); - assert.equal(result, true); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.hasMetadata("key", obj, "name"); - assert.equal(result, true); - }); -}); \ No newline at end of file diff --git a/test/no-conflict/reflect-hasownmetadata.ts b/test/no-conflict/reflect-hasownmetadata.ts deleted file mode 100644 index ace42a4..0000000 --- a/test/no-conflict/reflect-hasownmetadata.ts +++ /dev/null @@ -1,53 +0,0 @@ -// 4.1.5 Reflect.hasOwnMetadata ( metadataKey, target [, propertyKey] ) -// https://rbuckton.github.io/reflect-metadata/#reflect.hasownmetadata - -const Reflect = require("../../ReflectNoConflict"); -import { assert } from "chai"; - -describe("Reflect.hasOwnMetadata", () => { - it("InvalidTarget", () => { - assert.throws(() => Reflect.hasOwnMetadata("key", undefined, undefined!), TypeError); - }); - - it("WithoutTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WithoutTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, undefined!); - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, true); - }); - - it("WithoutTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, undefined!); - let result = Reflect.hasOwnMetadata("key", obj, undefined!); - assert.equal(result, false); - }); - - it("WithTargetKeyWhenNotDefined", () => { - let obj = {}; - let result = Reflect.hasOwnMetadata("key", obj, "name"); - assert.equal(result, false); - }); - - it("WithTargetKeyWhenDefined", () => { - let obj = {}; - Reflect.defineMetadata("key", "value", obj, "name"); - let result = Reflect.hasOwnMetadata("key", obj, "name"); - assert.equal(result, true); - }); - - it("WithTargetKeyWhenDefinedOnPrototype", () => { - let prototype = {}; - let obj = Object.create(prototype); - Reflect.defineMetadata("key", "value", prototype, "name"); - let result = Reflect.hasOwnMetadata("key", obj, "name"); - assert.equal(result, false); - }); -}); \ No newline at end of file diff --git a/test/no-conflict/reflect-metadata.ts b/test/no-conflict/reflect-metadata.ts deleted file mode 100644 index 05f133f..0000000 --- a/test/no-conflict/reflect-metadata.ts +++ /dev/null @@ -1,41 +0,0 @@ -// 4.1.2 Reflect.metadata ( metadataKey, metadataValue ) -// https://rbuckton.github.io/reflect-metadata/#reflect.metadata - -/// -const Reflect_ = require("../../ReflectNoConflict") as typeof Reflect; -import { assert } from "chai"; - -describe("Reflect.metadata", () => { - it("ReturnsDecoratorFunction", () => { - let result = Reflect_.metadata("key", "value"); - assert.equal(typeof result, "function"); - }); - - it("DecoratorThrowsWithInvalidTargetWithTargetKey", () => { - let decorator = Reflect_.metadata("key", "value"); - assert.throws(() => decorator(undefined!, "name"), TypeError); - }); - - it("DecoratorThrowsWithInvalidTargetKey", () => { - let decorator = Reflect_.metadata("key", "value"); - assert.throws(() => decorator({}, {}), TypeError); - }); - - it("OnTargetWithoutTargetKey", () => { - let decorator = Reflect_.metadata("key", "value"); - let target = function () {} - decorator(target); - - let result = Reflect_.hasOwnMetadata("key", target, undefined!); - assert.equal(result, true); - }); - - it("OnTargetWithTargetKey", () => { - let decorator = Reflect_.metadata("key", "value"); - let target = {} - decorator(target, "name"); - - let result = Reflect_.hasOwnMetadata("key", target, "name"); - assert.equal(result, true); - }); -}); \ No newline at end of file diff --git a/test/no-conflict/tsconfig.json b/test/no-conflict/tsconfig.json deleted file mode 100644 index 038cdd3..0000000 --- a/test/no-conflict/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "noImplicitAny": true, - "sourceMap": true, - "module": "commonjs", - "types": ["node", "mocha"], - "typeRoots": ["../../node_modules/@types"], - }, - "include": [ - "**/*.ts" - ] -} \ No newline at end of file diff --git a/test/reflect-decorate.ts b/test/reflect-decorate.ts new file mode 100644 index 0000000..b07430b --- /dev/null +++ b/test/reflect-decorate.ts @@ -0,0 +1,294 @@ +// Reflect.decorate ( decorators, target [, propertyKey [, descriptor] ] ) + +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites) { + describe(name, () => { + describe("Reflect.decorate", () => { + it("ThrowsIfDecoratorsArgumentNotArrayForFunctionOverload", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + let target = function() { }; + assert.throws(() => Reflect.decorate(undefined!, target, undefined!, undefined), TypeError); + }); + + it("ThrowsIfTargetArgumentNotFunctionForFunctionOverload", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + let decorators: (MethodDecorator | PropertyDecorator)[] = []; + let target = {}; + assert.throws(() => Reflect.decorate(decorators, target, undefined!, undefined), TypeError); + }); + + it("ThrowsIfDecoratorsArgumentNotArrayForPropertyOverload", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + let target = {}; + let name = "name"; + assert.throws(() => Reflect.decorate(undefined!, target, name, undefined), TypeError); + }); + + it("ThrowsIfTargetArgumentNotObjectForPropertyOverload", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + let decorators: (MethodDecorator | PropertyDecorator)[] = []; + let target = 1; + let name = "name"; + assert.throws(() => Reflect.decorate(decorators, target, name, undefined), TypeError); + }); + + it("ThrowsIfDecoratorsArgumentNotArrayForPropertyDescriptorOverload", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + let target = {}; + let name = "name"; + let descriptor = {}; + assert.throws(() => Reflect.decorate(undefined!, target, name, descriptor), TypeError); + }); + + it("ThrowsIfTargetArgumentNotObjectForPropertyDescriptorOverload", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + let decorators: (MethodDecorator | PropertyDecorator)[] = []; + let target = 1; + let name = "name"; + let descriptor = {}; + assert.throws(() => Reflect.decorate(decorators, target, name, descriptor), TypeError); + }); + + it("ExecutesDecoratorsInReverseOrderForFunctionOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let order: number[] = []; + let decorators = [ + (_target: Function): void => { order.push(0); }, + (_target: Function): void => { order.push(1); } + ]; + let target = function() { }; + Reflect.decorate(decorators, target); + assert.deepEqual(order, [1, 0]); + }); + + it("ExecutesDecoratorsInReverseOrderForPropertyOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let order: number[] = []; + let decorators = [ + (_target: Object, _name: string | symbol): void => { order.push(0); }, + (_target: Object, _name: string | symbol): void => { order.push(1); } + ]; + let target = {}; + let name = "name"; + Reflect.decorate(decorators, target, name, undefined); + assert.deepEqual(order, [1, 0]); + }); + + it("ExecutesDecoratorsInReverseOrderForPropertyDescriptorOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let order: number[] = []; + let decorators = [ + (_target: Object, _name: string | symbol): void => { order.push(0); }, + (_target: Object, _name: string | symbol): void => { order.push(1); } + ]; + let target = {}; + let name = "name"; + let descriptor = {}; + Reflect.decorate(decorators, target, name, descriptor); + assert.deepEqual(order, [1, 0]); + }); + + it("DecoratorPipelineForFunctionOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let A = function A(): void { }; + let B = function B(): void { }; + let decorators = [ + (_target: Function): any => { return undefined; }, + (_target: Function): any => { return A; }, + (_target: Function): any => { return B; } + ]; + let target = function (): void { }; + let result = Reflect.decorate(decorators, target); + assert.strictEqual(result, A); + }); + + it("DecoratorPipelineForPropertyOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let A = {}; + let B = {}; + let decorators = [ + (_target: Object, _name: string | symbol): any => { return undefined; }, + (_target: Object, _name: string | symbol): any => { return A; }, + (_target: Object, _name: string | symbol): any => { return B; } + ]; + let target = {}; + let result = Reflect.decorate(decorators, target, "name", undefined); + assert.strictEqual(result, A); + }); + + it("DecoratorPipelineForPropertyDescriptorOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let A = {}; + let B = {}; + let C = {}; + let decorators = [ + (_target: Object, _name: string | symbol): any => { return undefined; }, + (_target: Object, _name: string | symbol): any => { return A; }, + (_target: Object, _name: string | symbol): any => { return B; } + ]; + let target = {}; + let result = Reflect.decorate(decorators, target, "name", C); + assert.strictEqual(result, A); + }); + + it("DecoratorCorrectTargetInPipelineForFunctionOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let sent: Function[] = []; + let A = function A(): void { }; + let B = function B(): void { }; + let decorators = [ + (target: Function): any => { sent.push(target); return undefined; }, + (target: Function): any => { sent.push(target); return undefined; }, + (target: Function): any => { sent.push(target); return A; }, + (target: Function): any => { sent.push(target); return B; } + ]; + let target = function (): void { }; + Reflect.decorate(decorators, target); + assert.deepEqual(sent, [target, B, A, A]); + }); + + it("DecoratorCorrectTargetInPipelineForPropertyOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let sent: Object[] = []; + let decorators = [ + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); }, + (target: Object, _name: string | symbol): any => { sent.push(target); } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name"); + assert.deepEqual(sent, [target, target, target, target]); + }); + + it("DecoratorCorrectNameInPipelineForPropertyOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let sent: (symbol | string)[] = []; + let decorators = [ + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); }, + (_target: Object, name: string | symbol): any => { sent.push(name); } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name"); + assert.deepEqual(sent, ["name", "name", "name", "name"]); + }); + + it("DecoratorCorrectTargetInPipelineForPropertyDescriptorOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let sent: Object[] = []; + let A = { }; + let B = { }; + let C = { }; + let decorators = [ + (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return undefined; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return A; }, + (target: Object, _name: string | symbol): any => { sent.push(target); return B; } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name", C); + assert.deepEqual(sent, [target, target, target, target]); + }); + + it("DecoratorCorrectNameInPipelineForPropertyDescriptorOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let sent: (symbol | string)[] = []; + let A = { }; + let B = { }; + let C = { }; + let decorators = [ + (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return undefined; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return A; }, + (_target: Object, name: string | symbol): any => { sent.push(name); return B; } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name", C); + assert.deepEqual(sent, ["name", "name", "name", "name"]); + }); + + it("DecoratorCorrectDescriptorInPipelineForPropertyDescriptorOverload", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let sent: PropertyDescriptor[] = []; + let A = { }; + let B = { }; + let C = { }; + let decorators = [ + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return undefined; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return A; }, + (_target: Object, _name: string | symbol, descriptor: PropertyDescriptor): any => { sent.push(descriptor); return B; } + ]; + let target = { }; + Reflect.decorate(decorators, target, "name", C); + assert.deepEqual(sent, [C, B, A, A]); + }); + }); + }); +} diff --git a/test/reflect-definemetadata.ts b/test/reflect-definemetadata.ts new file mode 100644 index 0000000..733e0d7 --- /dev/null +++ b/test/reflect-definemetadata.ts @@ -0,0 +1,39 @@ +// 4.1.2 Reflect.defineMetadata ( metadataKey, metadataValue, target, propertyKey ) +// https://rbuckton.github.io/reflect-metadata/#reflect.definemetadata + +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites) { + describe(name, () => { + describe("Reflect.defineMetadata", () => { + it("InvalidTarget", () => { + debugger; + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + assert.throws(() => Reflect.defineMetadata("key", "value", undefined, undefined!), TypeError); + }); + + it("ValidTargetWithoutTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, undefined!)); + }); + + it("ValidTargetWithTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + assert.doesNotThrow(() => Reflect.defineMetadata("key", "value", { }, "name")); + }); + }); + }); +} \ No newline at end of file diff --git a/test/reflect-deletemetadata.ts b/test/reflect-deletemetadata.ts new file mode 100644 index 0000000..e5613d2 --- /dev/null +++ b/test/reflect-deletemetadata.ts @@ -0,0 +1,67 @@ +// 4.1.10 Reflect.deleteMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.deletemetadata + +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites) { + describe(name, () => { + describe("Reflect.deleteMetadata", () => { + it("InvalidTarget", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + assert.throws(() => Reflect.deleteMetadata("key", undefined, undefined!), TypeError); + }); + + it("WhenNotDefinedWithoutTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.deleteMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WhenDefinedWithoutTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.deleteMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WhenDefinedOnPrototypeWithoutTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + Reflect.defineMetadata("key", "value", prototype, undefined!); + let obj = Object.create(prototype); + let result = Reflect.deleteMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("AfterDeleteMetadata", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + Reflect.deleteMetadata("key", obj, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + }); + }); +} \ No newline at end of file diff --git a/test/reflect-getmetadata.ts b/test/reflect-getmetadata.ts new file mode 100644 index 0000000..2cdf48a --- /dev/null +++ b/test/reflect-getmetadata.ts @@ -0,0 +1,88 @@ +// 4.1.5 Reflect.getMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadata + +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites) { + describe(name, () => { + describe("Reflect.getMetadata", () => { + it("InvalidTarget", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + assert.throws(() => Reflect.getMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.getMetadata("key", obj, undefined!); + assert.equal(result, undefined); + }); + + it("WithoutTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getMetadata("key", obj, undefined!); + assert.equal(result, "value"); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getMetadata("key", obj, undefined!); + assert.equal(result, "value"); + }); + + it("WithTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.getMetadata("key", obj, "name"); + assert.equal(result, undefined); + }); + + it("WithTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getMetadata("key", obj, "name"); + assert.equal(result, "value"); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getMetadata("key", obj, "name"); + assert.equal(result, "value"); + }); + }); + }); +} \ No newline at end of file diff --git a/test/reflect-getmetadatakeys.ts b/test/reflect-getmetadatakeys.ts new file mode 100644 index 0000000..477eda8 --- /dev/null +++ b/test/reflect-getmetadatakeys.ts @@ -0,0 +1,155 @@ +// 4.1.8 Reflect.getMetadataKeys ( target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getmetadatakeys + +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites) { + describe(name, () => { + describe("Reflect.getMetadataKeys", () => { + it("KeysInvalidTarget", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + // 1. If Type(target) is not Object, throw a TypeError exception. + assert.throws(() => Reflect.getMetadataKeys(undefined, undefined!), TypeError); + }); + + it("KeysWithoutTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, []); + }); + + it("KeysWithoutTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key"]); + }); + + it("KeysOrderWithoutTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderAfterRedefineWithoutTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + Reflect.defineMetadata("key1", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderWithoutTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + Reflect.defineMetadata("key2", "value", prototype, undefined!); + let obj = Object.create(prototype); + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0", "key2"]); + }); + + it("KeysWithTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, []); + }); + + it("KeysWithTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key"]); + }); + + it("KeysOrderAfterRedefineWithTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, "name"); + Reflect.defineMetadata("key0", "value", obj, "name"); + Reflect.defineMetadata("key1", "value", obj, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderWithTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + Reflect.defineMetadata("key2", "value", prototype, "name"); + let obj = Object.create(prototype); + Reflect.defineMetadata("key1", "value", obj, "name"); + Reflect.defineMetadata("key0", "value", obj, "name"); + let result = Reflect.getMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key1", "key0", "key2"]); + }); + }); + }); +} \ No newline at end of file diff --git a/test/reflect-getownmetadata.ts b/test/reflect-getownmetadata.ts new file mode 100644 index 0000000..2a3041c --- /dev/null +++ b/test/reflect-getownmetadata.ts @@ -0,0 +1,88 @@ +// 4.1.7 Reflect.getOwnMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadata + +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites) { + describe(name, () => { + describe("Reflect.getOwnMetadata", () => { + it("InvalidTarget", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + assert.throws(() => Reflect.getOwnMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => {0 + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.getOwnMetadata("key", obj, undefined!); + assert.equal(result, undefined); + }); + + it("WithoutTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getOwnMetadata("key", obj, undefined!); + assert.equal(result, "value"); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getOwnMetadata("key", obj, undefined!); + assert.equal(result, undefined); + }); + + it("WithTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.getOwnMetadata("key", obj, "name"); + assert.equal(result, undefined); + }); + + it("WithTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getOwnMetadata("key", obj, "name"); + assert.equal(result, "value"); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getOwnMetadata("key", obj, "name"); + assert.equal(result, undefined); + }); + }); + }); +} \ No newline at end of file diff --git a/test/reflect-getownmetadatakeys.ts b/test/reflect-getownmetadatakeys.ts new file mode 100644 index 0000000..018aaab --- /dev/null +++ b/test/reflect-getownmetadatakeys.ts @@ -0,0 +1,127 @@ +// 4.1.9 Reflect.getOwnMetadataKeysKeys ( target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.getownmetadatakeys + +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites) { + describe(name, () => { + describe("Reflect.getOwnMetadataKeys", () => { + it("KeysKeysInvalidTarget", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + // 1. If Type(target) is not Object, throw a TypeError exception. + assert.throws(() => Reflect.getOwnMetadataKeys(undefined, undefined!), TypeError); + }); + + it("KeysWithoutTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, []); + }); + + it("KeysWithoutTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithoutTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, []); + }); + + it("KeysOrderWithoutTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysOrderAfterRedefineWithoutTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, undefined!); + Reflect.defineMetadata("key0", "value", obj, undefined!); + Reflect.defineMetadata("key1", "value", obj, undefined!); + let result = Reflect.getOwnMetadataKeys(obj, undefined!); + assert.deepEqual(result, ["key1", "key0"]); + }); + + it("KeysWithTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, []); + }); + + it("KeysWithTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key"]); + }); + + it("KeysWithTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, []); + }); + + it("KeysOrderAfterRedefineWithTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key1", "value", obj, "name"); + Reflect.defineMetadata("key0", "value", obj, "name"); + Reflect.defineMetadata("key1", "value", obj, "name"); + let result = Reflect.getOwnMetadataKeys(obj, "name"); + assert.deepEqual(result, ["key1", "key0"]); + }); + }); + }); +} \ No newline at end of file diff --git a/test/reflect-hasmetadata.ts b/test/reflect-hasmetadata.ts new file mode 100644 index 0000000..1be3ea2 --- /dev/null +++ b/test/reflect-hasmetadata.ts @@ -0,0 +1,88 @@ +// 4.1.4 Reflect.hasMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.hasmetadata + +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites) { + describe(name, () => { + describe("Reflect.hasMetadata", () => { + it("InvalidTarget", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + assert.throws(() => Reflect.hasMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.hasMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WithoutTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.hasMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.hasMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WithTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.hasMetadata("key", obj, "name"); + assert.equal(result, false); + }); + + it("WithTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.hasMetadata("key", obj, "name"); + assert.equal(result, true); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.hasMetadata("key", obj, "name"); + assert.equal(result, true); + }); + }); + }); +} \ No newline at end of file diff --git a/test/reflect-hasownmetadata.ts b/test/reflect-hasownmetadata.ts new file mode 100644 index 0000000..5cbd4cb --- /dev/null +++ b/test/reflect-hasownmetadata.ts @@ -0,0 +1,88 @@ +// 4.1.5 Reflect.hasOwnMetadata ( metadataKey, target [, propertyKey] ) +// https://rbuckton.github.io/reflect-metadata/#reflect.hasownmetadata + +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites) { + describe(name, () => { + describe("Reflect.hasOwnMetadata", () => { + it("InvalidTarget", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + assert.throws(() => Reflect.hasOwnMetadata("key", undefined, undefined!), TypeError); + }); + + it("WithoutTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WithoutTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, true); + }); + + it("WithoutTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, undefined!); + let result = Reflect.hasOwnMetadata("key", obj, undefined!); + assert.equal(result, false); + }); + + it("WithTargetKeyWhenNotDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + let result = Reflect.hasOwnMetadata("key", obj, "name"); + assert.equal(result, false); + }); + + it("WithTargetKeyWhenDefined", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let obj = {}; + Reflect.defineMetadata("key", "value", obj, "name"); + let result = Reflect.hasOwnMetadata("key", obj, "name"); + assert.equal(result, true); + }); + + it("WithTargetKeyWhenDefinedOnPrototype", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let prototype = {}; + let obj = Object.create(prototype); + Reflect.defineMetadata("key", "value", prototype, "name"); + let result = Reflect.hasOwnMetadata("key", obj, "name"); + assert.equal(result, false); + }); + }); + }); +} \ No newline at end of file diff --git a/test/reflect-metadata.ts b/test/reflect-metadata.ts new file mode 100644 index 0000000..8d99cc4 --- /dev/null +++ b/test/reflect-metadata.ts @@ -0,0 +1,68 @@ +// 4.1.2 Reflect.metadata ( metadataKey, metadataValue ) +// https://rbuckton.github.io/reflect-metadata/#reflect.metadata + +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites) { + describe(name, () => { + describe("Reflect.metadata", () => { + it("ReturnsDecoratorFunction", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let result = Reflect.metadata("key", "value"); + assert.equal(typeof result, "function"); + }); + + it("DecoratorThrowsWithInvalidTargetWithTargetKey", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + let decorator = Reflect.metadata("key", "value"); + assert.throws(() => decorator(undefined!, "name"), TypeError); + }); + + it("DecoratorThrowsWithInvalidTargetKey", () => { + const { Reflect, TypeError } = script(context)` + ${header} + exports.Reflect = Reflect; + exports.TypeError = TypeError; + `; + let decorator = Reflect.metadata("key", "value"); + assert.throws(() => decorator({}, {}), TypeError); + }); + + it("OnTargetWithoutTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let decorator = Reflect.metadata("key", "value"); + let target = function () {} + decorator(target); + + let result = Reflect.hasOwnMetadata("key", target, undefined!); + assert.equal(result, true); + }); + + it("OnTargetWithTargetKey", () => { + const { Reflect } = script(context)` + ${header} + exports.Reflect = Reflect; + `; + let decorator = Reflect.metadata("key", "value"); + let target = {} + decorator(target, "name"); + + let result = Reflect.hasOwnMetadata("key", target, "name"); + assert.equal(result, true); + }); + }); + }); +} \ No newline at end of file diff --git a/test/reflect-other.ts b/test/reflect-other.ts new file mode 100644 index 0000000..83007b1 --- /dev/null +++ b/test/reflect-other.ts @@ -0,0 +1,29 @@ +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites.filter(s => s.global)) { + describe(name, () => { + describe("Reflect", () => { + it("does not clobber existing implementation", () => { + const { Reflect, defineMetadata, obj } = script(context)` + const fs = require("fs"); + ${header} + + exports.Reflect = Reflect; + exports.defineMetadata = Reflect.defineMetadata; + exports.obj = {}; + Reflect.defineMetadata("key", "value", exports.obj); + + const reflectPath = require.resolve("../Reflect.js"); + const reflectContent = fs.readFileSync(reflectPath, "utf8"); + const reflectFunction = Function(reflectContent); + reflectFunction(); + `; + + assert.notStrictEqual(Reflect.defineMetadata, defineMetadata); + assert.strictEqual(Reflect.getOwnMetadata("key", obj), "value"); + }); + }); + }); +} \ No newline at end of file diff --git a/test/registry.ts b/test/registry.ts new file mode 100644 index 0000000..c1f4086 --- /dev/null +++ b/test/registry.ts @@ -0,0 +1,59 @@ +/// +/// +import { assert } from "chai"; +import { script } from "./vm"; +import { suites } from "./suites"; + +for (const { name, header, context } of suites.filter(s => s.global && !s.polyfill)) { + describe(`ReflectNoConflict + ${name}`, () => { + describe("MetadataRegistry", () => { + it("defines registry", () => { + const { registry } = script(context)` + const ReflectNoConflict = require("../ReflectNoConflict"); + ${header} + + const registrySymbol = Symbol.for("@reflect-metadata:registry"); + exports.registry = Reflect[registrySymbol]; + `; + assert.isDefined(registry); + }); + it("two registries", () => { + const { provider1, provider2 } = script(context)` + const ReflectNoConflict = require("../ReflectNoConflict"); + ${header} + + const registrySymbol = Symbol.for("@reflect-metadata:registry"); + const registry = Reflect[registrySymbol]; + + const obj1 = {}; + ReflectNoConflict.defineMetadata("key", "value", obj1); + + const obj2 = {}; + Reflect.defineMetadata("key", "value", obj2); + + const provider1 = registry.getProvider(obj1, undefined); + const provider2 = registry.getProvider(obj2, undefined); + + exports.provider1 = provider1; + exports.provider2 = provider2; + exports.registry = registry; + `; + assert.isDefined(provider1); + assert.isDefined(provider2); + assert.notStrictEqual(provider1, provider2); + }); + it("registries are shared", () => { + const { ReflectNoConflict, Reflect } = script(context)` + const ReflectNoConflict = require("../ReflectNoConflict"); + ${header} + + exports.ReflectNoConflict = ReflectNoConflict; + exports.Reflect = Reflect; + `; + const obj = {}; + ReflectNoConflict.defineMetadata("key", "value", obj); + assert.isTrue(Reflect.hasOwnMetadata("key", obj)); + }); + }); + }); +} \ No newline at end of file diff --git a/test/registry/registry.ts b/test/registry/registry.ts deleted file mode 100644 index 6a1d00a..0000000 --- a/test/registry/registry.ts +++ /dev/null @@ -1,31 +0,0 @@ -/// -/// -const ReflectNoConflict = require("../../ReflectNoConflict"); -require("../../Reflect"); -import { assert } from "chai"; - -describe("MetadataRegistry", () => { - it("defines registry", () => { - const registrySymbol = Symbol.for("@reflect-metadata:registry"); - const registry = (Reflect as any)[registrySymbol] as MetadataRegistry; - assert.isDefined(registry); - }); - it("two registries", () => { - const registrySymbol = Symbol.for("@reflect-metadata:registry"); - const registry = (Reflect as any)[registrySymbol] as MetadataRegistry; - const obj1 = {}; - ReflectNoConflict.defineMetadata("key", "value", obj1); - const obj2 = {}; - Reflect.defineMetadata("key", "value", obj2); - const provider1 = registry.getProvider(obj1, undefined); - const provider2 = registry.getProvider(obj2, undefined); - assert.isDefined(provider1); - assert.isDefined(provider2); - assert.notStrictEqual(provider1, provider2); - }); - it("registries are shared", () => { - const obj = {}; - ReflectNoConflict.defineMetadata("key", "value", obj); - assert.isTrue(Reflect.hasOwnMetadata("key", obj)); - }); -}); diff --git a/test/registry/tsconfig.json b/test/registry/tsconfig.json deleted file mode 100644 index 038cdd3..0000000 --- a/test/registry/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "noImplicitAny": true, - "sourceMap": true, - "module": "commonjs", - "types": ["node", "mocha"], - "typeRoots": ["../../node_modules/@types"], - }, - "include": [ - "**/*.ts" - ] -} \ No newline at end of file diff --git a/test/suites.ts b/test/suites.ts new file mode 100644 index 0000000..7fc2216 --- /dev/null +++ b/test/suites.ts @@ -0,0 +1,35 @@ +interface TestSuite { + name: string; + header: string; + global?: boolean; + polyfill?: boolean; + context?: any; +} + +export const suites: TestSuite[] = [ + { + name: "Reflect.js", + header: `require("../Reflect");`, + global: true, + }, + { + name: "Reflect.js (w/polyfill)", + header: `require("../Reflect");`, + global: true, + polyfill: true, + context: { + Map: {}, + Set: {}, + WeakMap: {}, + } + }, + { + name: "ReflectLite.js", + header: `require("../ReflectLite");`, + global: true, + }, + { + name: "ReflectNoConflict.js", + header: `const Reflect = require("../ReflectNoConflict");`, + }, +]; \ No newline at end of file diff --git a/test/full/tsconfig.json b/test/tsconfig.json similarity index 76% rename from test/full/tsconfig.json rename to test/tsconfig.json index 038cdd3..609ebe8 100644 --- a/test/full/tsconfig.json +++ b/test/tsconfig.json @@ -5,7 +5,7 @@ "sourceMap": true, "module": "commonjs", "types": ["node", "mocha"], - "typeRoots": ["../../node_modules/@types"], + "typeRoots": ["../node_modules/@types"], }, "include": [ "**/*.ts" diff --git a/test/vm.ts b/test/vm.ts new file mode 100644 index 0000000..3da0677 --- /dev/null +++ b/test/vm.ts @@ -0,0 +1,61 @@ +/// +import vm = require("vm"); +import mod = require("module"); +import fs = require("fs"); +import path = require("path"); + +class Loader { + cache = new Map(); + context: vm.Context; + constructor(context: vm.Context = { }) { + this.context = vm.createContext(context); + } + load(id: string, filename = id, code?: string): any { + let module = this.cache.get(id); + if (module) return module.exports; + module = { + id, + filename, + exports: {}, + require: undefined, + loaded: false, + paths: undefined!, + children: undefined!, + parent: undefined! + }; + this.cache.set(id, module); + if (mod.builtinModules.indexOf(id) >= 0) { + module.exports = require(id); + module.loaded = true; + } + else { + module.require = this.createRequire(filename); + if (code === undefined) { + code = fs.readFileSync(filename, { encoding: "utf8" }); + } + code = `(function(module, exports, require, __filename, __dirname) {${code}\n})`; + const func = vm.runInContext(code, this.context, { filename }); + func(module, module.exports, module.require, filename, path.dirname(filename)); + module.loaded = true; + } + return module.exports; + } + createRequire(filename: string) { + const req = mod.createRequireFromPath(filename) as NodeRequire; + const require = ((id: string) => this.load(mod.builtinModules.indexOf(id) >= 0 ? id : req.resolve(id))) as NodeRequire; + require.resolve = req.resolve; + return require; + } +} + +export function script(context: vm.Context = {}): (array: TemplateStringsArray, ...args: any[]) => any{ + return (array, ...args) => { + let code = array[0]; + for (let i = 1; i < array.length; i++) { + code += args[i - 1]; + code += array[i]; + } + const loader = new Loader(context); + return loader.load("test.js", __filename, code); + }; +} From ad6f84bd3e793a601f4652a98665bff23e064515 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 13 Dec 2023 11:42:23 -0500 Subject: [PATCH 8/8] Mark as prerelease for testing purposes --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1dd6918..3ca7324 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "reflect-metadata", - "version": "0.2.0", + "version": "0.2.0-pre.0", "description": "Polyfill for Metadata Reflection API", "type": "commonjs", "main": "Reflect.js",