Skip to content

Commit 125e37b

Browse files
committed
Assert styleguide
1 parent 1d352cd commit 125e37b

File tree

5 files changed

+88
-167
lines changed

5 files changed

+88
-167
lines changed

@types/shared/utils.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ export function assert(argument: boolean, errorMsg?: string): void;
437437
/**
438438
* Validate a value using a predicate function.
439439
* Throws if the predicate returns false.
440+
* IMPORTANT: use this function only for developper errors and not for user/data errors
440441
*
441442
* @param {ng.Validator} fn - Predicate validator function.
442443
* @param {*} arg - The value to validate.
@@ -459,6 +460,13 @@ export function validateRequired(arg: any, name: string): any;
459460
* @throws {TypeError} If the value does not satisfy the validator.
460461
*/
461462
export function validateArray(arg: any, name: string): any;
463+
/**
464+
* @param {*} arg - The value to validate.
465+
* @param {string} name - Parameter name (included in error message).
466+
* @returns {*} The validated value.
467+
* @throws {TypeError} If the value does not satisfy the validator.
468+
*/
469+
export function validateIsString(arg: any, name: string): any;
462470
/**
463471
* Throw error if the argument is falsy.
464472
*/

DEVELOPERS.md

Lines changed: 0 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -342,158 +342,3 @@ yarn grunt build
342342

