From ba5ace4ba6baf564a4784813e422e268c9651446 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Tue, 7 Aug 2018 10:51:49 -0700 Subject: [PATCH] fix(context): check constructor/method override for @inject https://github.com/strongloop/loopback-next/issues/1565 --- packages/context/src/inject.ts | 14 ++++++++++++++ packages/context/test/unit/inject.unit.ts | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/packages/context/src/inject.ts b/packages/context/src/inject.ts index 5122504772e7..ed7ecc02374d 100644 --- a/packages/context/src/inject.ts +++ b/packages/context/src/inject.ts @@ -10,6 +10,7 @@ import { PropertyDecoratorFactory, MetadataMap, MetadataAccessor, + InspectionOptions, } from '@loopback/metadata'; import {BoundValue, ValueOrPromise, resolveList} from './value-promise'; import {Context} from './context'; @@ -299,10 +300,23 @@ export function describeInjectedArguments( method?: string, ): Readonly[] { method = method || ''; + const options: InspectionOptions = {}; + if (method === '') { + // A hacky way to check if an explicit constructor exists + // See https://github.com/strongloop/loopback-next/issues/1565 + if (target.toString().match(/\s+constructor\s*\([^\)]*\)\s+\{/m)) { + options.ownMetadataOnly = true; + } + } else if (target.hasOwnProperty(method)) { + // The method exists in the target, no injections on the super method + // should be honored + options.ownMetadataOnly = true; + } const meta = MetadataInspector.getAllParameterMetadata>( PARAMETERS_KEY, target, method, + options, ); return meta || []; } diff --git a/packages/context/test/unit/inject.unit.ts b/packages/context/test/unit/inject.unit.ts index 2a149a098230..acbd71151afd 100644 --- a/packages/context/test/unit/inject.unit.ts +++ b/packages/context/test/unit/inject.unit.ts @@ -79,6 +79,20 @@ describe('function argument injection', () => { const meta = describeInjectedArguments(SubTestClass); expect(meta.map(m => m.bindingKey)).to.deepEqual(['bar']); }); + + it('supports inheritance with overriding constructor - no args', () => { + class TestClass { + constructor(@inject('foo') foo: string) {} + } + + class SubTestClass extends TestClass { + constructor() { + super('foo'); + } + } + const meta = describeInjectedArguments(SubTestClass); + expect(meta.map(m => m.bindingKey)).to.deepEqual([]); + }); }); describe('property injection', () => {