Skip to content

Commit

Permalink
feat(dev): better DI error messages for instantiation (#1917)
Browse files Browse the repository at this point in the history
[skip ci]
  • Loading branch information
bigopon committed Mar 3, 2024
1 parent 32f00ed commit 2fca6ea
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 8 deletions.
3 changes: 2 additions & 1 deletion packages-tooling/rollup-utils.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ export function getRollupConfig(pkg, configure = identity, configureTerser, post
input: inputFile,
external: Object.keys(pkg.dependencies ?? {})
.concat(Object.keys(pkg.devDependencies ?? {}))
.concat('os', 'path', 'fs', 'http', 'https', 'http2', 'url', 'stream'),
.concat('os', 'path', 'fs', 'http', 'https', 'http2', 'url', 'stream')
.concat('node:module', 'node:path'),
output: [
{
file: esmDist,
Expand Down
5 changes: 4 additions & 1 deletion packages-tooling/vite-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { IOptionalPreprocessOptions, preprocess } from '@aurelia/plugin-conventi
import { createFilter, FilterPattern } from '@rollup/pluginutils';
import { resolve, dirname } from 'path';
import { promises } from 'fs';
import { createRequire } from 'module';

const require = createRequire(import.meta.url);

export default function au(options: {
include?: FilterPattern;
Expand All @@ -25,7 +28,7 @@ export default function au(options: {
const devPlugin: import('vite').Plugin = {
name: 'aurelia:dev-alias',
config(config) {
const isDev = useDev || (!useDev && config.mode !== 'production');
const isDev = useDev === true || (useDev == null && config.mode !== 'production');
if (!isDev) {
return;
}
Expand Down
1 change: 1 addition & 0 deletions packages-tooling/vite-plugin/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": "../tsconfig-build.json",
"compilerOptions": {
"module": "esnext",
"rootDir": "src",
"declarationDir": "dist/types",
"outDir": "dist/cjs",
Expand Down
4 changes: 4 additions & 0 deletions packages/__tests__/src/1-kernel/di.invoke.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ describe('1-kernel/di.invoke.spec.ts', function () {
assert.strictEqual(v1, 2);
});

it('throws when invoking intrinsic types', function () {
assert.throws(() => container.invoke(String));
});

describe('inheritance', function () {
it('works with a list of keys', function () {
let i = 0;
Expand Down
81 changes: 77 additions & 4 deletions packages/kernel/src/di.container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
type IAllResolver,
type IOptionalResolver,
} from './di';
import { ErrorNames, createMappedError } from './errors';
import { ErrorNames, createMappedError, logError } from './errors';

const InstrinsicTypeNames = new Set<string>('Array ArrayBuffer Boolean DataView Date Error EvalError Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Number Object Promise RangeError ReferenceError RegExp Set SharedArrayBuffer String SyntaxError TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array URIError WeakMap WeakSet'.split(' '));
// const factoryKey = 'di:factory';
Expand Down Expand Up @@ -365,12 +365,35 @@ export class Container implements IContainer {
}

public invoke<T extends {}, TDeps extends unknown[] = unknown[]>(Type: Constructable<T>, dynamicDependencies?: TDeps): T {
if (isNativeFunction(Type)) {
throw createMappedError(ErrorNames.no_construct_native_fn, Type);
}
const previousContainer = currentContainer;
currentContainer = this;
try {
if (isNativeFunction(Type)) {
throw createMappedError(ErrorNames.no_construct_native_fn, Type);
if (__DEV__) {
let resolvedDeps: unknown[];
let dep: Key | undefined;

try {
resolvedDeps = getDependencies(Type).map(_ => this.get(dep = _));
} catch (ex) {
logError(`[DEV:aurelia] Error during construction of ${Type.name}, caused by dependency: ${String(dep)}`);
currentContainer = previousContainer;
throw ex;
}

try {
return dynamicDependencies === void 0
? new Type(...resolvedDeps)
: new Type(...resolvedDeps, ...dynamicDependencies);
} catch (ex) {
logError(`[DEV:aurelia] Error during construction of ${Type.name}`);
throw ex;
} finally {
currentContainer = previousContainer;
}
}
try {
return dynamicDependencies === void 0
? new Type(...getDependencies(Type).map(containerGetKey, this))
: new Type(...getDependencies(Type).map(containerGetKey, this), ...dynamicDependencies);
Expand Down Expand Up @@ -512,6 +535,37 @@ class Factory<T extends Constructable = any> implements IFactory<T> {
const previousContainer = currentContainer;
currentContainer = container;
let instance: Resolved<T>;
/* istanbul ignore next */
if (__DEV__) {
let resolvedDeps: unknown[];
let dep: Key | undefined;
try {
resolvedDeps = this.dependencies.map(_ => container.get(dep = _));
} catch (ex) {
logError(`[DEV:aurelia] Error during construction of ${this.Type.name}, caused by dependency: ${String(dep)}`);
currentContainer = previousContainer;
throw ex;
}

try {
if (dynamicDependencies === void 0) {
instance = new this.Type(...resolvedDeps) as Resolved<T>;
} else {
instance = new this.Type(...resolvedDeps, ...dynamicDependencies) as Resolved<T>;
}

if (this.transformers == null) {
return instance;
}

return this.transformers.reduce(transformInstance, instance);
} catch (ex) {
logError(`[DEV:aurelia] Error during construction of ${this.Type.name}`);
throw ex;
} finally {
currentContainer = previousContainer;
}
}
try {
if (dynamicDependencies === void 0) {
instance = new this.Type(...this.dependencies.map(containerGetKey, container)) as Resolved<T>;
Expand Down Expand Up @@ -578,6 +632,25 @@ export function resolve<K extends Key, A extends K[]>(...keys: A): Resolved<K> |
if (currentContainer == null) {
throw createMappedError(ErrorNames.no_active_container_for_resolve, ...keys);
}
/* istanbul ignore next */
if (__DEV__) {
if (keys.length === 1) {
try {
return currentContainer.get(keys[0]);
} catch (ex) {
logError(`[DEV:aurelia] resolve() call error for: ${String(keys[0])}`);
throw ex;
}
} else {
let key: Key | undefined;
try {
return keys.map(_ => currentContainer!.get(key = _));
} catch (ex) {
logError(`[DEV:aurelia] resolve() call error for: ${String(key)}`);
throw ex;
}
}
}
return keys.length === 1
? currentContainer.get(keys[0])
: keys.map(containerGetKey, currentContainer);
Expand Down
4 changes: 4 additions & 0 deletions packages/kernel/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,7 @@ function pleaseHelpCreateAnIssue(title: string, body?: string) {
+ `https://github.com/aurelia/aurelia/issues/new?title=${encodeURIComponent(title)}`
+ (body != null ? `&body=${encodeURIComponent(body)}` : '&template=bug_report.md');
}

/** @internal */
// eslint-disable-next-line
export const logError = (...args: unknown[]) => (globalThis as any).console.error(...args);
3 changes: 1 addition & 2 deletions packages/kernel/src/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,8 @@ export const isNativeFunction = /*@__PURE__*/(function () {
charCodeAt(sourceText, i - 12) === 0x74 && // t
charCodeAt(sourceText, i - 13) === 0x61 && // a
charCodeAt(sourceText, i - 14) === 0x6E && // n
charCodeAt(sourceText, i - 15) === 0x58 // [
charCodeAt(sourceText, i - 15) === 0x5B // [
);

lookup.set(fn, isNative);
}
return isNative;
Expand Down

0 comments on commit 2fca6ea

Please sign in to comment.