Skip to content

Commit 434fda0

Browse files
committed
fixing cycles around assert
1 parent 8f3b9f7 commit 434fda0

File tree

5 files changed

+66
-56
lines changed

5 files changed

+66
-56
lines changed

packages/@ember/debug/index.ts

Lines changed: 4 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import defaultDeprecate from './lib/deprecate';
66
import { isTesting } from './lib/testing';
77
import type { WarnFunc } from './lib/warn';
88
import _warn from './lib/warn';
9+
import { assert, setAssert } from './lib/assert';
910

1011
export { registerHandler as registerWarnHandler } from './lib/warn';
1112
export {
@@ -27,10 +28,6 @@ export type DebugFunctionType =
2728
| 'runInDebug'
2829
| 'deprecateFunc';
2930

30-
export interface AssertFunc {
31-
(desc: string, condition: unknown): asserts condition;
32-
(desc: string): never;
33-
}
3431
export type DebugFunc = (message: string) => void;
3532
export type DebugSealFunc = (obj: object) => void;
3633
export type DebugFreezeFunc = (obj: object) => void;
@@ -43,7 +40,7 @@ export type DeprecateFuncFunc = (
4340
) => Function;
4441

4542
export type GetDebugFunction = {
46-
(type: 'assert'): AssertFunc;
43+
(type: 'assert'): typeof assert;
4744
(type: 'info'): InfoFunc;
4845
(type: 'warn'): WarnFunc;
4946
(type: 'debug'): DebugFunc;
@@ -55,7 +52,7 @@ export type GetDebugFunction = {
5552
};
5653

5754
export type SetDebugFunction = {
58-
(type: 'assert', func: AssertFunc): AssertFunc;
55+
(type: 'assert', func: typeof assert): typeof assert;
5956
(type: 'info', func: InfoFunc): InfoFunc;
6057
(type: 'warn', func: WarnFunc): WarnFunc;
6158
(type: 'debug', func: DebugFunc): DebugFunc;
@@ -71,7 +68,6 @@ const noop = () => {};
7168

7269
// SAFETY: these casts are just straight-up lies, but the point is that they do
7370
// not do anything in production builds.
74-
let assert: AssertFunc = noop as unknown as AssertFunc;
7571
let info: InfoFunc = noop;
7672
let warn: WarnFunc = noop;
7773
let debug: DebugFunc = noop;
@@ -94,7 +90,7 @@ if (DEBUG) {
9490
setDebugFunction = function (type: DebugFunctionType, callback: Function) {
9591
switch (type) {
9692
case 'assert':
97-
return (assert = callback as AssertFunc);
93+
return setAssert(callback as typeof assert);
9894
case 'info':
9995
return (info = callback as InfoFunc);
10096
case 'warn':
@@ -143,51 +139,6 @@ if (DEBUG) {
143139
*/
144140

145141
if (DEBUG) {
146-
/**
147-
Verify that a certain expectation is met, or throw a exception otherwise.
148-
149-
This is useful for communicating assumptions in the code to other human
150-
readers as well as catching bugs that accidentally violates these
151-
expectations.
152-
153-
Assertions are removed from production builds, so they can be freely added
154-
for documentation and debugging purposes without worries of incuring any
155-
performance penalty. However, because of that, they should not be used for
156-
checks that could reasonably fail during normal usage. Furthermore, care
157-
should be taken to avoid accidentally relying on side-effects produced from
158-
evaluating the condition itself, since the code will not run in production.
159-
160-
```javascript
161-
import { assert } from '@ember/debug';
162-
163-
// Test for truthiness
164-
assert('Must pass a string', typeof str === 'string');
165-
166-
// Fail unconditionally
167-
assert('This code path should never be run');
168-
```
169-
170-
@method assert
171-
@static
172-
@for @ember/debug
173-
@param {String} description Describes the expectation. This will become the
174-
text of the Error thrown if the assertion fails.
175-
@param {any} condition Must be truthy for the assertion to pass. If
176-
falsy, an exception will be thrown.
177-
@public
178-
@since 1.0.0
179-
*/
180-
function assert(desc: string): never;
181-
function assert(desc: string, test: unknown): asserts test;
182-
// eslint-disable-next-line no-inner-declarations
183-
function assert(desc: string, test?: unknown): asserts test {
184-
if (!test) {
185-
throw new Error(`Assertion Failed: ${desc}`);
186-
}
187-
}
188-
189-
setDebugFunction('assert', assert);
190-
191142
/**
192143
Display a debug notice.
193144

packages/@ember/debug/lib/assert.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { DEBUG } from '@glimmer/env';
2+
3+
export interface AssertFunc {
4+
(desc: string, condition: unknown): asserts condition;
5+
(desc: string): never;
6+
}
7+
8+
export let assert: AssertFunc = (() => {}) as unknown as AssertFunc;
9+
10+
export function setAssert(implementation: typeof assert): typeof assert {
11+
assert = implementation;
12+
return implementation;
13+
}
14+
15+
if (DEBUG) {
16+
/**
17+
Verify that a certain expectation is met, or throw a exception otherwise.
18+
19+
This is useful for communicating assumptions in the code to other human
20+
readers as well as catching bugs that accidentally violates these
21+
expectations.
22+
23+
Assertions are removed from production builds, so they can be freely added
24+
for documentation and debugging purposes without worries of incuring any
25+
performance penalty. However, because of that, they should not be used for
26+
checks that could reasonably fail during normal usage. Furthermore, care
27+
should be taken to avoid accidentally relying on side-effects produced from
28+
evaluating the condition itself, since the code will not run in production.
29+
30+
```javascript
31+
import { assert } from '@ember/debug';
32+
33+
// Test for truthiness
34+
assert('Must pass a string', typeof str === 'string');
35+
36+
// Fail unconditionally
37+
assert('This code path should never be run');
38+
```
39+
40+
@method assert
41+
@static
42+
@for @ember/debug
43+
@param {String} description Describes the expectation. This will become the
44+
text of the Error thrown if the assertion fails.
45+
@param {any} condition Must be truthy for the assertion to pass. If
46+
falsy, an exception will be thrown.
47+
@public
48+
@since 1.0.0
49+
*/
50+
function assert(desc: string): never;
51+
function assert(desc: string, test: unknown): asserts test;
52+
// eslint-disable-next-line no-inner-declarations
53+
function assert(desc: string, test?: unknown): asserts test {
54+
if (!test) {
55+
throw new Error(`Assertion Failed: ${desc}`);
56+
}
57+
}
58+
setAssert(assert);
59+
}

packages/@ember/debug/lib/deprecate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ENV } from '@ember/-internals/environment';
22
import { DEBUG } from '@glimmer/env';
33

4-
import { assert } from '../index';
4+
import { assert } from './assert';
55
import type { HandlerCallback } from './handlers';
66
import { invoke, registerHandler as genericRegisterHandler } from './handlers';
77

packages/@ember/debug/lib/inspect.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { assert } from '@ember/debug';
1+
import { assert } from './assert';
22
const { toString: objectToString } = Object.prototype;
33
const { toString: functionToString } = Function.prototype;
44
const { isArray } = Array;

packages/@ember/debug/lib/warn.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { DEBUG } from '@glimmer/env';
22

3-
import { assert } from '../index';
3+
import { assert } from './assert';
44
import type { HandlerCallback } from './handlers';
55
import { invoke, registerHandler as genericRegisterHandler } from './handlers';
66

0 commit comments

Comments
 (0)