Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { DEBUG } from '@glimmer/env';
import { moduleFor, RenderingTestCase, applyMixins, strip, runTask } from 'internal-test-helpers';

import { isEmpty } from '@ember/utils';
import { action } from '@ember/object';
import { A as emberA } from '@ember/array';

Expand Down Expand Up @@ -956,35 +955,35 @@ moduleFor(
}
);

assert.ok(!isEmpty(instance), 'a instance was created');
assert.ok(instance, 'the component instance exinstance was created');
assert.equal(previousInstance, undefined, 'no previous component exists');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'open', 'the components text is "open"');

runTask(() => this.rerender());

assert.ok(!isEmpty(instance), 'the component instance exists');
assert.ok(instance, 'the component instance exists');
assert.equal(previousInstance, undefined, 'no previous component exists');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'open', 'the components text is "open"');

runTask(() => this.context.set('isOpen', false));

assert.ok(!isEmpty(instance), 'the component instance exists');
assert.ok(instance, 'the component instance exists');
assert.equal(previousInstance, undefined, 'no previous component exists');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'closed', 'the component text is "closed"');

runTask(() => this.rerender());

assert.ok(!isEmpty(instance), 'the component instance exists');
assert.ok(instance, 'the component instance exists');
assert.equal(previousInstance, undefined, 'no previous component exists');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'closed', 'the component text is "closed"');

runTask(() => this.context.set('isOpen', true));

assert.ok(!isEmpty(instance), 'the component instance exists');
assert.ok(instance, 'the component instance exists');
assert.equal(previousInstance, undefined, 'no previous component exists');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'open', 'the components text is "open"');
Expand Down Expand Up @@ -1021,35 +1020,35 @@ moduleFor(
}
);

assert.ok(!isEmpty(instance), 'a instance was created');
assert.ok(instance, 'a instance was created');
assert.equal(previousInstance, undefined, 'no previous component exists');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'open', 'the components text is "open"');

runTask(() => this.rerender());

assert.ok(!isEmpty(instance), 'the component instance exists');
assert.ok(instance, 'the component instance exists');
assert.equal(previousInstance, undefined, 'no previous component exists');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'open', 'the components text is "open"');

runTask(() => this.context.set('isOpen', false));

assert.ok(!isEmpty(instance), 'the component instance exists');
assert.ok(instance, 'the component instance exists');
assert.equal(previousInstance, undefined, 'no previous component exists');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'closed', 'the component text is "closed"');

runTask(() => this.rerender());

assert.ok(!isEmpty(instance), 'the component instance exists');
assert.ok(instance, 'the component instance exists');
assert.equal(previousInstance, undefined, 'no previous component exists');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'closed', 'the component text is "closed"');

runTask(() => this.context.set('isOpen', true));

assert.ok(!isEmpty(instance), 'the component instance exists');
assert.ok(instance, 'the component instance exists');
assert.equal(previousInstance, undefined, 'no previous component exists');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'open', 'the components text is "open"');
Expand Down Expand Up @@ -1099,22 +1098,22 @@ moduleFor(
}
);

assert.ok(!isEmpty(instance), 'a instance was created');
assert.ok(instance, 'a instance was created');
assert.equal(previousInstance, undefined, 'there is no previous instance');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'my-comp: open');

runTask(() => this.rerender());

assert.ok(!isEmpty(instance), 'a instance exists after rerender');
assert.ok(instance, 'a instance exists after rerender');
assert.equal(previousInstance, undefined, 'there is no previous instance after rerender');
assert.equal(initCount, 1, 'the component was constructed exactly 1 time');
assert.equal(this.$().text(), 'my-comp: open');

runTask(() => this.context.set('compName', 'your-comp'));

