static-injector 1.0.9 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/import/commonjs/index.js +331 -118
  2. package/import/es2015/di/create_injector.js +30 -0
  3. package/import/es2015/di/initializer_token.js +15 -0
  4. package/import/es2015/di/inject_switch.js +27 -6
  5. package/import/es2015/{decorator → di}/injectable.js +0 -0
  6. package/import/es2015/di/injection_token.js +6 -0
  7. package/import/es2015/di/injector.js +6 -8
  8. package/import/es2015/di/injector_compatibility.js +90 -34
  9. package/import/es2015/di/injector_token.js +1 -1
  10. package/import/es2015/di/interface/defs.js +39 -0
  11. package/import/es2015/di/interface/injector.js +1 -0
  12. package/import/es2015/di/internal_tokens.js +9 -0
  13. package/import/es2015/di/metadata.js +4 -4
  14. package/import/es2015/di/provider_collection.js +49 -0
  15. package/import/es2015/di/r3_injector.js +96 -66
  16. package/import/es2015/di/scope.js +2 -2
  17. package/import/es2015/index.js +1 -1
  18. package/import/es2015/render3/errors_di.js +1 -1
  19. package/import/fesm2015/index.js +322 -108
  20. package/import/typings/di/create_injector.d.ts +23 -0
  21. package/import/typings/di/initializer_token.d.ts +15 -0
  22. package/import/typings/di/inject_switch.d.ts +7 -2
  23. package/import/typings/{decorator → di}/injectable.d.ts +1 -1
  24. package/import/typings/di/injection_token.d.ts +4 -0
  25. package/import/typings/di/injector.d.ts +20 -7
  26. package/import/typings/di/injector_compatibility.d.ts +42 -21
  27. package/import/typings/di/interface/defs.d.ts +10 -0
  28. package/import/typings/di/interface/injector.d.ts +26 -0
  29. package/import/typings/di/interface/provider.d.ts +1 -6
  30. package/import/typings/di/internal_tokens.d.ts +10 -0
  31. package/import/typings/di/provider_collection.d.ts +30 -0
  32. package/import/typings/di/r3_injector.d.ts +67 -36
  33. package/import/typings/di/scope.d.ts +3 -2
  34. package/import/typings/index.d.ts +1 -1
  35. package/package.json +4 -2
  36. package/transform/compiler/index.js +5 -1
  37. package/transform/compiler/src/injectable_compiler_2.d.ts +7 -36
  38. package/transform/compiler/src/injectable_compiler_2.js +20 -23
  39. package/transform/compiler/src/output/output_ast.d.ts +29 -108
  40. package/transform/compiler/src/output/output_ast.js +66 -188
  41. package/transform/compiler/src/render3/r3_factory.js +11 -7
  42. package/transform/compiler/src/render3/util.d.ts +64 -0
  43. package/transform/compiler/src/render3/util.js +52 -9
  44. package/transform/compiler/src/render3/view/util.js +5 -1
  45. package/transform/compiler-cli/src/ngtsc/annotations/{src → common/src}/util.d.ts +5 -4
  46. package/transform/compiler-cli/src/ngtsc/annotations/{src → common/src}/util.js +32 -23
  47. package/transform/compiler-cli/src/ngtsc/annotations/src/factory.js +1 -1
  48. package/transform/compiler-cli/src/ngtsc/annotations/src/injectable.js +33 -21
  49. package/transform/compiler-cli/src/ngtsc/diagnostics/error.js +6 -2
  50. package/transform/compiler-cli/src/ngtsc/diagnostics/index.js +5 -1
  51. package/transform/compiler-cli/src/ngtsc/imports/index.js +5 -1
  52. package/transform/compiler-cli/src/ngtsc/reflection/index.js +5 -1
  53. package/transform/compiler-cli/src/ngtsc/reflection/src/host.d.ts +1 -1
  54. package/transform/compiler-cli/src/ngtsc/reflection/src/host.js +6 -2
  55. package/transform/compiler-cli/src/ngtsc/reflection/src/type_to_value.d.ts +2 -2
  56. package/transform/compiler-cli/src/ngtsc/reflection/src/type_to_value.js +36 -23
  57. package/transform/compiler-cli/src/ngtsc/reflection/src/typescript.js +18 -13
  58. package/transform/compiler-cli/src/ngtsc/reflection/src/util.js +5 -1
  59. package/transform/compiler-cli/src/ngtsc/transform/index.js +5 -1
  60. package/transform/compiler-cli/src/ngtsc/transform/src/utils.d.ts +2 -2
  61. package/transform/compiler-cli/src/ngtsc/transform/src/utils.js +13 -8
  62. package/transform/compiler-cli/src/ngtsc/translator/index.js +5 -1
  63. package/transform/compiler-cli/src/ngtsc/translator/src/import_manager.d.ts +3 -3
  64. package/transform/compiler-cli/src/ngtsc/translator/src/import_manager.js +7 -3
  65. package/transform/compiler-cli/src/ngtsc/translator/src/translator.d.ts +0 -4
  66. package/transform/compiler-cli/src/ngtsc/translator/src/translator.js +5 -17
  67. package/transform/compiler-cli/src/ngtsc/translator/src/typescript_ast_factory.d.ts +3 -6
  68. package/transform/compiler-cli/src/ngtsc/translator/src/typescript_ast_factory.js +67 -55
  69. package/{import/es2015/decorator/interface/provider.js → transform/compiler-cli/src/ngtsc/ts_compatibility/index.d.ts} +1 -1
  70. package/transform/compiler-cli/src/ngtsc/ts_compatibility/index.js +24 -0
  71. package/transform/compiler-cli/src/ngtsc/ts_compatibility/src/ts_cross_version_utils.d.ts +151 -0
  72. package/transform/compiler-cli/src/ngtsc/ts_compatibility/src/ts_cross_version_utils.js +210 -0
  73. package/transform/compiler-cli/src/ngtsc/util/src/typescript.js +5 -1
  74. package/transform/index.js +5 -1
  75. package/transform/injectable-transform.js +33 -38
  76. package/import/typings/decorator/interface/provider.d.ts +0 -312
  77. package/transform/compiler/src/render3/partial/util.d.ts +0 -16
  78. package/transform/compiler/src/render3/partial/util.js +0 -44
