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