343343
To view the docs, see [Running a Local Development Web Server](#local-server).
344344

345-
### Writing jsdoc
346-
347-
The ngdoc utility has basic support for many of the standard jsdoc directives. But in particular it
348-
is interested in the following block tags:
349-
350-
- `@name name` - the name of the ngdoc document
351-
- `@param {type} name description` - describes a parameter of a function
352-
- `@returns {type} description` - describes what a function returns
353-
- `@requires` - normally indicates that a JavaScript module is required; in an Angular service it is
354-
used to describe what other services this service relies on
355-
- `@property` - describes a property of an object
356-
- `@description` - used to provide a description of a component in markdown
357-
- `@link` - specifies a link to a URL or a type in the API reference.
358-
Links to the API have the following structure:
359-
- the module namespace, followed by `.` (optional, default `ng`)
360-
- the `@ngdoc` type (see below), followed by `:` (optional, automatically inferred)
361-
- the name
362-
- the method, property, or anchor (optional)
363-
- the display name
364-
365-
For example: `{@link ng.type:$rootScope.Scope#$new Scope.$new()}`.
366-
367-
- `@example` - specifies an example. This can be a simple code block, or a
368-
[runnable example](#the-example-tag).
369-
- `@deprecated` - specifies that the following code is deprecated and should not be used.
370-
In The AngularTS docs, there are two specific patterns which can be used to further describe
371-
the deprecation: `sinceVersion="<version>"` and `removeVersion="<version>"`
372-
373-
The `type` in `@param` and `@returns` must be wrapped in `{}` curly braces, e.g. `{Object|Array}`.
374-
Parameters can be made optional by _either_ appending a `=` to the type, e.g. `{Object=}`, _or_ by
375-
putting the `[name]` in square brackets.
376-
Default values are only possible with the second syntax by appending `=<value>` to the parameter
377-
name, e.g. `@param {boolean} [ownPropsOnly=false]`.
378-
379-
Descriptions can contain markdown formatting.
380-
381-
#### AngularTS-specific jsdoc directives
382-
383-
In addition to the standard jsdoc tags, there are a number that are specific to the Angular
384-
code-base:
385-
386-
- `@ngdoc` - specifies the type of thing being documented. See below for more detail.
387-
- `@eventType emit|broadcast` - specifies whether the event is emitted or broadcast
388-
- `@usage` - shows how to use a `function` or `directive`. Is usually automatically generated.
389-
- `@knownIssue` - adds info about known quirks, problems, or limitations with the API, and possibly,
390-
workarounds. This section is not for bugs.
391-
392-
The following are specific to directives:
393-
394-
- `@animations` - specifies the animations a directive supports
395-
- `@multiElement` - specifies if a directive can span over multiple elements
396-
- `@priority` - specifies a directive's priority
397-
- `@restrict` - is extracted to show the usage of a directive. For example, for [E]lement,
398-
[A]ttribute, and [C]lass, use `@restrict ECA`
399-
- `@scope` - specifies that a directive will create a new scope
400-
401-
### The `@ngdoc` Directive
402-
403-
This directive helps to specify the template used to render the item being documented. For instance,
404-
a directive would have different properties to a filter and so would be documented differently. The
405-
commonly used types are:
406-
407-
- `overview` - a general page (guide, api index)
408-
- `provider` - AngularTS provider, such as `$compileProvider` or `$httpProvider`.
409-
- `service` - injectable AngularTS service, such as `$compile` or `$http`.
410-
- `object` - well defined object (often exposed as a service)
411-
- `function` - function that will be available to other methods (such as a helper function within
412-
the ng module)
413-
- `method` - method on an object/service/controller
414-
- `property` - property on an object/service/controller
415-
- `event` - AngularTS event that will propagate through the `$scope` tree.
416-
- `directive` - AngularTS directive
417-
- `filter` - AngularTS filter
418-
- `error` - minErr error description
419-
420-
### General documentation with Markdown
421-
422-
Any text in tags can contain markdown syntax for formatting. Generally, you can use any markdown
423-
feature.
424-
425-
#### Headings
426-
427-
Only use _h2_ headings and lower, as the page title is set in _h1_. Also make sure you follow the
428-
heading hierarchy. This ensures correct table of contents are created.
429-
430-
#### Code blocks
431-
432-
In line code can be specified by enclosing the code in back-ticks (\`).
433-
A block of multi-line code can be enclosed in triple back-ticks (\`\`\`) but it is formatted better
434-
if it is enclosed in &lt;pre&gt;...&lt;/pre&gt; tags and the code lines themselves are indented.
435-
436-
### Writing runnable (live) examples and e2e tests
437-
438-
It is possible to embed examples in the documentation along with appropriate e2e tests. These
439-
examples and scenarios will be converted to runnable code within the documentation. So it is
440-
important that they work correctly. To ensure this, all these e2e scenarios are run as part of the
441-
continuous integration tests.
442-
443-
If you are adding an example with an e2e test, you should [run the test locally](#e2e-tests) first
444-
to ensure it passes. You can change `it(...)` to `it(...)` to run only your test,
445-
but make sure you change it back to `it(...)` before committing.
446-
447-
#### The `<example>` tag
448-
449-
This tag identifies a block of HTML that will define a runnable example. It can take the following
450-
attributes:
451-
452-
- `animations` - if set to `true` then this example uses ngAnimate.
453-
- `deps` - Semicolon-separated list of additional angular module files to be loaded,
454-
e.g. `angular-animate.js`
455-
- `name` - every example should have a name. It should start with the component, e.g directive name,
456-
and not contain whitespace
457-
- `module` - the name of the app module as defined in the example's JavaScript
458-
459-
Within this tag we provide `<file>` tags that specify what files contain the example code.
460-
461-
```
462-
<example
463-
module="angularAppModule"
464-
name="exampleName"
465-
deps="angular-animate.js;angular-route.js"
466-
animations="true">
467-
...
468-
<file name="index.html">...</file>
469-
<file name="script.js">...</file>
470-
<file name="animations.css">...</file>
471-
<file name="protractor.js">...</file>
472-
...
473-
</example>
474-
```
475-
476-
You can see an example of a well-defined example [in the `ngRepeat` documentation][code.ngRepeat-example].
477-
478-
[closing-issues]: https://help.github.com/articles/closing-issues-via-commit-messages/
479-
[Closure guide to i18n changes]: https://github.com/google/closure-library/wiki/Internationalization-%28i18n%29-changes-in-Closure-Library
480-
[code.badrestrict]: https://github.com/angular/angular.js/blob/202f1809ad14827a6ac6a125157c605d65e0b551/src/ng/compile.js#L1107-L1110
481-
[code.debugInfoEnabled]: https://github.com/angular/angular.js/blob/32fbb2e78f53d765fbb170f7cf99e42e072d363b/src/ng/compile.js#L1378-L1413
482-
[code.html5Mode]: https://github.com/angular/angular.js/blob/202f1809ad14827a6ac6a125157c605d65e0b551/src/ng/location.js#L752-L797
483-
[code.minErr]: https://github.com/angular/angular.js/blob/202f1809ad14827a6ac6a125157c605d65e0b551/src/minErr.js#L53-L113
484-
[code.ngRepeat-example]: https://github.com/angular/angular.js/blob/0822d34b10ea0371c260c80a1486a4d508ea5a91/src/ng/directive/ngRepeat.js#L249-L340
485-
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
486-
[Common Locale Data Repository (CLDR)]: http://cldr.unicode.org
487-
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
488-
[dgeni]: https://github.com/angular/dgeni
489-
[docs.badrestrict]: docs/content/error/$compile/badrestrict.ngdoc
490-
[docs.provider]: https://code.angularjs.org/snapshot/docs/api/auto/service/$provide#provider
491-
[git-revert]: https://git-scm.com/docs/git-revert
492-
[git-setup]: https://help.github.com/articles/set-up-git
493-
[github-issues]: https://github.com/angular/angular.js/issues
494-
[github]: https://github.com/angular/angular.js
495-
[js-style-guide]: https://google.github.io/styleguide/javascriptguide.xml
496-
[karma-browserstack]: https://github.com/karma-runner/karma-browserstack-launcher
497-
[karma-saucelabs]: https://github.com/karma-runner/karma-sauce-launcher
498-
[unit-testing]: https://docs.angularjs.org/guide/unit-testing
499-
[yarn-install]: https://yarnpkg.com/en/docs/install

STYLEGUIDE.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# AngularTS Internal style guide
2+
3+
## 🔒 Assert Validation
4+
5+
Asserts enforce **framework correctness**, not **application behavior**.
6+
7+
Asserts exist to **detect developer errors**, enforce **internal
8+
invariants**, and make framework misuse fail fast during development.\
9+
They are *not* a general-purpose validation mechanism for runtime or
10+
user-controlled data.
11+
12+
Any assert must:
13+
- fail early and loudly with developer-only "sanity" checks
14+
- maintain and support **public** API contracts and types
15+
- must itself be part of the API via `@throw` tag
16+
17+
#### ✅ When to Use Asserts
18+
19+
Use asserts **only** when the error indicates a **fatal error**
20+
or **misuse of an internal API** such that a framework cannot function.
21+
22+
Asserts SHOULD be used when:
23+
24+
- An internal invariant is violated.
25+
- An API contract is not respected by developers.
26+
- A value should *never* be invalid if the code using the API assumes it
27+
to be correct.
28+
- The input originates from the framework itself, not from end-users or
29+
dynamic data.
30+
- The failure shoudl notify the developer to immediately stop what they are
31+
doing and refactor their code.
32+
33+
#### ❌ When *Not* to Use Asserts
34+
35+
Do **not** use asserts for anything that may fail due to **external
36+
conditions**, **user-controlled input** or performance-critical code.
37+
38+
Asserts SHOULD NOT be used for:
39+
40+
- End-user data.
41+
- JSON data, environment config, or network responses.
42+
- Errors that are part of expected runtime behavior.
43+
- Validation of business rules.
44+
45+
Assert SHOULD NOT be used in "hot code paths" or any place where
46+
its use can degrade the performance of the application over a period of time.
47+
48+
These should be handled either by the developer, before it reaches the framework API,
49+
or by a unified error sink at the framework level, such as `$exceptionHandler`;
50+
51+
###### Examples
52+
53+
- User-provided data fails validation.
54+
- Server returns malformed JSON.
55+
- Missing runtime config.
56+
- Event payloads have unexpected types.
57+
- Anything that can be corrected by the user instead of the developer.
58+

src/services/cookie/cookie.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { $injectTokens } from "../../injection-tokens.js";
22
import {
33
BADARG,
4-
BADARGKEY,
54
BADARGVALUE,
65
assert,
76
isDefined,
8-
isFunction,
97
isNullOrUndefined,
108
isNumber,
11-
isObject,
129
isString,
10+
validateIsString,
11+
validateRequired,
1312
} from "../../shared/utils.js";
1413

1514
/**
@@ -42,8 +41,6 @@ export class CookieService {
4241
* @param {ng.ExceptionHandlerService} $exceptionHandler
4342
*/
4443
constructor(defaults, $exceptionHandler) {
45-
assert(isObject(defaults), BADARG);
46-
assert(isFunction($exceptionHandler), BADARG);
4744
/** @type {ng.CookieOptions} */
4845
this.defaults = Object.freeze({ ...defaults });
4946
this.$exceptionHandler = $exceptionHandler;
@@ -57,7 +54,7 @@ export class CookieService {
5754
* @throws {URIError} – If decodeURIComponent fails.
5855
*/
5956
get(key) {
60-
assert(isString(key), BADARG);
57+
validateIsString(key, "key");
6158

6259
try {
6360
const all = parseCookies();
@@ -77,7 +74,8 @@ export class CookieService {
7774
* @throws {SyntaxError} if cookie JSON is invalid
7875
*/
7976
getObject(key) {
80-
assert(isString(key), BADARG);
77+
validateIsString(key, "key");
78+
8179
const raw = this.get(key);
8280

8381
if (!raw) return null;
@@ -113,8 +111,8 @@ export class CookieService {
113111
* @param {ng.CookieOptions} [options]
114112
*/
115113
put(key, value, options = {}) {
116-
assert(isString(key), BADARGKEY);
117-
assert(isString(value), BADARGVALUE);
114+
validateIsString(key, "key");
115+
validateIsString(value, "value");
118116
const encodedKey = encodeURIComponent(key);
119117

120118
const encodedVal = encodeURIComponent(value);
@@ -138,7 +136,8 @@ export class CookieService {
138136
* @throws {TypeError} if Object cannot be converted to JSON
139137
*/
140138
putObject(key, value, options) {
141-
assert(isString(key), BADARGKEY);
139+
validateIsString(key, "key");
140+
validateRequired(value, "value");
142141
assert(!isNullOrUndefined(value), BADARGVALUE);
143142

144143
try {
@@ -159,7 +158,7 @@ export class CookieService {
159158
* @param {ng.CookieOptions} [options]
160159
*/
161160
remove(key, options = {}) {
162-
assert(isString(key), BADARG);
161+
validateIsString(key, "key");
163162
this.put(key, "", {
164163
...this.defaults,
165164
...options,

src/shared/utils.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,7 @@ export function assert(argument, errorMsg = "Assertion failed") {
961961

962962
/** @type {Map<ng.Validator, string>} */
963963
const reasons = new Map([
964-
[isNullOrUndefined, "required"],
964+
[notNullOrUndefined, "required"],
965965
[Array.isArray, "notarray"],
966966
[isInjectable, "notinjectable"],
967967
[isDefined, "required"],
@@ -980,6 +980,7 @@ function getReason(val) {
980980
/**
981981
* Validate a value using a predicate function.
982982
* Throws if the predicate returns false.
983+
* IMPORTANT: use this function only for developper errors and not for user/data errors
983984
*
984985
* @param {ng.Validator} fn - Predicate validator function.
985986
* @param {*} arg - The value to validate.
@@ -1021,6 +1022,16 @@ export function validateArray(arg, name) {
10211022
return validate(Array.isArray, arg, name);
10221023
}
10231024

1025+
/**
1026+
* @param {*} arg - The value to validate.
1027+
* @param {string} name - Parameter name (included in error message).
1028+
* @returns {*} The validated value.
1029+
* @throws {TypeError} If the value does not satisfy the validator.
1030+
*/
1031+
export function validateIsString(arg, name) {
1032+
return validate(isString, arg, name);
1033+
}
1034+
10241035
/**
10251036
* Throw error if the argument is falsy.
10261037
*/

0 commit comments

Comments
 (0)