@@ -240,7 +240,7 @@ function stringifyForError(value) {
240
240
  /** Throws an error when a token is not found in DI. */
241
241
  function throwProviderNotFoundError(token, injectorName) {
242
242
  const injectorDetails = injectorName ? ` in ${injectorName}` : '';
243
- throw new RuntimeError("201" /* PROVIDER_NOT_FOUND */, `No provider for ${stringifyForError(token)} found${injectorDetails}`);
243
+ throw new RuntimeError("201" /* RuntimeErrorCode.PROVIDER_NOT_FOUND */, `No provider for ${stringifyForError(token)} found${injectorDetails}`);
244
244
  }
245
245
 
246
246
  /**
@@ -314,6 +314,45 @@ function getOwnDefinition(type, field) {
314
314
  const NG_PROV_DEF = getClosureSafeProperty({
315
315
  ɵprov: getClosureSafeProperty,
316
316
  });
317
+ /**
318
+ * Read the injectable def (`ɵprov`) for `type` or read the `ɵprov` from one of its ancestors.
319
+ *
320
+ * @param type A type which may have `ɵprov`, via inheritance.
321
+ *
322
+ * @deprecated Will be removed in a future version of Angular, where an error will occur in the
323
+ * scenario if we find the `ɵprov` on an ancestor only.
324
+ */
325
+ function getInheritedInjectableDef(type) {
326
+ const def = type && (type[NG_PROV_DEF] || type[NG_INJECTABLE_DEF]);
327
+ if (def) {
328
+ const typeName = getTypeName(type);
329
+ // TODO(FW-1307): Re-add ngDevMode when closure can handle it
330
+ // ngDevMode &&
331
+ console.warn(`DEPRECATED: DI is instantiating a token "${typeName}" that inherits its @Injectable decorator but does not provide one itself.\n` +
332
+ `This will become an error in a future version of Angular. Please add @Injectable() to the "${typeName}" class.`);
333
+ return def;
334
+ }
335
+ else {
336
+ return null;
337
+ }
338
+ }
339
+ const NG_INJECTABLE_DEF = getClosureSafeProperty({
340
+ ngInjectableDef: getClosureSafeProperty,
341
+ });
342
+ /** Gets the name of a type, accounting for some cross-browser differences. */
343
+ function getTypeName(type) {
344
+ // `Function.prototype.name` behaves differently between IE and other browsers. In most browsers
345
+ // it'll always return the name of the function itself, no matter how many other functions it
346
+ // inherits from. On IE the function doesn't have its own `name` property, but it takes it from
347
+ // the lowest level in the prototype chain. E.g. if we have `class Foo extends Parent` most
348
+ // browsers will evaluate `Foo.name` to `Foo` while IE will return `Parent`. We work around
349
+ // the issue by converting the function to a string and parsing its name out that way via a regex.
350
+ if (type.hasOwnProperty('name')) {
351
+ return type.name;
352
+ }
353
+ const match = ('' + type).match(/^function\s*([^\s(]+)/);
354
+ return match === null ? '' : match[1];
355
+ }
317
356
 
318
357
  /**
319
358
  * @license
@@ -326,6 +365,7 @@ const NG_PROV_DEF = getClosureSafeProperty({
326
365
  * Injection flags for DI.
327
366
  *
328
367
  * @publicApi
368
+ * @deprecated use an options object for `inject` instead.
329
369
  */
330
370
  var InjectFlags;
331
371
  (function (InjectFlags) {
@@ -348,6 +388,27 @@ var InjectFlags;
348
388
  * Use of this source code is governed by an MIT-style license that can be
349
389
  * found in the LICENSE file at https://angular.io/license
350
390
  */
391
+ /**
392
+ * Current implementation of inject.
393
+ *
394
+ * By default, it is `injectInjectorOnly`, which makes it `Injector`-only aware. It can be changed
395
+ * to `directiveInject`, which brings in the `NodeInjector` system of ivy. It is designed this
396
+ * way for two reasons:
397
+ * 1. `Injector` should not depend on ivy logic.
398
+ * 2. To maintain tree shake-ability we don't want to bring in unnecessary code.
399
+ */
400
+ let _injectImplementation;
401
+ function getInjectImplementation() {
402
+ return _injectImplementation;
403
+ }
404
+ /**
405
+ * Sets the current inject implementation.
406
+ */
407
+ function setInjectImplementation(impl) {
408
+ const previous = _injectImplementation;
409
+ _injectImplementation = impl;
410
+ return previous;
411
+ }
351
412
  /**
352
413
  * Injects `root` tokens in limp mode.
353
414
  *
@@ -357,7 +418,7 @@ var InjectFlags;
357
418
  */
358
419
  function injectRootLimpMode(token, notFoundValue, flags) {
359
420
  const injectableDef = getInjectableDef(token);
360
- if (injectableDef && injectableDef.providedIn == "root") {
421
+ if (injectableDef && injectableDef.providedIn == 'root') {
361
422
  return injectableDef.value === undefined
362
423
  ? (injectableDef.value = injectableDef.factory())
363
424
  : injectableDef.value;
@@ -366,7 +427,7 @@ function injectRootLimpMode(token, notFoundValue, flags) {
366
427
  return null;
367
428
  if (notFoundValue !== undefined)
368
429
  return notFoundValue;
369
- throwProviderNotFoundError(stringify(token), "Injector");
430
+ throwProviderNotFoundError(stringify(token), 'Injector');
370
431
  }
371
432
 
372
433
  /**
@@ -383,12 +444,12 @@ const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
383
444
  * InjectFlag this decorator represents. This allows to avoid direct references to the DI decorators
384
445
  * in the code, thus making them tree-shakable.
385
446
  */
386
- const DI_DECORATOR_FLAG = "__NG_DI_FLAG__";
387
- const NG_TEMP_TOKEN_PATH = "ngTempTokenPath";
388
- const NG_TOKEN_PATH = "ngTokenPath";
447
+ const DI_DECORATOR_FLAG = '__NG_DI_FLAG__';
448
+ const NG_TEMP_TOKEN_PATH = 'ngTempTokenPath';
449
+ const NG_TOKEN_PATH = 'ngTokenPath';
389
450
  const NEW_LINE = /\n/gm;
390
- const NO_NEW_LINE = "ɵ";
391
- const SOURCE = "__source";
451
+ const NO_NEW_LINE = 'ɵ';
452
+ const SOURCE = '__source';
392
453
  const USE_VALUE = getClosureSafeProperty({
393
454
  provide: String,
394
455
  useValue: getClosureSafeProperty,
@@ -421,45 +482,101 @@ function ɵɵinject(token, flags = InjectFlags.Default) {
421
482
  }
422
483
  /**
423
484
  * Injects a token from the currently active injector.
424
- *
425
- * Must be used in the context of a factory function such as one defined for an
426
- * `InjectionToken`. Throws an error if not called from such a context.
427
- *
428
- * Within such a factory function, using this function to request injection of a dependency
429
- * is faster and more type-safe than providing an additional array of dependencies
430
- * (as has been common with `useFactory` providers).
431
- *
432
- * @param token The injection token for the dependency to be injected.
485
+ * `inject` is only supported during instantiation of a dependency by the DI system. It can be used
486
+ * during:
487
+ * - Construction (via the `constructor`) of a class being instantiated by the DI system, such
488
+ * as an `@Injectable` or `@Component`.
489
+ * - In the initializer for fields of such classes.
490
+ * - In the factory function specified for `useFactory` of a `Provider` or an `@Injectable`.
491
+ * - In the `factory` function specified for an `InjectionToken`.
492
+ *
493
+ * @param token A token that represents a dependency that should be injected.
433
494
  * @param flags Optional flags that control how injection is executed.
434
495
  * The flags correspond to injection strategies that can be specified with
435
496
  * parameter decorators `@Host`, `@Self`, `@SkipSef`, and `@Optional`.
436
- * @returns the injected value if injection is successful, `null` otherwise.
497
+ * @returns the injected value if operation is successful, `null` otherwise.
498
+ * @throws if called outside of a supported context.
437
499
  *
438
500
  * @usageNotes
501
+ * In practice the `inject()` calls are allowed in a constructor, a constructor parameter and a
502
+ * field initializer:
503
+ *
504
+ * ```typescript
505
+ * @Injectable({providedIn: 'root'})
506
+ * export class Car {
507
+ * radio: Radio|undefined;
508
+ * // OK: field initializer
509
+ * spareTyre = inject(Tyre);
510
+ *
511
+ * constructor() {
512
+ * // OK: constructor body
513
+ * this.radio = inject(Radio);
514
+ * }
515
+ * }
516
+ * ```
439
517
  *
440
- * ### Example
518
+ * It is also legal to call `inject` from a provider's factory:
441
519
  *
442
- * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
520
+ * ```typescript
521
+ * providers: [
522
+ * {provide: Car, useFactory: () => {
523
+ * // OK: a class factory
524
+ * const engine = inject(Engine);
525
+ * return new Car(engine);
526
+ * }}
527
+ * ]
528
+ * ```
529
+ *
530
+ * Calls to the `inject()` function outside of the class creation context will result in error. Most
531
+ * notably, calls to `inject()` are disallowed after a class instance was created, in methods
532
+ * (including lifecycle hooks):
533
+ *
534
+ * ```typescript
535
+ * @Component({ ... })
536
+ * export class CarComponent {
537
+ * ngOnInit() {
538
+ * // ERROR: too late, the component instance was already created
539
+ * const engine = inject(Engine);
540
+ * engine.start();
541
+ * }
542
+ * }
543
+ * ```
443
544
  *
444
545
  * @publicApi
445
546
  */
446
- const inject = ɵɵinject;
547
+ function inject(token, flags = InjectFlags.Default) {
548
+ return ɵɵinject(token, convertToBitFlags(flags));
549
+ }
550
+ // Converts object-based DI flags (`InjectOptions`) to bit flags (`InjectFlags`).
551
+ function convertToBitFlags(flags) {
552
+ if (typeof flags === 'undefined' || typeof flags === 'number') {
553
+ return flags;
554
+ }
555
+ // While TypeScript doesn't accept it without a cast, bitwise OR with false-y values in
556
+ // JavaScript is a no-op. We can use that for a very codesize-efficient conversion from
557
+ // `InjectOptions` to `InjectFlags`.
558
+ return (0 /* InternalInjectFlags.Default */ | // comment to force a line break in the formatter
559
+ (flags.optional && 8 /* InternalInjectFlags.Optional */) |
560
+ (flags.self && 2 /* InternalInjectFlags.Self */) |
561
+ (flags.skipSelf &&
562
+ 4 /* InternalInjectFlags.SkipSelf */));
563
+ }
447
564
  function injectArgs(types) {
448
565
  const args = [];
449
566
  for (let i = 0; i < types.length; i++) {
450
567
  const arg = resolveForwardRef(types[i]);
451
568
  if (Array.isArray(arg)) {
452
569
  if (arg.length === 0) {
453
- throw new Error("Arguments array must have arguments.");
570
+ throw new Error('Arguments array must have arguments.');
454
571
  }
455
572
  let type = undefined;
456
573
  let flags = InjectFlags.Default;
457
574
  for (let j = 0; j < arg.length; j++) {
458
575
  const meta = arg[j];
459
576
  const flag = getInjectFlag(meta);
460
- if (typeof flag === "number") {
577
+ if (typeof flag === 'number') {
461
578
  // Special case when we handle @Inject decorator.
462
- if (flag === -1 /* Inject */) {
579
+ if (flag === -1 /* DecoratorFlags.Inject */) {
463
580
  type = meta.token;
464
581
  }
465
582
  else {
@@ -506,35 +623,35 @@ function catchInjectorError(e, token, injectorErrorName, source) {
506
623
  if (token[SOURCE]) {
507
624
  tokenPath.unshift(token[SOURCE]);
508
625
  }
509
- e.message = formatError("\n" + e.message, tokenPath, injectorErrorName, source);
626
+ e.message = formatError('\n' + e.message, tokenPath, injectorErrorName, source);
510
627
  e[NG_TOKEN_PATH] = tokenPath;
511
628
  e[NG_TEMP_TOKEN_PATH] = null;
512
629
  throw e;
513
630
  }
514
631
  function formatError(text, obj, injectorErrorName, source = null) {
515
632
  text =
516
- text && text.charAt(0) === "\n" && text.charAt(1) == NO_NEW_LINE
517
- ? text.substr(2)
633
+ text && text.charAt(0) === '\n' && text.charAt(1) == NO_NEW_LINE
634
+ ? text.slice(2)
518
635
  : text;
519
636
  let context = stringify(obj);
520
637
  if (Array.isArray(obj)) {
521
- context = obj.map(stringify).join(" -> ");
638
+ context = obj.map(stringify).join(' -> ');
522
639
  }
523
- else if (typeof obj === "object") {
640
+ else if (typeof obj === 'object') {
524
641
  let parts = [];
525
642
  for (let key in obj) {
526
643
  if (obj.hasOwnProperty(key)) {
527
644
  let value = obj[key];
528
645
  parts.push(key +
529
- ":" +
530
- (typeof value === "string"
646
+ ':' +
647
+ (typeof value === 'string'
531
648
  ? JSON.stringify(value)
532
649
  : stringify(value)));
533
650
  }
534
651
  }
535
- context = `{${parts.join(", ")}}`;
652
+ context = `{${parts.join(', ')}}`;
536
653
  }
537
- return `${injectorErrorName}${source ? "(" + source + ")" : ""}[${context}]: ${text.replace(NEW_LINE, "\n ")}`;
654
+ return `${injectorErrorName}${source ? '(' + source + ')' : ''}[${context}]: ${text.replace(NEW_LINE, '\n ')}`;
538
655
  }
539
656
 
540
657
  /**
@@ -553,7 +670,7 @@ function formatError(text, obj, injectorErrorName, source = null) {
553
670
  const Inject = attachInjectFlag(
554
671
  // Disable tslint because `DecoratorFlags` is a const enum which gets inlined.
555
672
  // tslint:disable-next-line: no-toplevel-property-access
556
- makeParamDecorator('Inject', (token) => ({ token })), -1 /* Inject */);
673
+ makeParamDecorator('Inject', (token) => ({ token })), -1 /* DecoratorFlags.Inject */);
557
674
  /**
558
675
  * Optional decorator and metadata.
559
676
  *
@@ -563,7 +680,7 @@ makeParamDecorator('Inject', (token) => ({ token })), -1 /* Inject */);
563
680
  const Optional =
564
681
  // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
565
682
  // tslint:disable-next-line: no-toplevel-property-access
566
- attachInjectFlag(makeParamDecorator('Optional'), 8 /* Optional */);
683
+ attachInjectFlag(makeParamDecorator('Optional'), 8 /* InternalInjectFlags.Optional */);
567
684
  /**
568
685
  * Self decorator and metadata.
569
686
  *
@@ -573,7 +690,7 @@ attachInjectFlag(makeParamDecorator('Optional'), 8 /* Optional */);
573
690
  const Self =
574
691
  // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
575
692
  // tslint:disable-next-line: no-toplevel-property-access
576
- attachInjectFlag(makeParamDecorator('Self'), 2 /* Self */);
693
+ attachInjectFlag(makeParamDecorator('Self'), 2 /* InternalInjectFlags.Self */);
577
694
  /**
578
695
  * `SkipSelf` decorator and metadata.
579
696
  *
@@ -583,7 +700,7 @@ attachInjectFlag(makeParamDecorator('Self'), 2 /* Self */);
583
700
  const SkipSelf =
584
701
  // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
585
702
  // tslint:disable-next-line: no-toplevel-property-access
586
- attachInjectFlag(makeParamDecorator('SkipSelf'), 4 /* SkipSelf */);
703
+ attachInjectFlag(makeParamDecorator('SkipSelf'), 4 /* InternalInjectFlags.SkipSelf */);
587
704
 
588
705
  /**
589
706
  * @license
@@ -629,6 +746,21 @@ function newArray(size, value) {
629
746
  return list;
630
747
  }
631
748
 
749
+ /**
750
+ * @license
751
+ * Copyright Google LLC All Rights Reserved.
752
+ *
753
+ * Use of this source code is governed by an MIT-style license that can be
754
+ * found in the LICENSE file at https://angular.io/license
755
+ */
756
+ /**
757
+ * This file contains reuseable "empty" symbols that can be used as default return values
758
+ * in different parts of the rendering code. Because the same symbols are returned, this
759
+ * allows for identity checks against these values to be consistently used by the framework
760
+ * code.
761
+ */
762
+ const EMPTY_ARRAY = [];
763
+
632
764
  /**
633
765
  * @license
634
766
  * Copyright Google LLC All Rights Reserved.
@@ -695,11 +827,32 @@ class InjectionToken {
695
827
  });
696
828
  }
697
829
  }
830
+ /**
831
+ * @internal
832
+ */
833
+ get multi() {
834
+ return this;
835
+ }
698
836
  toString() {
699
837
  return `InjectionToken ${this._desc}`;
700
838
  }
701
839
  }
702
840
 
841
+ /**
842
+ * @license
843
+ * Copyright Google LLC All Rights Reserved.
844
+ *
845
+ * Use of this source code is governed by an MIT-style license that can be
846
+ * found in the LICENSE file at https://angular.io/license
847
+ */
848
+ /**
849
+ * A multi-provider token for initialization functions that will run upon construction of an
850
+ * environment injector.
851
+ *
852
+ * @publicApi
853
+ */
854
+ const ENVIRONMENT_INITIALIZER = new InjectionToken('ENVIRONMENT_INITIALIZER');
855
+
703
856
  /**
704
857
  * @license
705
858
  * Copyright Google LLC All Rights Reserved.
@@ -718,9 +871,18 @@ class InjectionToken {
718
871
  const INJECTOR = new InjectionToken("INJECTOR",
719
872
  // Dissable tslint because this is const enum which gets inlined not top level prop access.
720
873
  // tslint:disable-next-line: no-toplevel-property-access
721
- -1 /* Injector */ // Special value used by Ivy to identify `Injector`.
874
+ -1 /* InjectorMarkers.Injector */ // Special value used by Ivy to identify `Injector`.
722
875
  );
723
876
 
877
+ /**
878
+ * @license
879
+ * Copyright Google LLC All Rights Reserved.
880
+ *
881
+ * Use of this source code is governed by an MIT-style license that can be
882
+ * found in the LICENSE file at https://angular.io/license
883
+ */
884
+ const INJECTOR_DEF_TYPES = new InjectionToken('INJECTOR_DEF_TYPES');
885
+
724
886
  /**
725
887
  * @license
726
888
  * Copyright Google LLC All Rights Reserved.
@@ -751,7 +913,7 @@ class NullInjector {
751
913
  * as a root scoped injector when processing requests for unknown tokens which may indicate
752
914
  * they are provided in the root scope.
753
915
  */
754
- const INJECTOR_SCOPE = new InjectionToken("Set Injector scope.");
916
+ const INJECTOR_SCOPE = new InjectionToken('Set Injector scope.');
755
917
 
756
918
  /**
757
919
  * @license
@@ -783,54 +945,44 @@ function getNullInjector() {
783
945
  return NULL_INJECTOR;
784
946
  }
785
947
  /**
786
- * Create a new `Injector` which is configured using a `defType` of `InjectorType<any>`s.
787
- *
788
- * @publicApi
948
+ * An `Injector` that's part of the environment injector hierarchy, which exists outside of the
949
+ * component tree.
789
950
  */
790
- function createInjector(defType, parent = null, additionalProviders = null, name) {
791
- const injector = createInjectorWithoutInjectorInstances(defType, parent, additionalProviders, name);
792
- injector._resolveInjectorDefTypes();
793
- return injector;
794
- }
795
- /**
796
- * Creates a new injector without eagerly resolving its injector types. Can be used in places
797
- * where resolving the injector types immediately can lead to an infinite loop. The injector types
798
- * should be resolved at a later point by calling `_resolveInjectorDefTypes`.
799
- */
800
- function createInjectorWithoutInjectorInstances(defType, parent = null, additionalProviders = null, name) {
801
- return new R3Injector(defType, additionalProviders, parent || getNullInjector(), name);
951
+ class EnvironmentInjector {
802
952
  }
803
- class R3Injector {
804
- constructor(def, additionalProviders, parent, source = null) {
953
+ class R3Injector extends EnvironmentInjector {
954
+ constructor(providers, parent, source, scopes) {
955
+ super();
805
956
  this.parent = parent;
957
+ this.source = source;
958
+ this.scopes = scopes;
806
959
  /**
807
960
  * Map of tokens to records which contain the instances of those tokens.
808
961
  * - `null` value implies that we don't have the record. Used by tree-shakable injectors
809
962
  * to prevent further searches.
810
963
  */
811
964
  this.records = new Map();
812
- /**
813
- * The transitive set of `InjectorType`s which define this injector.
814
- */
815
- this.injectorDefTypes = new Set();
816
965
  /**
817
966
  * Set of values instantiated by this injector which contain `ngOnDestroy` lifecycle hooks.
818
967
  */
819
- this.onDestroy = new Set();
968
+ this._ngOnDestroyHooks = new Set();
969
+ this._onDestroyHooks = [];
820
970
  this._destroyed = false;
821
- // Start off by creating Records for every provider declared in every InjectorType
822
- // included transitively in additional providers then do the same for `def`. This order is
823
- // important because `def` may include providers that override ones in additionalProviders.
824
- additionalProviders &&
825
- deepForEach(additionalProviders, (provider) => this.processProvider(provider, def, additionalProviders));
971
+ // Start off by creating Records for every provider.
972
+ forEachSingleProvider(providers, (provider) => this.processProvider(provider));
826
973
  // Make sure the INJECTOR token provides this injector.
827
974
  this.records.set(INJECTOR, makeRecord(undefined, this));
975
+ // And `EnvironmentInjector` if the current injector is supposed to be env-scoped.
976
+ if (scopes.has('environment')) {
977
+ this.records.set(EnvironmentInjector, makeRecord(undefined, this));
978
+ }
828
979
  // Detect whether this injector has the APP_ROOT_SCOPE token and thus should provide
829
980
  // any injectable scoped to APP_ROOT_SCOPE.
830
981
  const record = this.records.get(INJECTOR_SCOPE);
831
- this.scope = record != null ? record.value : null;
832
- // Source name, used for debugging
833
- this.source = source || (typeof def === 'object' ? null : stringify(def));
982
+ if (record != null && typeof record.value === 'string') {
983
+ this.scopes.add(record.value);
984
+ }
985
+ this.injectorDefTypes = new Set(this.get(INJECTOR_DEF_TYPES.multi, EMPTY_ARRAY, InjectFlags.Self));
834
986
  }
835
987
  /**
836
988
  * Flag indicating that this injector was previously destroyed.
@@ -850,19 +1002,42 @@ class R3Injector {
850
1002
  this._destroyed = true;
851
1003
  try {
852
1004
  // Call all the lifecycle hooks.
853
- this.onDestroy.forEach((service) => service.ngOnDestroy());
1005
+ for (const service of this._ngOnDestroyHooks) {
1006
+ service.ngOnDestroy();
1007
+ }
1008
+ for (const hook of this._onDestroyHooks) {
1009
+ hook();
1010
+ }
854
1011
  }
855
1012
  finally {
856
1013
  // Release all references.
857
1014
  this.records.clear();
858
- this.onDestroy.clear();
1015
+ this._ngOnDestroyHooks.clear();
859
1016
  this.injectorDefTypes.clear();
1017
+ this._onDestroyHooks.length = 0;
1018
+ }
1019
+ }
1020
+ onDestroy(callback) {
1021
+ this._onDestroyHooks.push(callback);
1022
+ }
1023
+ runInContext(fn) {
1024
+ this.assertNotDestroyed();
1025
+ const previousInjector = setCurrentInjector(this);
1026
+ const previousInjectImplementation = setInjectImplementation(undefined);
1027
+ try {
1028
+ return fn();
1029
+ }
1030
+ finally {
1031
+ setCurrentInjector(previousInjector);
1032
+ setInjectImplementation(previousInjectImplementation);
860
1033
  }
861
1034
  }
862
1035
  get(token, notFoundValue = THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
863
1036
  this.assertNotDestroyed();
1037
+ flags = convertToBitFlags(flags);
864
1038
  // Set the injection context.
865
1039
  const previousInjector = setCurrentInjector(this);
1040
+ const previousInjectImplementation = setInjectImplementation(undefined);
866
1041
  try {
867
1042
  // Check for the SkipSelf flag.
868
1043
  if (!(flags & InjectFlags.SkipSelf)) {
@@ -920,16 +1095,31 @@ class R3Injector {
920
1095
  }
921
1096
  finally {
922
1097
  // Lastly, restore the previous injection context.
1098
+ setInjectImplementation(previousInjectImplementation);
923
1099
  setCurrentInjector(previousInjector);
924
1100
  }
925
1101
  }
926
1102
  /** @internal */
927
- _resolveInjectorDefTypes() {
928
- this.injectorDefTypes.forEach((defType) => this.get(defType));
1103
+ resolveInjectorInitializers() {
1104
+ const previousInjector = setCurrentInjector(this);
1105
+ const previousInjectImplementation = setInjectImplementation(undefined);
1106
+ try {
1107
+ const initializers = this.get(ENVIRONMENT_INITIALIZER.multi, EMPTY_ARRAY, InjectFlags.Self);
1108
+ for (const initializer of initializers) {
1109
+ initializer();
1110
+ }
1111
+ }
1112
+ finally {
1113
+ setCurrentInjector(previousInjector);
1114
+ setInjectImplementation(previousInjectImplementation);
1115
+ }
929
1116
  }
930
1117
  toString() {
931
- const tokens = [], records = this.records;
932
- records.forEach((v, token) => tokens.push(stringify(token)));
1118
+ const tokens = [];
1119
+ const records = this.records;
1120
+ for (const token of records.keys()) {
1121
+ tokens.push(stringify(token));
1122
+ }
933
1123
  return `R3Injector[${tokens.join(', ')}]`;
934
1124
  }
935
1125
  assertNotDestroyed() {
@@ -937,19 +1127,10 @@ class R3Injector {
937
1127
  throw new Error('Injector has already been destroyed.');
938
1128
  }
939
1129
  }
940
- /**
941
- * Add an `InjectorType` or `InjectorTypeWithProviders` and all of its transitive providers
942
- * to this injector.
943
- *
944
- * If an `InjectorTypeWithProviders` that declares providers besides the type is specified,
945
- * the function will return "true" to indicate that the providers of the type definition need
946
- * to be processed. This allows us to process providers of injector types after all imports of
947
- * an injector definition are processed. (following View Engine semantics: see FW-1349)
948
- */
949
1130
  /**
950
1131
  * Process a `SingleProvider` and add it.
951
1132
  */
952
- processProvider(provider, ngModuleType, providers) {
1133
+ processProvider(provider) {
953
1134
  // Determine the token from the provider. Either it's its own token, or has a {provide: ...}
954
1135
  // property.
955
1136
  provider = resolveForwardRef(provider);
@@ -957,16 +1138,13 @@ class R3Injector {
957
1138
  ? provider
958
1139
  : resolveForwardRef(provider && provider.provide);
959
1140
  // Construct a `Record` for the provider.
960
- const record = providerToRecord(provider, ngModuleType, providers);
1141
+ const record = providerToRecord(provider);
961
1142
  if (!isTypeProvider(provider) && provider.multi === true) {
962
1143
  // If the provider indicates that it's a multi-provider, process it specially.
963
1144
  // First check whether it's been defined already.
964
1145
  let multiRecord = this.records.get(token);
965
1146
  if (multiRecord) {
966
1147
  // It has. Throw a nice error if
967
- // if (ngDevMode && multiRecord.multi === undefined) {
968
- // throwMixedMultiProviderError();
969
- // }
970
1148
  }
971
1149
  else {
972
1150
  multiRecord = makeRecord(undefined, NOT_YET, true);
@@ -977,17 +1155,11 @@ class R3Injector {
977
1155
  multiRecord.multi.push(provider);
978
1156
  }
979
1157
  else {
980
- // const existing = this.records.get(token);
981
- // if (ngDevMode && existing && existing.multi !== undefined) {
982
- // throwMixedMultiProviderError();
983
- // }
1158
+ const existing = this.records.get(token);
984
1159
  }
985
1160
  this.records.set(token, record);
986
1161
  }
987
1162
  hydrate(token, record) {
988
- // if (ngDevMode && record.value === CIRCULAR) {
989
- // throwCyclicDependencyError(stringify(token));
990
- // } else
991
1163
  if (record.value === NOT_YET) {
992
1164
  record.value = CIRCULAR;
993
1165
  record.value = record.factory();
@@ -995,7 +1167,7 @@ class R3Injector {
995
1167
  if (typeof record.value === 'object' &&
996
1168
  record.value &&
997
1169
  hasOnDestroy(record.value)) {
998
- this.onDestroy.add(record.value);
1170
+ this._ngOnDestroyHooks.add(record.value);
999
1171
  }
1000
1172
  return record.value;
1001
1173
  }
@@ -1005,7 +1177,7 @@ class R3Injector {
1005
1177
  }
1006
1178
  const providedIn = resolveForwardRef(def.providedIn);
1007
1179
  if (typeof providedIn === 'string') {
1008
- return providedIn === 'any' || providedIn === this.scope;
1180
+ return providedIn === 'any' || this.scopes.has(providedIn);
1009
1181
  }
1010
1182
  else {
1011
1183
  return this.injectorDefTypes.has(providedIn);
@@ -1043,14 +1215,20 @@ function getUndecoratedInjectableFactory(token) {
1043
1215
  // def from an ancestor if there is one.
1044
1216
  // Otherwise this really is a simple class with no dependencies, so return a factory that
1045
1217
  // just instantiates the zero-arg constructor.
1046
- return () => new token();
1218
+ const inheritedInjectableDef = getInheritedInjectableDef(token);
1219
+ if (inheritedInjectableDef !== null) {
1220
+ return () => inheritedInjectableDef.factory(token);
1221
+ }
1222
+ else {
1223
+ return () => new token();
1224
+ }
1047
1225
  }
1048
- function providerToRecord(provider, ngModuleType, providers) {
1226
+ function providerToRecord(provider) {
1049
1227
  if (isValueProvider(provider)) {
1050
1228
  return makeRecord(undefined, provider.useValue);
1051
1229
  }
1052
1230
  else {
1053
- const factory = providerToFactory(provider, ngModuleType, providers);
1231
+ const factory = providerToFactory(provider);
1054
1232
  return makeRecord(factory, NOT_YET);
1055
1233
  }
1056
1234
  }
@@ -1124,6 +1302,16 @@ function couldBeInjectableType(value) {
1124
1302
  return (typeof value === 'function' ||
1125
1303
  (typeof value === 'object' && value instanceof InjectionToken));
1126
1304
  }
1305
+ function forEachSingleProvider(providers, fn) {
1306
+ for (const provider of providers) {
1307
+ if (Array.isArray(provider)) {
1308
+ forEachSingleProvider(provider, fn);
1309
+ }
1310
+ else {
1311
+ fn(provider);
1312
+ }
1313
+ }
1314
+ }
1127
1315
 
1128
1316
  /**
1129
1317
  * @license
@@ -1132,10 +1320,34 @@ function couldBeInjectableType(value) {
1132
1320
  * Use of this source code is governed by an MIT-style license that can be
1133
1321
  * found in the LICENSE file at https://angular.io/license
1134
1322
  */
1135
- function INJECTOR_IMPL__POST_R3__(providers, parent, name) {
1136
- return createInjector({ name: name }, parent, providers, name);
1323
+ /**
1324
+ * Create a new `Injector` which is configured using a `defType` of `InjectorType<any>`s.
1325
+ *
1326
+ * @publicApi
1327
+ */
1328
+ function createInjector(defType, parent = null, additionalProviders = null, name) {
1329
+ const injector = createInjectorWithoutInjectorInstances(defType, parent, additionalProviders, name);
1330
+ injector.resolveInjectorInitializers();
1331
+ return injector;
1332
+ }
1333
+ /**
1334
+ * Creates a new injector without eagerly resolving its injector types. Can be used in places
1335
+ * where resolving the injector types immediately can lead to an infinite loop. The injector types
1336
+ * should be resolved at a later point by calling `_resolveInjectorDefTypes`.
1337
+ */
1338
+ function createInjectorWithoutInjectorInstances(defType, parent = null, additionalProviders = null, name, scopes = new Set()) {
1339
+ const providers = [additionalProviders || EMPTY_ARRAY];
1340
+ name = name || (typeof defType === 'object' ? undefined : stringify(defType));
1341
+ return new R3Injector(providers, parent || getNullInjector(), name || null, scopes);
1137
1342
  }
1138
- const INJECTOR_IMPL = INJECTOR_IMPL__POST_R3__;
1343
+
1344
+ /**
1345
+ * @license
1346
+ * Copyright Google LLC All Rights Reserved.
1347
+ *
1348
+ * Use of this source code is governed by an MIT-style license that can be
1349
+ * found in the LICENSE file at https://angular.io/license
1350
+ */
1139
1351
  /**
1140
1352
  * Concrete injectors implement this interface. Injectors are configured
1141
1353
  * with [providers](guide/glossary#provider) that associate
@@ -1162,11 +1374,13 @@ const INJECTOR_IMPL = INJECTOR_IMPL__POST_R3__;
1162
1374
  */
1163
1375
  class Injector {
1164
1376
  static create(options, parent) {
1377
+ var _a;
1165
1378
  if (Array.isArray(options)) {
1166
- return INJECTOR_IMPL(options, parent, '');
1379
+ return createInjector({ name: '' }, parent, options, '');
1167
1380
  }
1168
1381
  else {
1169
- return INJECTOR_IMPL(options.providers, options.parent, options.name || '');
1382
+ const name = (_a = options.name) !== null && _a !== void 0 ? _a : '';
1383
+ return createInjector({ name }, options.parent, options.providers, name);
1170
1384
  }
1171
1385
  }
1172
1386
  }
@@ -1182,7 +1396,7 @@ Injector.ɵprov = ɵɵdefineInjectable({
1182
1396
  * @internal
1183
1397
  * @nocollapse
1184
1398
  */
1185
- Injector.__NG_ELEMENT_ID__ = -1 /* Injector */;
1399
+ Injector.__NG_ELEMENT_ID__ = -1 /* InjectorMarkers.Injector */;
1186
1400
 
1187
1401
  /**
1188
1402
  * @license
@@ -1254,4 +1468,4 @@ function getFactoryOf(type) {
1254
1468
  return getFactoryDef(type);
1255
1469
  }
1256
1470
 
1257
- export { INJECTOR_IMPL, INJECTOR_IMPL__POST_R3__, INJECTOR_SCOPE, Inject, InjectFlags, Injectable, InjectionToken, Injector, NG_PROV_DEF, NG_TEMP_TOKEN_PATH, NullInjector, Optional, R3Injector, SOURCE, Self, SkipSelf, THROW_IF_NOT_FOUND, USE_VALUE, attachInjectFlag, catchInjectorError, createInjector, createInjectorWithoutInjectorInstances, formatError, getInjectFlag, getInjectableDef, inject, injectArgs, injectInjectorOnly, isTypeProvider, providerToFactory, setCurrentInjector, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵgetInheritedFactory, ɵɵinject, ɵɵinvalidFactory };
1471
+ export { EnvironmentInjector, INJECTOR_SCOPE, Inject, InjectFlags, Injectable, InjectionToken, Injector, NG_INJECTABLE_DEF, NG_PROV_DEF, NG_TEMP_TOKEN_PATH, NullInjector, Optional, R3Injector, SOURCE, Self, SkipSelf, THROW_IF_NOT_FOUND, USE_VALUE, attachInjectFlag, catchInjectorError, convertToBitFlags, formatError, getInheritedInjectableDef, getInjectFlag, getInjectableDef, getNullInjector, inject, injectArgs, injectInjectorOnly, isTypeProvider, providerToFactory, setCurrentInjector, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵgetInheritedFactory, ɵɵinject, ɵɵinvalidFactory };