From c87993c408f057c962c9df18ee3fc243dc71af93 Mon Sep 17 00:00:00 2001 From: alin Date: Wed, 31 Jan 2024 15:47:53 +0100 Subject: [PATCH] Remove experimental reflect decorator The @reflect() decorator, along with all related components are now no longer needed. The idea was "good", but very cumbersome and possible too performance demanding. The new @targetMeta() decorator has taken the best out of this experiment and can now be used to associate metadata directly with class methods, which is good enough for now. Developers can use it to store their own "reflection-like" data as metadata, if needed. --- .../src/support/reflections/Reflection.ts | 65 --- .../src/support/reflections/index.ts | 15 - packages/support/src/reflections/Encoder.ts | 159 ------- .../support/src/reflections/Reflection.ts | 156 ------ packages/support/src/reflections/index.ts | 13 - packages/support/src/reflections/reflect.ts | 157 ------ .../src/reflections/toWeakReference.ts | 23 - .../reflections/class-reflection.test.js | 71 --- .../reflections/method-reflection.test.js | 449 ------------------ .../reflections/misc-reflection.test.js | 24 - 10 files changed, 1132 deletions(-) delete mode 100644 packages/contracts/src/support/reflections/Reflection.ts delete mode 100644 packages/support/src/reflections/Encoder.ts delete mode 100644 packages/support/src/reflections/Reflection.ts delete mode 100644 packages/support/src/reflections/reflect.ts delete mode 100644 packages/support/src/reflections/toWeakReference.ts delete mode 100644 tests/browser/packages/support/reflections/class-reflection.test.js delete mode 100644 tests/browser/packages/support/reflections/method-reflection.test.js delete mode 100644 tests/browser/packages/support/reflections/misc-reflection.test.js diff --git a/packages/contracts/src/support/reflections/Reflection.ts b/packages/contracts/src/support/reflections/Reflection.ts deleted file mode 100644 index 51b86343..00000000 --- a/packages/contracts/src/support/reflections/Reflection.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @deprecated TODO: This component must be redesigned or removed entirely... - * - * Reflection - * - * Contains meta information about a target element. - */ -export default interface Reflection -{ - /** - * The name of the element - * - * @returns {string | symbol | undefined} - */ - get name(): string | symbol | undefined; - - /** - * The kind of element - * - * @returns {string} - */ - get kind(): string; - - /** - * Determine if element is declared as static - * - * @returns {boolean} - */ - get static(): boolean; - - /** - * Determine if element is declared as private - * - * @returns {boolean} - */ - get private(): boolean; - - /** - * Opposite of {@link private} - * - * @returns {boolean} - */ - get public(): boolean; - - /** - * Target element - * - * **Note**: value is undefined if target element is not an - * object (e.g. if a primitive value), or if target element - * otherwise cannot be referenced. - * - * @returns {object | undefined} - */ - get target(): object | undefined; - - /** - * Owner of target - * - * Typically, this will correspond to the class that defines - * the target (not class instance). - * - * @returns {object | undefined} - */ - get owner(): object | undefined; -} \ No newline at end of file diff --git a/packages/contracts/src/support/reflections/index.ts b/packages/contracts/src/support/reflections/index.ts index 961aa3c8..a6fdf909 100644 --- a/packages/contracts/src/support/reflections/index.ts +++ b/packages/contracts/src/support/reflections/index.ts @@ -1,21 +1,6 @@ -import Reflection from "./Reflection"; - /** * Support Reflections identifier * * @type {Symbol} */ export const SUPPORT_REFLECTIONS: unique symbol = Symbol('@aedart/contracts/support/reflections'); - -/** - * @deprecated TODO: This component must be redesigned or removed entirely... - * - * Reflections identifier in metadata - * - * @type {symbol} - */ -export const META_REFLECTIONS: unique symbol = Symbol('reflections'); - -export { - type Reflection -} \ No newline at end of file diff --git a/packages/support/src/reflections/Encoder.ts b/packages/support/src/reflections/Encoder.ts deleted file mode 100644 index 1588045b..00000000 --- a/packages/support/src/reflections/Encoder.ts +++ /dev/null @@ -1,159 +0,0 @@ -import type {Context} from "@aedart/contracts/support/meta"; -import type { Reflection as ReflectionContract } from "@aedart/contracts/support/reflections"; -import {Kind} from "@aedart/contracts/support/meta"; -import { toWeakReference } from "./toWeakReference"; -import Reflection from "./Reflection"; - -/** - * @deprecated TODO: This component must be redesigned or removed entirely... - * - * "Encoded" Reflection object - * - * ``` - * 0 = kind, - * 1 = private, - * 2 = static, - * 3 = name, - * 4 = target owner reference, - * ``` - */ -export type EncodedReflection = [ - number, // 0 - number, // 1 - number, // 2 - string | symbol | undefined, // 3 - WeakRef | undefined, // 4 -]; - -/** - * @deprecated TODO: This component must be redesigned or removed entirely... - * - * Encoder - */ -export default class Encoder -{ - /** - * "Encode" a decorator context object and target directly to an array - * - * @param {Context} context - * @param {WeakRef | object | undefined} [owner=undefined] - * - * @returns {EncodedReflection} - * - * @throws {TypeError} If context kind is not supported - */ - static encodeContext( - context: Context, - owner: WeakRef | object | undefined = undefined, - ): EncodedReflection - { - return Encoder.encode( - context.kind, - context.kind === 'class' ? false : context.private, - context.kind === 'class' ? false : context.static, - context.name, - owner - ) - } - - /** - * "Encode" reflection attributes to an array - * - * @param {string} kind - * @param {boolean} isPrivate - * @param {boolean} isStatic - * @param {string | symbol | undefined} name - * @param {WeakRef | object | undefined} [owner=undefined] - * - * @returns {EncodedReflection} - * - * @throws {TypeError} If element kind is not supported - */ - static encode( - kind: string, - isPrivate: boolean, - isStatic: boolean, - name: string | symbol | undefined, - owner: WeakRef | object | undefined = undefined, - ): EncodedReflection - { - return [ - Encoder.encodeElementKind(kind as keyof typeof Kind), // 0 - Number(isPrivate), // 1 - Number(isStatic), // 2 - name, // 3 - toWeakReference(owner) // 4 - ]; - } - - /** - * "Decode" array and create a new instance of given Reflection class - * - * @param {EncodedReflection} arr - * @param {object} target - * @param {{name?: string | symbol | undefined, owner?: object}} [overwrites] - * - * @returns {import('@aedart/contracts/support/reflections')} Reflection instance - * - * @throws {TypeError} - */ - static decode(arr: EncodedReflection, target: object, overwrites: { name?: string | symbol | undefined, owner?: object } = {}): ReflectionContract - { - const min: number = 4; - if (arr.length < min) { - throw new TypeError(`Insufficient elements in array. Expected at least ${min}`); - } - - const name: string | symbol | undefined = (overwrites.name !== undefined) - ? overwrites.name - : arr[3]; - - const owner = (overwrites.owner !== undefined) - ? toWeakReference(overwrites.owner) - : toWeakReference(arr[4] ?? undefined); - - return new Reflection( - Encoder.decodeElementKind(arr[0] as number), - Boolean(arr[1]), - Boolean(arr[2]), - name, - toWeakReference(target), - owner, - ); - } - - /** - * Encode "element kind" to a numeric value - * - * @param {keyof typeof Kind} kind - * - * @returns {number} - * - * @throws {TypeError} If kind is not supported - */ - static encodeElementKind(kind: keyof typeof Kind): number - { - if (!Reflect.has(Kind, kind)) { - throw new TypeError(`Kind: "${kind}" is unsupported`); - } - - return Kind[kind]; - } - - /** - * Decode "element kind" from a numeric value - * - * @param {number} kind - * @returns {string} - * - * @throws {TypeError} If kind is not supported - */ - static decodeElementKind(kind: number): string - { - if (!Reflect.has(Kind, kind)) { - throw new TypeError(`Kind: "${kind}" is unsupported`); - } - - return Kind[kind]; - } -} \ No newline at end of file diff --git a/packages/support/src/reflections/Reflection.ts b/packages/support/src/reflections/Reflection.ts deleted file mode 100644 index 91907f89..00000000 --- a/packages/support/src/reflections/Reflection.ts +++ /dev/null @@ -1,156 +0,0 @@ -import type { Reflection as ReflectionContract } from "@aedart/contracts/support/reflections"; -import { isset } from "@aedart/support/misc"; - -/** - * @deprecated TODO: This component must be redesigned or removed entirely... - * - * Reflection - * - * @see import('@aedart/contracts/support/reflections').Reflection - */ -export default class Reflection implements ReflectionContract -{ - /** - * The kind of element - * - * @type {string} - * @private - */ - readonly #kind: string; - - /** - * The name of the element - * - * @type {string | symbol | undefined} - * @private - */ - readonly #name: string | symbol | undefined; - - /** - * If element is declared as private - * - * @type {boolean} - * @private - */ - readonly #private: boolean; - - /** - * If element is declared as static - * - * @type {boolean} - * @private - */ - readonly #static: boolean; - - /** - * Reference to target element - * - * @type {WeakRef | undefined} - * @private - */ - readonly #target: WeakRef | undefined; - - /** - * Reference to target owner - * - * @type {WeakRef | undefined} - * @private - */ - readonly #owner: WeakRef | undefined; - - /** - * Create new Reflection instance - * - * @see fromArray - * @see fromContext - * - * @param {string} kind - * @param {boolean} isPrivate - * @param {boolean} isStatic - * @param {string | symbol | undefined} name - * @param {WeakRef | undefined} target - * @param {WeakRef | undefined} owner - * - * @throws {TypeError} If `target` or `owner` are not {@link WeakRef} instances - - * `undefined` is allowed. - */ - constructor( - kind: string, - isPrivate: boolean, - isStatic: boolean, - name: string | symbol | undefined, - target: WeakRef | undefined, - owner: WeakRef | undefined, - ) - { - if (isset(target) && !(target instanceof WeakRef)) { - throw new TypeError('Target must be a WeakRef or undefined'); - } - if (isset(owner) && !(owner instanceof WeakRef)) { - throw new TypeError('Owner must be a WeakRef or undefined'); - } - - this.#kind = kind; - this.#name = name; - this.#private = isPrivate; - this.#static = isStatic; - this.#target = target; - this.#owner = owner; - } - - /** - * @inheritdoc - */ - get kind(): string - { - return this.#kind; - } - - /** - * @inheritdoc - */ - get name(): string | symbol | undefined - { - return this.#name; - } - - /** - * @inheritdoc - */ - get private(): boolean - { - return this.#private; - } - - /** - * @inheritdoc - */ - get public(): boolean - { - return !this.private; - } - - /** - * @inheritdoc - */ - get static(): boolean - { - return this.#static; - } - - /** - * @inheritdoc - */ - get target(): object | undefined - { - return this.#target?.deref(); - } - - /** - * @inheritdoc - */ - get owner(): object | undefined - { - return this.#owner?.deref(); - } -} \ No newline at end of file diff --git a/packages/support/src/reflections/index.ts b/packages/support/src/reflections/index.ts index b9b3268d..452ca9ca 100644 --- a/packages/support/src/reflections/index.ts +++ b/packages/support/src/reflections/index.ts @@ -1,16 +1,3 @@ -import Reflection from "./Reflection"; -import Encoder from "./Encoder"; -import {reflect, getReflection} from "./reflect"; - -export * from './toWeakReference'; -export { - Reflection, - Encoder, - - reflect, - getReflection -} - export * from './isCallable'; export * from './isClassConstructor'; export * from './isConstructor'; \ No newline at end of file diff --git a/packages/support/src/reflections/reflect.ts b/packages/support/src/reflections/reflect.ts deleted file mode 100644 index c1a429e5..00000000 --- a/packages/support/src/reflections/reflect.ts +++ /dev/null @@ -1,157 +0,0 @@ -import type {Key} from "@aedart/contracts/support"; -import {type Context, METADATA} from "@aedart/contracts/support/meta"; -import {META_REFLECTIONS, type Reflection} from "@aedart/contracts/support/reflections"; -import {meta, getMeta} from "@aedart/support/meta"; -import Encoder, { EncodedReflection } from "./Encoder"; -import {Constructor} from "@aedart/contracts"; -import { isset } from "@aedart/support/misc"; - -/** - * @deprecated TODO: This component must be redesigned or removed entirely... - * - * Internal registry entry - * - * ``` - * 0 = Meta Key, - * 1 = Weak Reference to owner, - * ``` - */ -type RegistryEntry = [ - Key, - WeakRef -]; - -/** - * @deprecated TODO: This component must be redesigned or removed entirely... - * - * Internal registry of targets and metadata key. - * - * @type {WeakMap} - */ -const registry: WeakMap = new WeakMap(); - -/** - * @deprecated TODO: This component must be redesigned or removed entirely... - * - * Store a "reflection" of the target element, as metadata - * - * @returns {(target: object, context: Context) => (void | ((initialValue: unknown) => unknown))} - */ -export function reflect() -{ - return meta((target: object, context: Context, owner: object) => { - - // For now, only classes and methods are supported... A future version could perhaps extend the functionality - // to offer support for getters, setters, ...etc. - if (!['class', 'method'].includes(context.kind)) { - throw new TypeError(`@reflect() does not support "${context.kind}" (only "class" and "method" are supported)`); - } - - // Create a key for given target - const isStatic: number = (context.kind !== 'class' && context.static) - ? 1 // static element - : 0; // non-static element - - const key: Key = [ - META_REFLECTIONS, - Encoder.encodeElementKind(context.kind).toString(), - isStatic, // Ensures that we do not overwrite static / none-static elements with same name! - context.name ?? 'undefined' // The "undefined" is for anonymous classes (they do not have a name) - ]; - - // Encode parts of the given context... - const value:EncodedReflection = Encoder.encodeContext(context, owner); - - // Save the key and target owner in an internal registry for target, so it can - // be looked it up again... - const registryEntry: RegistryEntry = [ key, new WeakRef(owner) ]; - registry.set(target, registryEntry); - - // In situations when a base class' method is reflected, but overwritten in a child - // class, we store another entry with the overwritten method as target in the internal - // registry. This allows to look up reflection for the overwritten method. - // NOTE: This will work for non-static methods only... - if (context.kind === 'method' && Reflect.has(owner, 'prototype')) { - // @ts-expect-error: TS2339 Owner has a prototype at this point... - const proto = owner.prototype; - - if (isset(proto, proto[context.name]) && proto[context.name] !== target) { - registry.set(proto[context.name], registryEntry); - } - } - - // Finally, return the key-value pair to be stored as metadata. - return { - key, - value - }; - }); -} - -/** - * @deprecated TODO: This component must be redesigned or removed entirely... - * - * Get a "reflection" of given target, if any was stored as metadata - * - * @param {object} target - * - * @returns {Reflection | undefined} - */ -export function getReflection(target: object): Reflection | undefined -{ - const entry: RegistryEntry | undefined = findEntry(target); - if (entry === undefined) { - return undefined; - } - - const owner: object | undefined = entry[1]?.deref(); - if (owner === undefined) { - return undefined; - } - - const encoded: EncodedReflection | undefined | unknown = getMeta(owner, entry[0]); - if (encoded === undefined) { - return undefined; - } - - // Whenever the target is a class (that has metadata), we might have obtained reflection - // metadata via its parent. Therefore, we must ensure that the name is correct. - const overwrites: { name?: string | symbol | undefined, owner?: object } = Object.create(null); - if (METADATA in target) { - overwrites.name = (target as Constructor).name; - overwrites.owner = target; // If we leave this out, then the top-most parent class (that has reflection) - // is set as the target's owner for a class. Could result in strange usage - // of Reflection object of a class? (...Feels inconsistent). - } - - return Encoder.decode(encoded, target, overwrites); -} - -/** - * @deprecated TODO: This component must be redesigned or removed entirely... - * - * Find entry in registry for given target - * - * @param {object} target - * - * @returns {RegistryEntry | undefined} - */ -function findEntry(target: object): RegistryEntry | undefined -{ - const entry: RegistryEntry | undefined = registry.get(target); - - // In case that target is a class (that has metadata), it could have a parent that - // has reflection defined. If so, then we attempt to obtain an entry for given - // parent. - if (entry === undefined && METADATA in target) { - const parent = Reflect.getPrototypeOf(target); - - if (parent !== null && parent !== Reflect.getPrototypeOf(Function)) { - return findEntry(parent); - } - } - - // Return found entry or undefined... - return entry; -} - diff --git a/packages/support/src/reflections/toWeakReference.ts b/packages/support/src/reflections/toWeakReference.ts deleted file mode 100644 index 3f02bd1b..00000000 --- a/packages/support/src/reflections/toWeakReference.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { isset } from "@aedart/support/misc"; - -/** - * @deprecated Use {@link import('@aedart/support/misc').toWeakRef} instead - * - * Converts target object to a weak reference, if not already - * - * @param {WeakRef | object | undefined} [target=undefined] - * - * @returns {WeakRef | undefined} Undefined if no target given or target is not an object - */ -export function toWeakReference(target: WeakRef | object | undefined = undefined): WeakRef | undefined -{ - if (!isset(target)) { - return undefined; - } - - if (target instanceof WeakRef) { - return target; - } - - return new WeakRef(target as object); -} \ No newline at end of file diff --git a/tests/browser/packages/support/reflections/class-reflection.test.js b/tests/browser/packages/support/reflections/class-reflection.test.js deleted file mode 100644 index fb66cd6c..00000000 --- a/tests/browser/packages/support/reflections/class-reflection.test.js +++ /dev/null @@ -1,71 +0,0 @@ -import { reflect, getReflection } from "@aedart/support/reflections"; - -describe('@aedart/support/reflections', () => { - - describe('class', () => { - - it('can reflect class', () => { - - @reflect() - class A {} - - const reflection = getReflection(A); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('A'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('class'); - - expect(reflection.private) - .withContext('Element private visibility incorrect') - .toBeFalse(); - - expect(reflection.static) - .withContext('Element static declaration incorrect') - .toBeFalse(); - - expect(reflection.target) - .withContext('Element target incorrect') - .toEqual(A); - - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(A); - }); - - it('inherits class reflection', () => { - - @reflect() - class A {} - class B extends A {} - class C extends B {} - - const reflection = getReflection(C); - - expect(reflection) - .withContext('No reflection found for target') - .not - .toBeUndefined(); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('C'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('class'); - - expect(reflection.target) - .withContext('Element target incorrect') - .toEqual(C); - - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(C); - }); - - }); -}); \ No newline at end of file diff --git a/tests/browser/packages/support/reflections/method-reflection.test.js b/tests/browser/packages/support/reflections/method-reflection.test.js deleted file mode 100644 index 9c7b90b1..00000000 --- a/tests/browser/packages/support/reflections/method-reflection.test.js +++ /dev/null @@ -1,449 +0,0 @@ -import { reflect, getReflection } from "@aedart/support/reflections"; - -describe('@aedart/support/reflections', () => { - - describe('method', () => { - - it('can reflect method', () => { - - class A { - - @reflect() - foo() {} - } - - const a = new A(); - const reflection = getReflection(a.foo); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('foo'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('method'); - - expect(reflection.private) - .withContext('Element private visibility incorrect') - .toBeFalse(); - - expect(reflection.static) - .withContext('Element static declaration incorrect') - .toBeFalse(); - - expect(reflection.target) - .withContext('Element target incorrect') - .toEqual(a.foo); - - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(A); - }); - - it('inherits method reflection', () => { - - class A { - - @reflect() - foo() {} - } - class B extends A {} - class C extends B {} - - const c = new C(); - const reflection = getReflection(c.foo); - - expect(reflection) - .withContext('No reflection found for target') - .not - .toBeUndefined(); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('foo'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('method'); - - expect(reflection.target) - .withContext('Element target incorrect') - .toEqual(c.foo); - - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(C); - }); - - it('can reflect private method', () => { - - class A { - - @reflect() - #foo() {} - - getFooReflection() - { - return getReflection(this.#foo); - } - } - - const a = new A(); - const reflection = a.getFooReflection(); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('#foo'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('method'); - - expect(reflection.private) - .withContext('Element private visibility incorrect') - .toBeTrue(); - - expect(reflection.static) - .withContext('Element static declaration incorrect') - .toBeFalse(); - - expect(reflection.target) - .withContext('Element target incorrect') - .not - .toBeUndefined(); - - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(A); - }); - - it('inherits private method reflection', () => { - - class A { - - @reflect() - #foo() {} - - getFooReflection() - { - return getReflection(this.#foo); - } - } - class B extends A {} - class C extends B {} - - const c = new C(); - const reflection = c.getFooReflection() - - expect(reflection) - .withContext('No reflection found for target') - .not - .toBeUndefined(); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('#foo'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('method'); - - expect(reflection.private) - .withContext('Element private visibility incorrect') - .toBeTrue(); - - expect(reflection.target) - .withContext('Element target incorrect') - .not - .toBeUndefined(); - - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(C); - }); - - it('can reflect static method', () => { - - class A { - - @reflect() - static foo() {} - } - - const reflection = getReflection(A.foo); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('foo'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('method'); - - expect(reflection.private) - .withContext('Element private visibility incorrect') - .toBeFalse(); - - expect(reflection.static) - .withContext('Element static declaration incorrect') - .toBeTrue(); - - expect(reflection.target) - .withContext('Element target incorrect') - .toEqual(A.foo); - - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(A); - }); - - it('inherits static method reflection', () => { - - class A { - - @reflect() - static foo() {} - } - class B extends A {} - class C extends B {} - - const reflection = getReflection(C.foo); - - expect(reflection) - .withContext('No reflection found for target') - .not - .toBeUndefined(); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('foo'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('method'); - - expect(reflection.static) - .withContext('Element static declaration incorrect') - .toBeTrue(); - - expect(reflection.target) - .withContext('Element target incorrect') - .toEqual(C.foo); - - // NOTE: Here the owner is the class that defines the static method... - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(A); - }); - - it('can reflect private static method', () => { - - class A { - - @reflect() - static #foo() {} - - static getFooReflection() - { - return getReflection(A.#foo); - } - } - - const reflection = A.getFooReflection(); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('#foo'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('method'); - - expect(reflection.private) - .withContext('Element private visibility incorrect') - .toBeTrue(); - - expect(reflection.static) - .withContext('Element static declaration incorrect') - .toBeTrue(); - - expect(reflection.target) - .withContext('Element target incorrect') - .not - .toBeUndefined(); - - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(A); - }); - - it('inherits private static method reflection', () => { - - class A { - - @reflect() - static #foo() {} - - static getFooReflection() - { - return getReflection(A.#foo); - } - } - class B extends A {} - class C extends B {} - - const reflection = C.getFooReflection(); - - expect(reflection) - .withContext('No reflection found for target') - .not - .toBeUndefined(); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('#foo'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('method'); - - expect(reflection.private) - .withContext('Element private visibility incorrect') - .toBeTrue(); - - expect(reflection.static) - .withContext('Element static declaration incorrect') - .toBeTrue(); - - expect(reflection.target) - .withContext('Element target incorrect') - .not - .toBeUndefined(); - - // NOTE: Here the owner is the class that defines the static method... - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(A); - }); - - it('inherits method reflection even when overwritten', () => { - - class A { - - @reflect() - foo() {} - } - class B extends A { - - // Note: method overwrite here... - foo() { - // Note: no super.foo() call here... - } - } - class C extends B {} - - const c = new C(); - const reflection = getReflection(c.foo); - - expect(reflection) - .withContext('No reflection found for target') - .not - .toBeUndefined(); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('foo'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('method'); - - expect(reflection.target) - .withContext('Element target incorrect') - .toEqual(c.foo); - - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(C); - }); - - it('can reflect method and static method with same name', () => { - - class A { - - @reflect() - foo() {} - - @reflect() - static foo() {} - } - - const reflectionOfStatic = getReflection(A.foo); - const a = new A(); - const reflection = getReflection(a.foo); - - - expect(reflectionOfStatic.static) - .withContext('(static foo) Element static declaration incorrect') - .toBeTrue(); - - expect(reflection.static) - .withContext('(foo) Element static declaration incorrect') - .toBeFalse(); - - expect(reflectionOfStatic.target) - .withContext('static Element target incorrect') - .toEqual(A.foo); - - expect(reflection.target) - .withContext('Element target incorrect') - .toEqual(a.foo); - - expect(reflectionOfStatic.owner) - .withContext('static Element owner incorrect') - .toEqual(A); - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(A); - }); - - // TODO: Not sure this can be resolved... - xit('inherits static method reflection even when overwritten', () => { - - class A { - - @reflect() - static foo() {} - } - class B extends A { - - // Note: static method overwrite here... - static foo() {} - } - class C extends B {} - - const reflection = getReflection(C.foo); - - expect(reflection) - .withContext('No reflection found for target') - .not - .toBeUndefined(); - - expect(reflection.name) - .withContext('Element name incorrect') - .toEqual('foo'); - - expect(reflection.kind) - .withContext('Element kind incorrect') - .toEqual('method'); - - expect(reflection.target) - .withContext('Element target incorrect') - .toEqual(C.foo); - - expect(reflection.owner) - .withContext('Element owner incorrect') - .toEqual(C); - }); - }); -}); \ No newline at end of file diff --git a/tests/browser/packages/support/reflections/misc-reflection.test.js b/tests/browser/packages/support/reflections/misc-reflection.test.js deleted file mode 100644 index 39fafd5f..00000000 --- a/tests/browser/packages/support/reflections/misc-reflection.test.js +++ /dev/null @@ -1,24 +0,0 @@ -import { reflect } from "@aedart/support/reflections"; - -describe('@aedart/support/reflections', () => { - - describe('misc', () => { - - it('fails when attempting to reflect unsupported class elements', () => { - - const callback = function() { - - class A { - @reflect() - foo = 'bar'; - } - - return new A(); - } - - expect(callback) - .withContext('Should not support reflect on unsupported class element') - .toThrowError(TypeError); - }); - }); -}); \ No newline at end of file