@angular-wave/angular.ts 0.0.64 → 0.0.66
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.
- package/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +2 -2
- package/package.json +1 -1
- package/public/jasmine/jasmine-5.1.2/jasmine-html.js +0 -1
- package/src/angular.spec.js +1 -1
- package/src/animations/animate-js.js +6 -0
- package/src/animations/animation.js +1 -1
- package/src/binding.spec.js +1 -1
- package/src/core/animate/animate.spec.js +1 -1
- package/src/core/cache/cache-factory.spec.js +1 -1
- package/src/core/compile/compile.js +13 -1
- package/src/core/compile/compile.spec.js +2 -3
- package/src/core/controller/controller.js +5 -0
- package/src/core/controller/controller.spec.js +1 -1
- package/src/core/cookie-reader.spec.js +1 -1
- package/src/core/di/injector.html +18 -0
- package/src/core/di/injector.js +299 -0
- package/src/{injector.md → core/di/injector.md} +3 -3
- package/src/{injector.spec.js → core/di/injector.spec.js} +49 -30
- package/src/core/di/injector.test.js +12 -0
- package/src/core/di/internal-injector.js +233 -0
- package/src/core/di/ng-module.html +18 -0
- package/src/core/{ng-module.js → di/ng-module.js} +64 -29
- package/src/core/di/ng-module.spec.js +269 -0
- package/src/core/di/ng-module.test.js +12 -0
- package/src/core/filter/filter.js +5 -0
- package/src/core/filter/filter.spec.js +1 -1
- package/src/core/interpolate/interpolate.spec.js +1 -1
- package/src/core/interval/interval.spec.js +1 -1
- package/src/core/location/location.spec.js +1 -1
- package/src/core/on.spec.js +1 -1
- package/src/core/parser/lexer.spec.js +1 -1
- package/src/core/parser/parse.spec.js +1 -1
- package/src/core/prop.spec.js +1 -1
- package/src/core/q/q.spec.js +1 -4
- package/src/core/q/q.test.js +12 -0
- package/src/core/sce/sce.js +6 -1
- package/src/core/sce/sce.spec.js +1 -1
- package/src/core/scope/scope.js +0 -1
- package/src/core/scope/scope.spec.js +1 -1
- package/src/core/timeout/timeout.spec.js +1 -1
- package/src/directive/attrs/attrs.spec.js +2 -2
- package/src/directive/attrs/boolean.spec.js +1 -1
- package/src/directive/attrs/element-style.spec.js +1 -1
- package/src/directive/attrs/src.spec.js +2 -2
- package/src/directive/bind/bind.spec.js +2 -2
- package/src/directive/bind/bing-html.spec.js +1 -1
- package/src/directive/change/change.spec.js +1 -1
- package/src/directive/class/class.spec.js +1 -1
- package/src/directive/cloak/cloak.spec.js +1 -1
- package/src/directive/controller/controller.spec.js +1 -1
- package/src/directive/events/click.spec.js +2 -2
- package/src/directive/events/event.spec.js +1 -1
- package/src/directive/form/form.spec.js +1 -1
- package/src/directive/if/if.spec.js +1 -1
- package/src/directive/include/include.spec.js +1 -1
- package/src/directive/init/init.spec.js +1 -1
- package/src/directive/input/input.spec.js +1 -2
- package/src/directive/list/list.spec.js +2 -2
- package/src/directive/model/model.spec.js +1 -1
- package/src/directive/model-options/model-options.spec.js +1 -1
- package/src/directive/non-bindable/non-bindable.spec.js +2 -2
- package/src/directive/options/options.spec.js +1 -1
- package/src/directive/ref/href.spec.js +1 -1
- package/src/directive/ref/ref.spec.js +1 -1
- package/src/directive/repeat/repeat.spec.js +1 -1
- package/src/directive/script/script.spec.js +1 -1
- package/src/directive/select/select.spec.js +1 -1
- package/src/directive/show-hide/show-hide.spec.js +1 -1
- package/src/directive/style/style.spec.js +1 -1
- package/src/directive/switch/switch.spec.js +1 -1
- package/src/directive/validators/validators.spec.js +1 -1
- package/src/exts/aria/aria.spec.js +1 -1
- package/src/exts/messages/messages.spec.js +1 -1
- package/src/filters/filter.spec.js +1 -1
- package/src/filters/filters.spec.js +1 -1
- package/src/filters/limit-to.spec.js +1 -1
- package/src/filters/order-by.spec.js +1 -1
- package/src/loader.js +7 -7
- package/src/loader.spec.js +4 -19
- package/src/public.spec.js +1 -1
- package/src/router/services.js +9 -4
- package/src/router/state/state-builder.js +4 -3
- package/src/router/state/state-registry.js +5 -0
- package/src/router/state/views.js +2 -1
- package/src/router/template-factory.js +5 -4
- package/src/services/http/http.js +12 -0
- package/src/services/http/http.spec.js +1 -1
- package/src/services/http/template-request.spec.js +1 -1
- package/src/services/http-backend/http-backend.spec.js +1 -1
- package/src/shared/jqlite/jqlite.js +0 -2
- package/src/shared/jqlite/jqlite.spec.js +1 -1
- package/src/shared/utils.js +10 -1
- package/src/src.html +0 -1
- package/src/types.js +9 -11
- package/types/animations/animate-js.d.ts +1 -1
- package/types/animations/animation.d.ts +1 -1
- package/types/core/compile/compile.d.ts +1 -1
- package/types/core/controller/controller.d.ts +1 -1
- package/types/core/di/injector.d.ts +18 -0
- package/types/core/di/internal-injector.d.ts +36 -0
- package/types/core/{ng-module.d.ts → di/ng-module.d.ts} +30 -8
- package/types/core/filter/filter.d.ts +1 -1
- package/types/core/sce/sce.d.ts +1 -1
- package/types/loader.d.ts +5 -5
- package/types/router/services.d.ts +8 -1
- package/types/router/state/state-registry.d.ts +2 -2
- package/types/router/template-factory.d.ts +2 -2
- package/types/services/http/http.d.ts +1 -1
- package/types/shared/utils.d.ts +7 -1
- package/types/types.d.ts +7 -32
- package/src/injector.js +0 -409
- package/types/injector.d.ts +0 -12
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Angular } from "
|
|
2
|
-
import { createInjector } from "./injector";
|
|
3
|
-
import { valueFn, extend } from "
|
|
1
|
+
import { Angular } from "../../loader";
|
|
2
|
+
import { createInjector, annotate } from "./injector";
|
|
3
|
+
import { valueFn, extend } from "../../shared/utils";
|
|
4
4
|
|
|
5
5
|
describe("injector.modules", () => {
|
|
6
6
|
beforeEach(() => {
|
|
@@ -13,10 +13,23 @@ describe("injector.modules", () => {
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
it("should have $injector", () => {
|
|
16
|
-
const $injector = createInjector();
|
|
16
|
+
const $injector = createInjector([]);
|
|
17
17
|
expect($injector.get("$injector")).toBe($injector);
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
+
it("should have modules property", () => {
|
|
21
|
+
const $injector = createInjector([]);
|
|
22
|
+
expect($injector.modules).toEqual({});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should have methods", () => {
|
|
26
|
+
const $injector = createInjector([]);
|
|
27
|
+
expect($injector.has).toBeDefined();
|
|
28
|
+
expect($injector.invoke).toBeDefined();
|
|
29
|
+
expect($injector.instantiate).toBeDefined();
|
|
30
|
+
expect($injector.get).toBeDefined();
|
|
31
|
+
});
|
|
32
|
+
|
|
20
33
|
it("should have a false strictDi property", () => {
|
|
21
34
|
const injector = createInjector([]);
|
|
22
35
|
expect(injector.strictDi).toBe(false);
|
|
@@ -30,13 +43,15 @@ describe("injector.modules", () => {
|
|
|
30
43
|
|
|
31
44
|
it("should provide useful message if no provider", () => {
|
|
32
45
|
expect(() => {
|
|
33
|
-
createInjector([])
|
|
46
|
+
const injector = createInjector([]);
|
|
47
|
+
injector.get("idontexist");
|
|
34
48
|
}).toThrowError(/Unknown provider/);
|
|
35
49
|
});
|
|
36
50
|
|
|
37
51
|
it("has a constant that has been registered to a module", () => {
|
|
38
52
|
const module = angular.module("myModule", []);
|
|
39
53
|
module.constant("aConstant", 42);
|
|
54
|
+
|
|
40
55
|
const injector = createInjector(["myModule"]);
|
|
41
56
|
expect(injector.has("aConstant")).toBe(true);
|
|
42
57
|
});
|
|
@@ -108,6 +123,7 @@ describe("injector.modules", () => {
|
|
|
108
123
|
log.push("initial");
|
|
109
124
|
});
|
|
110
125
|
const injector = createInjector(["initial"]);
|
|
126
|
+
expect(log).toEqual(["initial"]);
|
|
111
127
|
log.push("created");
|
|
112
128
|
|
|
113
129
|
angular
|
|
@@ -274,7 +290,7 @@ describe("injector.modules", () => {
|
|
|
274
290
|
expect(injector.invoke(fn)).toBe(3);
|
|
275
291
|
});
|
|
276
292
|
|
|
277
|
-
it("invokes
|
|
293
|
+
it("invokes a class with static property with dependency injection", () => {
|
|
278
294
|
const module = angular.module("myModule", []);
|
|
279
295
|
module.constant("a", 1);
|
|
280
296
|
module.constant("b", 2);
|
|
@@ -288,6 +304,20 @@ describe("injector.modules", () => {
|
|
|
288
304
|
expect(injector.invoke(Foo).c).toBe(3);
|
|
289
305
|
});
|
|
290
306
|
|
|
307
|
+
it("invokes an annotated class with dependency injection", () => {
|
|
308
|
+
const module = angular.module("myModule", []);
|
|
309
|
+
module.constant("a", 1);
|
|
310
|
+
module.constant("b", 2);
|
|
311
|
+
const injector = createInjector(["myModule"]);
|
|
312
|
+
class Foo {
|
|
313
|
+
constructor(a, b) {
|
|
314
|
+
this.c = a + b;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
Foo.$inject = ["a", "b"];
|
|
318
|
+
expect(injector.invoke(Foo).c).toBe(3);
|
|
319
|
+
});
|
|
320
|
+
|
|
291
321
|
it("does not accept non-strings as injection tokens", () => {
|
|
292
322
|
const module = angular.module("myModule", []);
|
|
293
323
|
module.constant("a", 1);
|
|
@@ -325,7 +355,7 @@ describe("injector.modules", () => {
|
|
|
325
355
|
return one + this.two;
|
|
326
356
|
},
|
|
327
357
|
};
|
|
328
|
-
|
|
358
|
+
expect(injector.invoke(["a", obj.fn], obj)).toBe(3);
|
|
329
359
|
});
|
|
330
360
|
|
|
331
361
|
it("overrides dependencies with locals when invoking", () => {
|
|
@@ -372,12 +402,10 @@ describe("injector.modules", () => {
|
|
|
372
402
|
});
|
|
373
403
|
|
|
374
404
|
describe("annotate", () => {
|
|
375
|
-
let annotate;
|
|
376
405
|
let injector;
|
|
377
406
|
beforeEach(() => {
|
|
378
407
|
window.angular = new Angular();
|
|
379
408
|
injector = createInjector([]);
|
|
380
|
-
annotate = injector.annotate;
|
|
381
409
|
});
|
|
382
410
|
|
|
383
411
|
it("should return $inject", () => {
|
|
@@ -392,7 +420,6 @@ describe("annotate", () => {
|
|
|
392
420
|
|
|
393
421
|
it("should create $inject", () => {
|
|
394
422
|
const extraParams = () => {};
|
|
395
|
-
/* eslint-disable space-before-function-paren */
|
|
396
423
|
// keep the multi-line to make sure we can handle it
|
|
397
424
|
function $f_n0 /*
|
|
398
425
|
*/(
|
|
@@ -498,43 +525,43 @@ describe("annotate", () => {
|
|
|
498
525
|
const injector = createInjector([]);
|
|
499
526
|
const fn = () => {};
|
|
500
527
|
fn.$inject = ["a", "b"];
|
|
501
|
-
expect(
|
|
528
|
+
expect(annotate(fn)).toEqual(["a", "b"]);
|
|
502
529
|
});
|
|
503
530
|
|
|
504
531
|
it("returns the array-style annotations of a function", () => {
|
|
505
532
|
const injector = createInjector([]);
|
|
506
533
|
const fn = ["a", "b", () => {}];
|
|
507
|
-
expect(
|
|
534
|
+
expect(annotate(fn)).toEqual(["a", "b"]);
|
|
508
535
|
});
|
|
509
536
|
|
|
510
537
|
it("returns the array-style annotations of a function", () => {
|
|
511
538
|
const injector = createInjector([]);
|
|
512
539
|
const fn = ["a", "b", () => {}];
|
|
513
|
-
expect(
|
|
540
|
+
expect(annotate(fn)).toEqual(["a", "b"]);
|
|
514
541
|
});
|
|
515
542
|
|
|
516
543
|
it("returns annotations parsed from function args when not annotated", () => {
|
|
517
544
|
const injector = createInjector([]);
|
|
518
545
|
const fn = function (a, b) {};
|
|
519
|
-
expect(
|
|
546
|
+
expect(annotate(fn)).toEqual(["a", "b"]);
|
|
520
547
|
});
|
|
521
548
|
|
|
522
549
|
it("returns annotations parsed from arrow args when not annotated", () => {
|
|
523
550
|
const injector = createInjector([]);
|
|
524
551
|
const fn = (a, b) => {};
|
|
525
|
-
expect(
|
|
552
|
+
expect(annotate(fn)).toEqual(["a", "b"]);
|
|
526
553
|
});
|
|
527
554
|
|
|
528
555
|
it("strips comments from argument lists when parsing", () => {
|
|
529
556
|
const injector = createInjector([]);
|
|
530
557
|
const fn = function (a, /*b,*/ c) {};
|
|
531
|
-
expect(
|
|
558
|
+
expect(annotate(fn)).toEqual(["a", "c"]);
|
|
532
559
|
});
|
|
533
560
|
|
|
534
561
|
it("strips several comments from argument lists when parsing", () => {
|
|
535
562
|
const injector = createInjector([]);
|
|
536
563
|
const fn = function (a, /*b,*/ c /*, d*/) {};
|
|
537
|
-
expect(
|
|
564
|
+
expect(annotate(fn)).toEqual(["a", "c"]);
|
|
538
565
|
});
|
|
539
566
|
|
|
540
567
|
it("strips // comments from argument lists when parsing", () => {
|
|
@@ -543,19 +570,13 @@ describe("annotate", () => {
|
|
|
543
570
|
a, //b,
|
|
544
571
|
c,
|
|
545
572
|
) {};
|
|
546
|
-
expect(
|
|
573
|
+
expect(annotate(fn)).toEqual(["a", "c"]);
|
|
547
574
|
});
|
|
548
575
|
|
|
549
576
|
it("strips surrounding underscores from argument names when parsing", () => {
|
|
550
577
|
const injector = createInjector([]);
|
|
551
578
|
const fn = function (a, _b_, c_, _d, an_argument) {};
|
|
552
|
-
expect(
|
|
553
|
-
"a",
|
|
554
|
-
"b",
|
|
555
|
-
"c_",
|
|
556
|
-
"_d",
|
|
557
|
-
"an_argument",
|
|
558
|
-
]);
|
|
579
|
+
expect(annotate(fn)).toEqual(["a", "b", "c_", "_d", "an_argument"]);
|
|
559
580
|
});
|
|
560
581
|
|
|
561
582
|
it("throws when using a non-annotated fn in strict mode", () => {
|
|
@@ -1909,7 +1930,8 @@ describe("decorator", () => {
|
|
|
1909
1930
|
"ng",
|
|
1910
1931
|
function ($provide) {
|
|
1911
1932
|
$provide.decorator("$injector", function ($delegate) {
|
|
1912
|
-
|
|
1933
|
+
// Don't forget the prototype
|
|
1934
|
+
return extend(Object.create($delegate), $delegate, {
|
|
1913
1935
|
get: function (val) {
|
|
1914
1936
|
if (val === "key") {
|
|
1915
1937
|
return "value";
|
|
@@ -1920,7 +1942,6 @@ describe("decorator", () => {
|
|
|
1920
1942
|
});
|
|
1921
1943
|
},
|
|
1922
1944
|
]);
|
|
1923
|
-
|
|
1924
1945
|
expect(injector.get("key")).toBe("value");
|
|
1925
1946
|
expect(injector.get("$http")).not.toBeUndefined();
|
|
1926
1947
|
});
|
|
@@ -2232,9 +2253,7 @@ describe("protection modes", () => {
|
|
|
2232
2253
|
});
|
|
2233
2254
|
|
|
2234
2255
|
it("should prevent instance lookup in module", () => {
|
|
2235
|
-
function instanceLookupInModule(name) {
|
|
2236
|
-
throw new Error("FAIL");
|
|
2237
|
-
}
|
|
2256
|
+
function instanceLookupInModule(name) {}
|
|
2238
2257
|
expect(() => {
|
|
2239
2258
|
createInjector([
|
|
2240
2259
|
function ($provide) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { test, expect } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
const TEST_URL = "src/core/di/injector.html";
|
|
4
|
+
|
|
5
|
+
test("unit tests contain no errors", async ({ page }) => {
|
|
6
|
+
await page.goto(TEST_URL);
|
|
7
|
+
await page.content();
|
|
8
|
+
await page.waitForTimeout(5000);
|
|
9
|
+
await expect(page.locator(".jasmine-overall-result")).toHaveText(
|
|
10
|
+
/0 failures/,
|
|
11
|
+
);
|
|
12
|
+
});
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { assertArgFn, minErr } from "../../shared/utils";
|
|
2
|
+
import { INJECTOR_LITERAL } from "./ng-module";
|
|
3
|
+
|
|
4
|
+
const ARROW_ARG = /^([^(]+?)=>/;
|
|
5
|
+
const FN_ARGS = /^[^(]*\(\s*([^)]*)\)/m;
|
|
6
|
+
const FN_ARG_SPLIT = /,/;
|
|
7
|
+
const FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
|
|
8
|
+
const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
|
|
9
|
+
const $injectorMinErr = minErr(INJECTOR_LITERAL);
|
|
10
|
+
|
|
11
|
+
const providerSuffix = "Provider";
|
|
12
|
+
const INSTANTIATING = "INSTANTIATING";
|
|
13
|
+
|
|
14
|
+
export class ProviderInjector {
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} cache
|
|
18
|
+
* @param {boolean} strictDi
|
|
19
|
+
*/
|
|
20
|
+
constructor(cache, strictDi) {
|
|
21
|
+
this.cache = cache;
|
|
22
|
+
this.strictDi = strictDi;
|
|
23
|
+
this.path = [];
|
|
24
|
+
this.providerCache = cache;
|
|
25
|
+
this.modules = undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
factory(caller) {
|
|
29
|
+
this.path.push(caller);
|
|
30
|
+
// prevents lookups to providers through get
|
|
31
|
+
throw $injectorMinErr(
|
|
32
|
+
"unpr",
|
|
33
|
+
"Unknown provider: {0}",
|
|
34
|
+
this.path.join(" <- "),
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
* @param {String} serviceName
|
|
41
|
+
* @returns {any}
|
|
42
|
+
*/
|
|
43
|
+
get(serviceName) {
|
|
44
|
+
if (Object.prototype.hasOwnProperty.call(this.cache, serviceName)) {
|
|
45
|
+
if (this.cache[serviceName] === INSTANTIATING) {
|
|
46
|
+
throw $injectorMinErr(
|
|
47
|
+
"cdep",
|
|
48
|
+
"Circular dependency found: {0}",
|
|
49
|
+
`${serviceName} <- ${this.path.join(" <- ")}`,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return this.cache[serviceName];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.path.unshift(serviceName);
|
|
56
|
+
this.cache[serviceName] = INSTANTIATING;
|
|
57
|
+
try {
|
|
58
|
+
// this goes to line 60
|
|
59
|
+
this.cache[serviceName] = this.factory(serviceName);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
// this is for the error handling being thrown by the providerCache multiple times
|
|
62
|
+
delete this.cache[serviceName];
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
return this.cache[serviceName];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
injectionArgs(fn, locals, serviceName) {
|
|
69
|
+
const args = [];
|
|
70
|
+
const $inject = annotate(fn, this.strictDi, serviceName);
|
|
71
|
+
|
|
72
|
+
for (let i = 0, { length } = $inject; i < length; i++) {
|
|
73
|
+
const key = $inject[i];
|
|
74
|
+
if (typeof key !== "string") {
|
|
75
|
+
throw $injectorMinErr(
|
|
76
|
+
"itkn",
|
|
77
|
+
"Incorrect injection token! Expected service name as string, got {0}",
|
|
78
|
+
key,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
args.push(
|
|
82
|
+
locals && Object.prototype.hasOwnProperty.call(locals, key)
|
|
83
|
+
? locals[key]
|
|
84
|
+
: this.get(key),
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
return args;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
invoke(fn, self, locals, serviceName) {
|
|
91
|
+
if (typeof locals === "string") {
|
|
92
|
+
serviceName = locals;
|
|
93
|
+
locals = null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const args = this.injectionArgs(fn, locals, serviceName);
|
|
97
|
+
if (Array.isArray(fn)) {
|
|
98
|
+
fn = fn[fn.length - 1];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (isClass(fn)) {
|
|
102
|
+
args.unshift(null);
|
|
103
|
+
return new (Function.prototype.bind.apply(fn, args))();
|
|
104
|
+
} else {
|
|
105
|
+
return fn.apply(self, args);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
instantiate(Type, locals, serviceName) {
|
|
110
|
+
// Check if Type is annotated and use just the given function at n-1 as parameter
|
|
111
|
+
// e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
|
|
112
|
+
const ctor = Array.isArray(Type) ? Type[Type.length - 1] : Type;
|
|
113
|
+
const args = this.injectionArgs(Type, locals, serviceName);
|
|
114
|
+
// Empty object at position 0 is ignored for invocation with `new`, but required.
|
|
115
|
+
args.unshift(null);
|
|
116
|
+
return new (Function.prototype.bind.apply(ctor, args))();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
*
|
|
121
|
+
* @param {String} name
|
|
122
|
+
* @returns {boolean}
|
|
123
|
+
*/
|
|
124
|
+
has(name) {
|
|
125
|
+
const hasProvider = Object.prototype.hasOwnProperty.call(
|
|
126
|
+
this.providerCache,
|
|
127
|
+
name + providerSuffix,
|
|
128
|
+
);
|
|
129
|
+
const hasCache = Object.prototype.hasOwnProperty.call(this.cache, name);
|
|
130
|
+
return hasProvider || hasCache;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// /**
|
|
135
|
+
// * @typedef {Object} LegacyInjectorService
|
|
136
|
+
// * @property {function(Function, boolean=): string[]} annotate - Annotate a function or an array of inline annotations.
|
|
137
|
+
// * @property {function(string, string=): any} get - Get a service by name.
|
|
138
|
+
// * @property {function(Function, any?): any} instantiate - Instantiate a type constructor with optional locals.
|
|
139
|
+
// * @property {function(import("../../types").Injectable<Function | ((...args: any[]) => any)>, any=, any=): any} invoke - Invoke a function with optional context and locals.
|
|
140
|
+
// * @property {function(Array<import("../../types").Module | string | import("../../types").Injectable<(...args: any[]) => void>>): void} [loadNewModules] - Add and load new modules to the injector.
|
|
141
|
+
// * @property {Object.<string, import("../../types").Module>} [modules] - A map of all the modules loaded into the injector.
|
|
142
|
+
// * @property {boolean} [strictDi] - Indicates if strict dependency injection is enforced.
|
|
143
|
+
// */
|
|
144
|
+
|
|
145
|
+
export class InjectorService extends ProviderInjector {
|
|
146
|
+
constructor(cache, strictDi, providerInjector) {
|
|
147
|
+
super(cache, strictDi);
|
|
148
|
+
this.strictDi = strictDi;
|
|
149
|
+
this.providerInjector = providerInjector;
|
|
150
|
+
this.providerCache = providerInjector.cache;
|
|
151
|
+
this.modules = undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
factory(serviceName, caller) {
|
|
155
|
+
const provider = this.providerInjector.get(
|
|
156
|
+
serviceName + providerSuffix,
|
|
157
|
+
caller,
|
|
158
|
+
);
|
|
159
|
+
const res = this.invoke(provider.$get, provider, undefined, serviceName);
|
|
160
|
+
return res;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Gets overridden
|
|
164
|
+
loadNewModules() {}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Helpers
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @param {String} fn
|
|
171
|
+
* @returns {String}
|
|
172
|
+
*/
|
|
173
|
+
function stringifyFn(fn) {
|
|
174
|
+
return Function.prototype.toString.call(fn);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @param {String} fn
|
|
179
|
+
* @returns {Array<any>}
|
|
180
|
+
*/
|
|
181
|
+
function extractArgs(fn) {
|
|
182
|
+
const fnText = stringifyFn(fn).replace(STRIP_COMMENTS, "");
|
|
183
|
+
const args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
|
|
184
|
+
return args;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @param {String} func
|
|
189
|
+
* @returns {boolean}
|
|
190
|
+
*/
|
|
191
|
+
function isClass(func) {
|
|
192
|
+
return /^class\b/.test(stringifyFn(func));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
*
|
|
197
|
+
* @param {any} fn
|
|
198
|
+
* @param {boolean} strictDi
|
|
199
|
+
* @param {String} name
|
|
200
|
+
* @returns {Array<string>}
|
|
201
|
+
*/
|
|
202
|
+
function annotate(fn, strictDi, name) {
|
|
203
|
+
var $inject, argDecl, last;
|
|
204
|
+
|
|
205
|
+
if (typeof fn === "function") {
|
|
206
|
+
if (!($inject = fn.$inject)) {
|
|
207
|
+
$inject = [];
|
|
208
|
+
if (fn.length) {
|
|
209
|
+
if (strictDi) {
|
|
210
|
+
throw $injectorMinErr(
|
|
211
|
+
"strictdi",
|
|
212
|
+
"{0} is not using explicit annotation and cannot be invoked in strict mode",
|
|
213
|
+
name,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
argDecl = extractArgs(/** @type {String} */ (fn));
|
|
217
|
+
argDecl[1].split(FN_ARG_SPLIT).forEach(function (arg) {
|
|
218
|
+
arg.replace(FN_ARG, function (all, underscore, name) {
|
|
219
|
+
$inject.push(name);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
fn.$inject = $inject;
|
|
224
|
+
}
|
|
225
|
+
} else if (Array.isArray(fn)) {
|
|
226
|
+
last = /** @type {Array} */ (fn).length - 1;
|
|
227
|
+
assertArgFn(fn[last], "fn");
|
|
228
|
+
$inject = /** @type {Array} */ (fn).slice(0, last);
|
|
229
|
+
} else {
|
|
230
|
+
assertArgFn(fn, "fn", true);
|
|
231
|
+
}
|
|
232
|
+
return $inject;
|
|
233
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>AngularTS Test Runner</title>
|
|
6
|
+
|
|
7
|
+
<link rel="shortcut icon" type="image/png" href="/images/favicon.ico" />
|
|
8
|
+
<link rel="stylesheet" href="/jasmine/jasmine-5.1.2/jasmine.css" />
|
|
9
|
+
<script src="/jasmine/jasmine-5.1.2/jasmine.js"></script>
|
|
10
|
+
<script src="/jasmine/jasmine-5.1.2/jasmine-html.js"></script>
|
|
11
|
+
<script src="/jasmine/jasmine-5.1.2/boot0.js"></script>
|
|
12
|
+
<script src="/jasmine/jasmine-5.1.2/boot1.js"></script>
|
|
13
|
+
<script type="module" src="/src/core/di/ng-module.spec.js"></script>
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<div id="dummy"></div>
|
|
17
|
+
</body>
|
|
18
|
+
</html>
|
|
@@ -1,7 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
isFunction,
|
|
3
|
+
isDefined,
|
|
4
|
+
isObject,
|
|
5
|
+
isString,
|
|
6
|
+
assert,
|
|
7
|
+
} from "../../shared/utils";
|
|
8
|
+
|
|
9
|
+
export const PROVIDE_LITERAL = "$provide";
|
|
10
|
+
export const INJECTOR_LITERAL = "$injector";
|
|
11
|
+
export const COMPILE_LITERAL = "$compileProvider";
|
|
12
|
+
export const ANIMATION_LITERAL = "$animateProvider";
|
|
13
|
+
export const FILTER_LITERAL = "$filterProvider";
|
|
14
|
+
export const CONTROLLER_LITERAL = "$controllerProvider";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Modules are collections of application configuration information for components:
|
|
18
|
+
* controllers, directives, filters, etc. They provide recipes for the injector
|
|
19
|
+
* to do the actual instantiation. A module itself has no behaviour but only state.
|
|
20
|
+
* A such, it acts as a data structure between the Angular instance and the injector service.
|
|
21
|
+
*
|
|
22
|
+
* Since this is an internal structure that is exposed only via the Angular instance,
|
|
23
|
+
* it contains no validation of the items it receives. It is up to the instantiator on
|
|
24
|
+
* modules to do the actual validation.
|
|
25
|
+
*/
|
|
5
26
|
export class NgModule {
|
|
6
27
|
/**
|
|
7
28
|
*
|
|
@@ -10,6 +31,8 @@ export class NgModule {
|
|
|
10
31
|
* @param {Function} [configFn]
|
|
11
32
|
*/
|
|
12
33
|
constructor(name, requires, configFn) {
|
|
34
|
+
assert(isString(name), "name required");
|
|
35
|
+
assert(Array.isArray(requires), "requires array required");
|
|
13
36
|
/**
|
|
14
37
|
* @type {string}
|
|
15
38
|
* Name of the module.
|
|
@@ -21,16 +44,17 @@ export class NgModule {
|
|
|
21
44
|
*/
|
|
22
45
|
this.requires = requires;
|
|
23
46
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Holds a collection of tasks, required to instantiate an angular component
|
|
49
|
+
* @type {!Array<Array<*>>}
|
|
50
|
+
*/
|
|
51
|
+
this.invokeQueue = [];
|
|
28
52
|
|
|
29
|
-
/** @type {!Array
|
|
30
|
-
this.
|
|
53
|
+
/** @type {!Array<Array<*>>} */
|
|
54
|
+
this.configBlocks = [];
|
|
31
55
|
|
|
32
56
|
/** @type {!Array.<Function>} */
|
|
33
|
-
this.
|
|
57
|
+
this.runBlocks = [];
|
|
34
58
|
|
|
35
59
|
/** @type {Object} */
|
|
36
60
|
this.infoState = {};
|
|
@@ -41,14 +65,12 @@ export class NgModule {
|
|
|
41
65
|
}
|
|
42
66
|
|
|
43
67
|
/**
|
|
44
|
-
*
|
|
45
68
|
* @param {Object} value
|
|
46
69
|
* @returns
|
|
47
70
|
*/
|
|
48
71
|
info(value) {
|
|
49
72
|
if (isDefined(value)) {
|
|
50
|
-
|
|
51
|
-
throw ngMinErr("aobj", "Argument '{0}' must be an object", "value");
|
|
73
|
+
assert(isObject(value), "module info value must be an object");
|
|
52
74
|
this.infoState = value;
|
|
53
75
|
return this;
|
|
54
76
|
}
|
|
@@ -61,7 +83,7 @@ export class NgModule {
|
|
|
61
83
|
* @returns {NgModule}
|
|
62
84
|
*/
|
|
63
85
|
value(name, object) {
|
|
64
|
-
this.
|
|
86
|
+
this.invokeQueue.push([PROVIDE_LITERAL, "value", [name, object]]);
|
|
65
87
|
return this;
|
|
66
88
|
}
|
|
67
89
|
|
|
@@ -71,17 +93,22 @@ export class NgModule {
|
|
|
71
93
|
* @returns {NgModule}
|
|
72
94
|
*/
|
|
73
95
|
constant(name, object) {
|
|
74
|
-
this.
|
|
96
|
+
this.invokeQueue.unshift([PROVIDE_LITERAL, "constant", [name, object]]);
|
|
75
97
|
return this;
|
|
76
98
|
}
|
|
77
99
|
|
|
100
|
+
/**
|
|
101
|
+
*
|
|
102
|
+
* @param {Function} configFn
|
|
103
|
+
* @returns {NgModule}
|
|
104
|
+
*/
|
|
78
105
|
config(configFn) {
|
|
79
|
-
this.
|
|
106
|
+
this.configBlocks.push([INJECTOR_LITERAL, "invoke", [configFn]]);
|
|
80
107
|
return this;
|
|
81
108
|
}
|
|
82
109
|
|
|
83
110
|
run(block) {
|
|
84
|
-
this.
|
|
111
|
+
this.runBlocks.push(block);
|
|
85
112
|
return this;
|
|
86
113
|
}
|
|
87
114
|
|
|
@@ -89,7 +116,7 @@ export class NgModule {
|
|
|
89
116
|
if (options && isFunction(options)) {
|
|
90
117
|
options.$$moduleName = name;
|
|
91
118
|
}
|
|
92
|
-
this.
|
|
119
|
+
this.invokeQueue.push([COMPILE_LITERAL, "component", [name, options]]);
|
|
93
120
|
return this;
|
|
94
121
|
}
|
|
95
122
|
|
|
@@ -97,7 +124,11 @@ export class NgModule {
|
|
|
97
124
|
if (providerFunction && isFunction(providerFunction)) {
|
|
98
125
|
providerFunction.$$moduleName = name;
|
|
99
126
|
}
|
|
100
|
-
this.
|
|
127
|
+
this.invokeQueue.push([
|
|
128
|
+
PROVIDE_LITERAL,
|
|
129
|
+
"factory",
|
|
130
|
+
[name, providerFunction],
|
|
131
|
+
]);
|
|
101
132
|
return this;
|
|
102
133
|
}
|
|
103
134
|
|
|
@@ -105,7 +136,11 @@ export class NgModule {
|
|
|
105
136
|
if (serviceFunction && isFunction(serviceFunction)) {
|
|
106
137
|
serviceFunction.$$moduleName = name;
|
|
107
138
|
}
|
|
108
|
-
this.
|
|
139
|
+
this.invokeQueue.push([
|
|
140
|
+
PROVIDE_LITERAL,
|
|
141
|
+
"service",
|
|
142
|
+
[name, serviceFunction],
|
|
143
|
+
]);
|
|
109
144
|
return this;
|
|
110
145
|
}
|
|
111
146
|
|
|
@@ -113,7 +148,7 @@ export class NgModule {
|
|
|
113
148
|
if (providerType && isFunction(providerType)) {
|
|
114
149
|
providerType.$$moduleName = name;
|
|
115
150
|
}
|
|
116
|
-
this.
|
|
151
|
+
this.invokeQueue.push([PROVIDE_LITERAL, "provider", [name, providerType]]);
|
|
117
152
|
return this;
|
|
118
153
|
}
|
|
119
154
|
|
|
@@ -121,7 +156,7 @@ export class NgModule {
|
|
|
121
156
|
if (decorFn && isFunction(decorFn)) {
|
|
122
157
|
decorFn.$$moduleName = name;
|
|
123
158
|
}
|
|
124
|
-
this.
|
|
159
|
+
this.configBlocks.push([PROVIDE_LITERAL, "decorator", [name, decorFn]]);
|
|
125
160
|
return this;
|
|
126
161
|
}
|
|
127
162
|
|
|
@@ -129,8 +164,8 @@ export class NgModule {
|
|
|
129
164
|
if (directiveFactory && isFunction(directiveFactory)) {
|
|
130
165
|
directiveFactory.$$moduleName = name;
|
|
131
166
|
}
|
|
132
|
-
this.
|
|
133
|
-
|
|
167
|
+
this.invokeQueue.push([
|
|
168
|
+
COMPILE_LITERAL,
|
|
134
169
|
"directive",
|
|
135
170
|
[name, directiveFactory],
|
|
136
171
|
]);
|
|
@@ -141,8 +176,8 @@ export class NgModule {
|
|
|
141
176
|
if (animationFactory && isFunction(animationFactory)) {
|
|
142
177
|
animationFactory.$$moduleName = name;
|
|
143
178
|
}
|
|
144
|
-
this.
|
|
145
|
-
|
|
179
|
+
this.invokeQueue.push([
|
|
180
|
+
ANIMATION_LITERAL,
|
|
146
181
|
"register",
|
|
147
182
|
[name, animationFactory],
|
|
148
183
|
]);
|
|
@@ -153,7 +188,7 @@ export class NgModule {
|
|
|
153
188
|
if (filterFn && isFunction(filterFn)) {
|
|
154
189
|
filterFn.$$moduleName = name;
|
|
155
190
|
}
|
|
156
|
-
this.
|
|
191
|
+
this.invokeQueue.push([FILTER_LITERAL, "register", [name, filterFn]]);
|
|
157
192
|
return this;
|
|
158
193
|
}
|
|
159
194
|
|
|
@@ -161,7 +196,7 @@ export class NgModule {
|
|
|
161
196
|
if (ctlFn && isFunction(ctlFn)) {
|
|
162
197
|
ctlFn.$$moduleName = name;
|
|
163
198
|
}
|
|
164
|
-
this.
|
|
199
|
+
this.invokeQueue.push([CONTROLLER_LITERAL, "register", [name, ctlFn]]);
|
|
165
200
|
return this;
|
|
166
201
|
}
|
|
167
202
|
}
|