assert.ok(!isEmpty(instance), 'an instance was created after component name changed');
assert.ok(!isEmpty(previousInstance), 'a previous instance now exists');
assert.ok(instance, 'an instance was created after component name changed');
assert.ok(previousInstance, 'a previous instance now exists');
assert.notEqual(
instance,
previousInstance,
Expand All @@ -1125,11 +1124,8 @@ moduleFor(

runTask(() => this.rerender());

assert.ok(
!isEmpty(instance),
'an instance was created after component name changed (rerender)'
);
assert.ok(!isEmpty(previousInstance), 'a previous instance now exists (rerender)');
assert.ok(instance, 'an instance was created after component name changed (rerender)');
assert.ok(previousInstance, 'a previous instance now exists (rerender)');
assert.notEqual(
instance,
previousInstance,
Expand All @@ -1140,8 +1136,8 @@ moduleFor(

runTask(() => this.context.set('compName', 'my-comp'));

assert.ok(!isEmpty(instance), 'an instance was created after component name changed');
assert.ok(!isEmpty(previousInstance), 'a previous instance still exists');
assert.ok(instance, 'an instance was created after component name changed');
assert.ok(previousInstance, 'a previous instance still exists');
assert.notEqual(
instance,
previousInstance,
Expand Down
2 changes: 2 additions & 0 deletions packages/@ember/-internals/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ export {
teardownMandatorySetter,
setWithMandatorySetter,
} from './lib/mandatory-setter';
export type { TypeName } from './lib/type-of';
export { default as typeOf } from './lib/type-of';
125 changes: 125 additions & 0 deletions packages/@ember/-internals/utils/lib/type-of.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// import CoreObject from '@ember/object/core';

export type TypeName =
| 'undefined'
| 'null'
| 'string'
| 'number'
| 'boolean'
| 'function'
| 'array'
| 'regexp'
| 'date'
| 'filelist'
| 'class'
| 'instance'
| 'error'
| 'object';

// ........................................
// TYPING & ARRAY MESSAGING
//
const TYPE_MAP: Record<string, TypeName> = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object AsyncFunction]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regexp',
'[object Object]': 'object',
'[object FileList]': 'filelist',
} as const;

const { toString } = Object.prototype;

/**
@module @ember/utils
*/
/**
Returns a consistent type for the passed object.

Use this instead of the built-in `typeof` to get the type of an item.
It will return the same result across all browsers and includes a bit
more detail. Here is what will be returned:

| Return Value | Meaning |
|---------------|------------------------------------------------------|
| 'string' | String primitive or String object. |
| 'number' | Number primitive or Number object. |
| 'boolean' | Boolean primitive or Boolean object. |
| 'null' | Null value |
| 'undefined' | Undefined value |
| 'function' | A function |
| 'array' | An instance of Array |
| 'regexp' | An instance of RegExp |
| 'date' | An instance of Date |
| 'filelist' | An instance of FileList |
| 'class' | An Ember class (created using EmberObject.extend()) |
| 'instance' | An Ember object instance |
| 'error' | An instance of the Error object |
| 'object' | A JavaScript object not inheriting from EmberObject |

Examples:

```javascript
import { A } from '@ember/array';
import { typeOf } from '@ember/utils';
import EmberObject from '@ember/object';

typeOf(); // 'undefined'
typeOf(null); // 'null'
typeOf(undefined); // 'undefined'
typeOf('michael'); // 'string'
typeOf(new String('michael')); // 'string'
typeOf(101); // 'number'
typeOf(new Number(101)); // 'number'
typeOf(true); // 'boolean'
typeOf(new Boolean(true)); // 'boolean'
typeOf(A); // 'function'
typeOf(A()); // 'array'
typeOf([1, 2, 90]); // 'array'
typeOf(/abc/); // 'regexp'
typeOf(new Date()); // 'date'
typeOf(event.target.files); // 'filelist'
typeOf(EmberObject.extend()); // 'class'
typeOf(EmberObject.create()); // 'instance'
typeOf(new Error('teamocil')); // 'error'

// 'normal' JavaScript object
typeOf({ a: 'b' }); // 'object'
```

@method typeOf
@for @ember/-internals/utils
@param item the item to check
@return {String} the type
@public
@static
*/
export default function typeOf(item: unknown): TypeName {
if (item === null) {
return 'null';
}
if (item === undefined) {
return 'undefined';
}
let ret = TYPE_MAP[toString.call(item)] || 'object';

if (ret === 'function') {
// if (CoreObject.detect(item)) {
// ret = 'class';
// }
} else if (ret === 'object') {
if (item instanceof Error) {
ret = 'error';
// } else if (item instanceof CoreObject) {
// ret = 'instance';
} else if (item instanceof Date) {
ret = 'date';
}
}

return ret;
}
3 changes: 2 additions & 1 deletion packages/@ember/array/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import Mixin from '@ember/object/mixin';
import { assert } from '@ember/debug';
import Enumerable from '@ember/enumerable';
import MutableEnumerable from '@ember/enumerable/mutable';
import { compare, typeOf } from '@ember/utils';
import { compare } from '@ember/utils';
import { typeOf } from '@ember/-internals/utils';
import Observable from '@ember/object/observable';
import type { MethodNamesOf, MethodParams, MethodReturns } from '@ember/-internals/utility-types';
import type { ComputedPropertyCallback } from '@ember/-internals/metal';
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/debug/container-debug-adapter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { classify, dasherize } from '@ember/-internals/string';
import EmberObject from '@ember/object';
import { typeOf } from '@ember/utils';
import { typeOf } from '@ember/-internals/utils';
import type Owner from '@ember/owner';
import { getOwner } from '@ember/-internals/owner';
import type { Resolver } from '@ember/owner';
Expand Down
21 changes: 21 additions & 0 deletions packages/@ember/object/lib/computed/computed_macros.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ function generateComputedWithPredicate(name: string, predicate: (value: unknown)
@public
*/
export function empty(dependentKey: string) {
deprecate('empty is deprecated. Define your own property using @ember/legacy-utils.', false, {
id: 'ember-object.deprecate-empty',
until: '7.0.0',
for: 'ember-source',
since: { available: '6.8.0' },
});

assert(
'You attempted to use @empty as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
Expand Down Expand Up @@ -142,6 +149,13 @@ export function empty(dependentKey: string) {
@public
*/
export function notEmpty(dependentKey: string) {
deprecate('notEmpty is deprecated. Define your own property using @ember/legacy-utils.', false, {
id: 'ember-object.deprecate-not-empty',
until: '7.0.0',
for: 'ember-source',
since: { available: '6.8.0' },
});

assert(
'You attempted to use @notEmpty as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
Expand Down Expand Up @@ -185,6 +199,13 @@ export function notEmpty(dependentKey: string) {
@public
*/
export function none(dependentKey: string) {
deprecate('none is deprecated. Define your own property using @ember/legacy-utils.', false, {
id: 'ember-object.deprecate-none',
until: '7.0.0',
for: 'ember-source',
since: { available: '6.8.0' },
});

assert(
'You attempted to use @none as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
Expand Down
3 changes: 1 addition & 2 deletions packages/@ember/routing/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import EmberObject, { computed, get, set, getProperties, setProperties } from '@
import Evented from '@ember/object/evented';
import { A as emberA } from '@ember/array';
import { ActionHandler } from '@ember/-internals/runtime';
import { typeOf } from '@ember/utils';
import { isProxy, lookupDescriptor } from '@ember/-internals/utils';
import { isProxy, lookupDescriptor, typeOf } from '@ember/-internals/utils';
import type { AnyFn } from '@ember/-internals/utility-types';
import Controller from '@ember/controller';
import type { ControllerQueryParamType } from '@ember/controller';
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/routing/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import type {
import type RouterService from '@ember/routing/router-service';
import EmberObject from '@ember/object';
import { A as emberA } from '@ember/array';
import { typeOf } from '@ember/utils';
import { typeOf } from '@ember/-internals/utils';
import Evented from '@ember/object/evented';
import { assert, info } from '@ember/debug';
import { cancel, once, run, scheduleOnce } from '@ember/runloop';
Expand Down
9 changes: 8 additions & 1 deletion packages/@ember/utils/lib/compare.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { TypeName } from './type-of';
import typeOf from './type-of';
import { Comparable } from '@ember/-internals/runtime';
import { assert } from '@ember/debug';
import { assert, deprecate } from '@ember/debug';

const TYPE_ORDER: Record<TypeName, number> = {
undefined: 0,
Expand Down Expand Up @@ -97,6 +97,13 @@ function spaceship(a: number, b: number): Compare {
@public
*/
export default function compare<T>(v: T, w: T): Compare {
deprecate('compare is deprecated. Use @ember/legacy-utils instead.', false, {
for: 'ember-source',
id: 'ember-utils.deprecate-compare',
since: { available: '6.8.0' },
until: '7.0.0',
});

if (v === w) {
return 0;
}
Expand Down
10 changes: 10 additions & 0 deletions packages/@ember/utils/lib/is-equal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/**
@module @ember/utils
*/

import { deprecate } from '@ember/debug';

/**
Compares two objects, returning true if they are equal.

Expand Down Expand Up @@ -48,6 +51,13 @@
@public
*/
export default function isEqual(a: unknown, b: unknown): boolean {
deprecate('isEqual is deprecated. Use @ember/legacy-utils instead.', false, {
for: 'ember-source',
id: 'ember-utils.deprecate-isEqual',
since: { available: '6.8.0' },
until: '7.0.0',
});

if (a && typeof (a as IsEqual).isEqual === 'function') {
return (a as IsEqual).isEqual(b);
}
Expand Down
Loading
Loading