Skip to content

Commit ea38f39

Browse files
committed
Additional validation functions
1 parent eb6f98f commit ea38f39

File tree

14 files changed

+171
-91
lines changed

14 files changed

+171
-91
lines changed

@types/core/di/ng-module/ng-module.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@ export class NgModule {
3838
restDefinitions: any[];
3939
/**
4040
* @param {string} name
41-
* @param {any} object
41+
* @param {any} object - Allows undefined
4242
* @returns {NgModule}
4343
*/
4444
value(name: string, object: any): NgModule;
4545
/**
4646
* @param {string} name
47-
* @param {any} object
47+
* @param {Object|string|number} object
4848
* @returns {NgModule}
4949
*/
50-
constant(name: string, object: any): NgModule;
50+
constant(name: string, object: any | string | number): NgModule;
5151
/**
5252
*
5353
* @param {ng.Injectable<any>} configFn

@types/namespace.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ import {
5151
SseService as TSseService,
5252
SseConfig as TSseConfig,
5353
} from "./services/sse/interface.ts";
54-
import type { ErrorHandlingConfig as TErrorHandlingConfig } from "./shared/interface.ts";
54+
import type {
55+
ErrorHandlingConfig as TErrorHandlingConfig,
56+
Validator as TValidator,
57+
} from "./shared/interface.ts";
5558
import {
5659
BoundTranscludeFn as TBoundTranscludeFn,
5760
CompileFn as TCompileFn,
@@ -175,5 +178,6 @@ declare global {
175178
type ServiceProvider = TServiceProvider;
176179
type Expression = TExpression;
177180
type NgModelController = TNgModelController;
181+
type Validator = TValidator;
178182
}
179183
}

@types/shared/interface.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ export interface ErrorHandlingConfig {
1717
*/
1818
urlErrorParamsEnabled?: boolean;
1919
}
20+
export type Validator = (value: unknown) => boolean;

