Skip to content
This repository has been archived by the owner on Dec 27, 2024. It is now read-only.

@Injectable can throw cannot read property of undefined error #122

Closed
3 tasks done
etsuo opened this issue Jan 18, 2018 · 0 comments
Closed
3 tasks done

@Injectable can throw cannot read property of undefined error #122

etsuo opened this issue Jan 18, 2018 · 0 comments

Comments

@etsuo
Copy link
Member

etsuo commented Jan 18, 2018

Injectable code:

export function getDependencyInjections(target: any, t: any, sapi: SakuraApi) {
  const expectedDiArgs = Reflect.getMetadata('design:paramtypes', t);

  const diArgs = [];

  for (const arg of expectedDiArgs || []) {
    debug(`injecting ${arg.name} into ${target.name}`);

    const isInjectable = !!arg[injectableSymbols.isSakuraApiInjectable];
    if (typeof arg !== 'function' || !isInjectable) {
      throw new NonInjectableConstructorParameterError(arg, target);
    }

    debug('\t getting provider from sapi');
    diArgs.push(sapi.getProvider(arg));
  }

  return diArgs;
}
  • debug should not assume arg is instantiated (debugs should never throw errors in code).
  • If arg is undefined, it should throw NonInjectableConstructorParameterError (see [1] below). -- It is likely this is because of a circular dependency -- notify the integrator this might be the case
  • NonInjectableConstructorParameterError needs to be updated so that it returns the raw target if it's falsy so that the error message is properly rendered as: Error: Unable to inject undefined into SomeService. Only classes decorated with '@Injectable' can be passed into the SalesforceService constructor. -- right now it's reporting Object when it's undefined, which obfuscates what's actually happening. See [2] below:

[1] (transpiled output)

function getDependencyInjections(target, t, sapi) {
  const expectedDiArgs = Reflect.getMetadata('design:paramtypes', t);
  const diArgs = [];

  for (const arg of expectedDiArgs || []) {
    if (!arg) {
      throw new NonInjectableConstructorParameterError(arg, target);
    }

    debug(`injecting ${arg.name} into ${target.name}`);
    const isInjectable = !!arg[exports.injectableSymbols.isSakuraApiInjectable];
    if (typeof arg !== 'function' || !isInjectable) {
      throw new NonInjectableConstructorParameterError(arg, target);
    }
    debug('\t getting provider from sapi');
    diArgs.push(sapi.getProvider(arg));
  }
  return diArgs;
}

[2] (transpiled output)

class NonInjectableConstructorParameterError extends Error {

  constructor(target, source) {

    const targetName = (!target) ? target : (target || {}).name
      || ((target || {}).constructor || {}).name
      || typeof target;
    const sourceName = (source || {}).name
      || ((source || {}).constructor || {}).name
      || typeof source;
    const message = `Unable to inject ${targetName} into ${sourceName}. Only classes decorated with '@Injectable' can`
      + ` be passed into the ${sourceName} constructor.`;
    super(message);
  }
}
@etsuo etsuo added the bug label Jan 18, 2018
@etsuo etsuo added this to the 0.9.0 milestone Jan 18, 2018
@etsuo etsuo self-assigned this Jan 18, 2018
@etsuo etsuo removed their assignment Jan 18, 2018
@etsuo etsuo self-assigned this Jan 27, 2018
@etsuo etsuo closed this as completed in 4678348 Jan 27, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant