diff --git a/packages/@ember/-internals/container/lib/container.ts b/packages/@ember/-internals/container/lib/container.ts index 3647776e505..546b85fe351 100644 --- a/packages/@ember/-internals/container/lib/container.ts +++ b/packages/@ember/-internals/container/lib/container.ts @@ -7,7 +7,7 @@ import type { FullName, } from '@ember/-internals/owner'; import { setOwner } from '@ember/-internals/owner'; -import { dictionary } from '@ember/-internals/utils'; +import { dictionary, guidFor } from '@ember/-internals/utils'; import { assert } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; import type { DebugRegistry } from './registry'; @@ -152,7 +152,20 @@ export default class Container { options?: RegisterOptions ): InternalFactory | object | undefined { if (this.isDestroyed) { - throw new Error(`Cannot call \`.lookup('${fullName}')\` after the owner has been destroyed`); + if (macroCondition(isTesting())) { + let guid = guidFor(this.owner); + // SAFETY: cast is for accessing private data stored globally + let testInfo = (globalThis as any)['__OWNER_MAP__']?.get(guid); + + throw new Error( + `Cannot call \`.lookup('${fullName}')\` after the owner has been destroyed. ` + + `owner is ${guid} (test ${testInfo?.testId} ${testInfo?.name})` + ); + } else { + throw new Error( + `Cannot call \`.lookup('${fullName}')\` after the owner has been destroyed` + ); + } } assert('fullName must be a proper full name', this.registry.isValidFullName(fullName)); return lookup(this, this.registry.normalize(fullName), options); diff --git a/packages/@ember/-internals/metal/lib/property_set.ts b/packages/@ember/-internals/metal/lib/property_set.ts index 65b78f9c1ed..55e6f1958a2 100644 --- a/packages/@ember/-internals/metal/lib/property_set.ts +++ b/packages/@ember/-internals/metal/lib/property_set.ts @@ -1,4 +1,10 @@ -import { lookupDescriptor, setWithMandatorySetter, toString } from '@ember/-internals/utils'; +import { getOwner } from '@ember/-internals/owner'; +import { + guidFor, + lookupDescriptor, + setWithMandatorySetter, + toString, +} from '@ember/-internals/utils'; import { assert } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; import { COMPUTED_SETTERS } from './decorator'; @@ -55,10 +61,23 @@ export function set(obj: object, keyName: string, value: T, tolerant?: boolea ); if ((obj as ExtendedObject).isDestroyed) { - assert( - `calling set on destroyed object: ${toString(obj)}.${keyName} = ${toString(value)}`, - tolerant - ); + if (macroCondition(isTesting())) { + let guid = guidFor(getOwner(obj)); + + // SAFETY: cast is for accessing private data stored globally + let testInfo = (globalThis as any)['__OWNER_MAP__']?.get(guid); + assert( + `calling set on destroyed object: ${toString(obj)}.${keyName} = ${toString(value)} ` + + `owner is ${guid} (test ${testInfo?.testId} ${testInfo?.name})`, + tolerant + ); + } else { + assert( + `calling set on destroyed object: ${toString(obj)}.${keyName} = ${toString(value)}`, + tolerant + ); + } + return value; }