@types/shared/utils.d.ts

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,7 @@ export function isObject(value: any): boolean;
5757
* @returns {boolean} True if `value` is an `Object` with a null prototype
5858
*/
5959
export function isBlankObject(value: any): boolean;
60-
/**
61-
* Determines if a reference is a `String`.
62-
*
63-
* @param {*} value Reference to check.
64-
* @returns {boolean} True if `value` is a `String`.
65-
*/
66-
export function isString(value: any): boolean;
60+
export function isString(value: unknown): boolean;
6761
/**
6862
* Determines if a reference is a null.
6963
*
@@ -78,6 +72,13 @@ export function isNull(value: any): boolean;
7872
* @returns {boolean} True if `value` is null or undefined.
7973
*/
8074
export function isNullOrUndefined(obj: any): boolean;
75+
/**
76+
* Determines if a reference is not null or undefined.
77+
*
78+
* @param {*} obj Reference to check.
79+
* @returns {boolean} True if `value` is null or undefined.
80+
*/
81+
export function notNullOrUndefined(obj: any): boolean;
8182
/**
8283
* Determines if a reference is a `Number`.
8384
*
@@ -434,9 +435,30 @@ export function shallowCopy(src: any, dst: any): any;
434435
*/
435436
export function assert(argument: boolean, errorMsg?: string): void;
436437
/**
437-
* Throw error if the argument is falsy.
438+
* Validate a value using a predicate function.
439+
* Throws if the predicate returns false.
440+
*
441+
* @param {ng.Validator} fn - Predicate validator function.
442+
* @param {*} arg - The value to validate.
443+
* @param {string} name - Parameter name (included in error message).
444+
* @returns {*} The validated value.
445+
* @throws {TypeError} If the value does not satisfy the validator.
446+
*/
447+
export function validate(fn: ng.Validator, arg: any, name: string): any;
448+
/**
449+
* @param {*} arg - The value to validate.
450+
* @param {string} name - Parameter name (included in error message).
451+
* @returns {*} The validated value.
452+
* @throws {TypeError} If the value does not satisfy the validator.
453+
*/
454+
export function validateRequired(arg: any, name: string): any;
455+
/**
456+
* @param {*} arg - The value to validate.
457+
* @param {string} name - Parameter name (included in error message).
458+
* @returns {*} The validated value.
459+
* @throws {TypeError} If the value does not satisfy the validator.
438460
*/
439-
export function validate(fn: any, arg: any, name: any): any;
461+
export function validateArray(arg: any, name: string): any;
440462
/**
441463
* Throw error if the argument is falsy.
442464
*/
@@ -452,12 +474,12 @@ export function assertArgFn(
452474
*
453475
* Omitted or undefined options will leave the corresponding configuration values unchanged.
454476
*
455-
* @param {import("./interface.ts").ErrorHandlingConfig} [config]
456-
* @returns {import("./interface.ts").ErrorHandlingConfig}
477+
* @param {ng.ErrorHandlingConfig} [config]
478+
* @returns {ng.ErrorHandlingConfig}
457479
*/
458480
export function errorHandlingConfig(
459-
config?: import("./interface.ts").ErrorHandlingConfig,
460-
): import("./interface.ts").ErrorHandlingConfig;
481+
config?: ng.ErrorHandlingConfig,
482+
): ng.ErrorHandlingConfig;
461483
/**
462484
* This object provides a utility for producing rich Error messages within
463485
* AngularTS. It can be called as follows:

src/angular.spec.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -350,9 +350,15 @@ describe("module loader", () => {
350350

351351
it("should record calls", () => {
352352
const otherModule = angular.module("other", []);
353-
otherModule.config("otherInit");
354353

355-
const myModule = angular.module("my", ["other"], "config");
354+
const init = () => {};
355+
const config = () => {};
356+
const init2 = () => {};
357+
const run = () => {};
358+
359+
otherModule.config(init);
360+
361+
const myModule = angular.module("my", ["other"], config);
356362
const filterFn = () => () => "filterFn";
357363
expect(
358364
myModule
@@ -365,9 +371,9 @@ describe("module loader", () => {
365371
.directive("d", "dd")
366372
.component("c", "cc")
367373
.controller("ctrl", "ccc")
368-
.config("init2")
374+
.config(init2)
369375
.constant("abc", 123)
370-
.run("runBlock"),
376+
.run(run),
371377
).toBe(myModule);
372378

373379
expect(myModule.requires).toEqual(["other"]);
@@ -391,11 +397,11 @@ describe("module loader", () => {
391397
],
392398
]);
393399
expect(myModule.configBlocks).toEqual([
394-
["$injector", "invoke", jasmine.objectContaining(["config"])],
400+
["$injector", "invoke", jasmine.objectContaining([config])],
395401
["$provide", "decorator", jasmine.objectContaining(["dk", "dv"])],
396-
["$injector", "invoke", jasmine.objectContaining(["init2"])],
402+
["$injector", "invoke", jasmine.objectContaining([init2])],
397403
]);
398-
expect(myModule.runBlocks).toEqual(["runBlock"]);
404+
expect(myModule.runBlocks).toEqual([run]);
399405
});
400406

401407
it("should not throw error when `module.decorator` is declared before provider that it decorates", () => {

src/core/compile/compile.spec.js

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15396,7 +15396,6 @@ describe("$compile", () => {
1539615396
it("should return the module", () => {
1539715397
const myModule = module;
1539815398
expect(myModule.component("myComponent", {})).toBe(myModule);
15399-
expect(myModule.component({})).toBe(myModule);
1540015399
});
1540115400

1540215401
it("should register a directive", () => {
@@ -15412,34 +15411,6 @@ describe("$compile", () => {
1541215411
expect(log[0]).toEqual("OK");
1541315412
});
1541415413

15415-
it("should register multiple directives when object passed as first parameter", async () => {
15416-
module.component({
15417-
fooComponent: {
15418-
template: "<div>FOO SUCCESS</div>",
15419-
controller() {
15420-
log.push("FOO:OK");
15421-
},
15422-
},
15423-
barComponent: {
15424-
template: "<div>BAR SUCCESS</div>",
15425-
controller() {
15426-
log.push("BAR:OK");
15427-
},
15428-
},
15429-
});
15430-
initInjector("test1");
15431-
const fooElement = $compile("<foo-component></foo-component>")(
15432-
$rootScope,
15433-
);
15434-
const barElement = $compile("<bar-component></bar-component>")(
15435-
$rootScope,
15436-
);
15437-
await wait();
15438-
expect(fooElement.children[0].innerText).toEqual("FOO SUCCESS");
15439-
expect(barElement.children[0].innerText).toEqual("BAR SUCCESS");
15440-
expect(log.join("")).toEqual("FOO:OKBAR:OK");
15441-
});
15442-
1544315414
it("should register a directive via $compileProvider.component()", () => {
1544415415
module.component("myComponent", {
1544515416
template: "<div>SUCCESS</div>",

src/core/di/injector.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {
22
assert,
3-
assertArg,
43
assertArgFn,
54
assertNotHasOwnProperty,
65
isFunction,
@@ -9,6 +8,7 @@ import {
98
isString,
109
isUndefined,
1110
minErr,
11+
validateArray,
1212
} from "../../shared/utils.js";
1313
import { InjectorService, ProviderInjector } from "./internal-injector.js";
1414
import { createPersistentProxy } from "../../services/storage/storage.js";
@@ -282,11 +282,7 @@ export function createInjector(modulesToLoad, strictDi = false) {
282282
* @returns
283283
*/
284284
function loadModules(modules) {
285-
assertArg(
286-
isUndefined(modules) || Array.isArray(modules),
287-
"modulesToLoad",
288-
"not an array",
289-
);
285+
validateArray(modules, "modules");
290286
let moduleRunBlocks = [];
291287

292288
modules.forEach((module) => {

src/core/di/ng-module/ng-module.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import {
44
instantiateWasm,
55
isFunction,
66
isString,
7-
assertArg,
87
validate,
8+
isDefined,
99
} from "../../../shared/utils.js";
10+
import { isInjectable } from "../../../shared/predicates.js";
1011

1112
/**
1213
* Modules are collections of application configuration information for components:
@@ -22,7 +23,7 @@ export class NgModule {
2223
*/
2324
constructor(name, requires, configFn) {
2425
validate(isString, name, "name");
25-
validate(Array.isArray, requires, "not array");
26+
validate(Array.isArray, requires, "requires");
2627
/**
2728
* Name of the current module.
2829
* @type {string}
@@ -58,21 +59,26 @@ export class NgModule {
5859

5960
/**
6061
* @param {string} name
61-
* @param {any} object
62+
* @param {any} object - Allows undefined
6263
* @returns {NgModule}
6364
*/
6465
value(name, object) {
66+
validate(isString, name, "name");
67+
6568
this.invokeQueue.push([$t.$provide, "value", [name, object]]);
6669

6770
return this;
6871
}
6972

7073
/**
7174
* @param {string} name
72-
* @param {any} object
75+
* @param {Object|string|number} object
7376
* @returns {NgModule}
7477
*/
7578
constant(name, object) {
79+
validate(isString, name, "name");
80+
validate(isDefined, object, "object");
81+
7682
this.invokeQueue.unshift([$t.$provide, "constant", [name, object]]);
7783

7884
return this;
@@ -84,6 +90,8 @@ export class NgModule {
8490
* @returns {NgModule}
8591
*/
8692
config(configFn) {
93+
validate(isInjectable, configFn, "configFn");
94+
8795
this.configBlocks.push([$t.$injector, "invoke", [configFn]]);
8896

8997
return this;
@@ -94,6 +102,8 @@ export class NgModule {
94102
* @returns {NgModule}
95103
*/
96104
run(block) {
105+
validate(isInjectable, block, "block");
106+
97107
this.runBlocks.push(block);
98108

99109
return this;
@@ -105,6 +115,9 @@ export class NgModule {
105115
* @returns {NgModule}
106116
*/
107117
component(name, options) {
118+
validate(isString, name, "name");
119+
validate(isDefined, options, "object");
120+
108121
this.invokeQueue.push([$t.$compileProvider, "component", [name, options]]);
109122

110123
return this;
@@ -197,8 +210,8 @@ export class NgModule {
197210
* @return {NgModule}
198211
*/
199212
filter(name, filterFn) {
200-
assertArg(isString(name), "name");
201-
assertArg(isFunction(filterFn), `filterFn`);
213+
validate(isString, name, "name");
214+
validate(isFunction, filterFn, `filterFn`);
202215
this.invokeQueue.push([$t.$filterProvider, "register", [name, filterFn]]);
203216

204217
return this;

src/directive/options/options.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { emptyElement, removeElement, startingTag } from "../../shared/dom.js";
22
import {
3-
assertArg,
43
equals,
54
hasOwn,
65
hashKey,
76
includes,
87
isArrayLike,
98
isDefined,
109
minErr,
10+
validateRequired,
1111
} from "../../shared/utils.js";
1212

1313
const ngOptionsMinErr = minErr("ngOptions");
@@ -420,7 +420,7 @@ export function ngOptionsDirective($compile, $parse) {
420420
// compile the element since there might be bindings in it
421421
const linkFn = $compile(selectCtrl.emptyOption);
422422

423-
assertArg(linkFn, "LinkFn required");
423+
validateRequired(linkFn, "linkFn");
424424
selectElement.prepend(selectCtrl.emptyOption);
425425
linkFn(scope);
426426

src/namespace.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ import {
5555
SseService as TSseService,
5656
SseConfig as TSseConfig,
5757
} from "./services/sse/interface.ts";
58-
import type { ErrorHandlingConfig as TErrorHandlingConfig } from "./shared/interface.ts";
58+
import type {
59+
ErrorHandlingConfig as TErrorHandlingConfig,
60+
Validator as TValidator,
61+
} from "./shared/interface.ts";
5962
import {
6063
BoundTranscludeFn as TBoundTranscludeFn,
6164
CompileFn as TCompileFn,
@@ -188,5 +191,6 @@ declare global {
188191
export type ServiceProvider = TServiceProvider;
189192
export type Expression = TExpression;
190193
export type NgModelController = TNgModelController;
194+
export type Validator = TValidator;
191195
}
192196
}

0 commit comments

Comments
 (0)