Skip to content

Commit c9bf142

Browse files
Merge pull request #21459 from emberjs/nvp/make-renderComponent-demo-even-smaller
Reducing hello-world size
2 parents 8a9f078 + f374fdc commit c9bf142

9 files changed

Lines changed: 99 additions & 76 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@
211211
"@ember/application/namespace.js": "ember-source/@ember/application/namespace.js",
212212
"@ember/array/-internals.js": "ember-source/@ember/array/-internals.js",
213213
"@ember/array/index.js": "ember-source/@ember/array/index.js",
214+
"@ember/array/lib/is-array.js": "ember-source/@ember/array/lib/is-array.js",
214215
"@ember/array/lib/make-array.js": "ember-source/@ember/array/lib/make-array.js",
215216
"@ember/array/make.js": "ember-source/@ember/array/make.js",
216217
"@ember/array/mutable.js": "ember-source/@ember/array/mutable.js",

packages/@ember/-internals/glimmer/lib/component-managers/mount.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { InternalOwner } from '@ember/-internals/owner';
22
import { generateControllerFactory } from '@ember/routing/lib/generate_controller';
33
import { assert } from '@ember/debug';
4-
import EngineInstance from '@ember/engine/instance';
4+
import type EngineInstance from '@ember/engine/instance';
55
import { associateDestroyableChild } from '@glimmer/destroyable';
66
import type {
77
CapturedArguments,
@@ -82,8 +82,8 @@ class MountManager
8282
// we should resolve the engine app template in the helper
8383
// it also should use the owner that looked up the mount helper.
8484

85-
assert('Expected owner to be an EngineInstance', owner instanceof EngineInstance);
86-
let engine = owner.buildChildEngineInstance(name);
85+
assert('Expected owner to be an EngineInstance', 'buildChildEngineInstance' in owner);
86+
let engine = (owner as EngineInstance).buildChildEngineInstance(name);
8787

8888
engine.boot();
8989

packages/@ember/-internals/glimmer/lib/component-managers/outlet.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { InternalOwner } from '@ember/-internals/owner';
22
import type { Nullable } from '@ember/-internals/utility-types';
33
import { assert } from '@ember/debug';
4-
import EngineInstance from '@ember/engine/instance';
4+
import type EngineInstance from '@ember/engine/instance';
55
import { _instrumentStart } from '@ember/instrumentation';
66
import { precompileTemplate } from '@ember/template-compilation';
77
import type {
@@ -97,15 +97,16 @@ class OutletComponentManager
9797
if (parentOwner && parentOwner !== currentOwner) {
9898
assert(
9999
'Expected currentOwner to be an EngineInstance',
100-
currentOwner instanceof EngineInstance
100+
currentOwner != null && 'buildChildEngineInstance' in currentOwner
101101
);
102102

103-
let { mountPoint } = currentOwner;
103+
let engineInstance = currentOwner as EngineInstance;
104+
let { mountPoint } = engineInstance;
104105

105106
if (mountPoint) {
106107
state.engine = {
107108
mountPoint,
108-
instance: currentOwner,
109+
instance: engineInstance,
109110
};
110111
}
111112
}

packages/@ember/-internals/glimmer/lib/renderer.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ import { dict } from '@glimmer/util/lib/collections';
4444
import { unwrapTemplate } from './component-managers/unwrap-template';
4545
import { CURRENT_TAG, validateTag, valueForTag } from '@glimmer/validator/lib/validators';
4646
import type { SimpleDocument, SimpleElement, SimpleNode } from '@simple-dom/interface';
47-
import RSVP from 'rsvp';
4847
import type Component from './component';
4948
import { hasDOM } from '../../browser-environment';
5049
import type ClassicComponent from './component';
@@ -293,7 +292,12 @@ function loopBegin(): void {
293292
}
294293
}
295294

296-
let renderSettledDeferred: RSVP.Deferred<void> | null = null;
295+
interface RenderSettledDeferred {
296+
promise: Promise<void>;
297+
resolve: () => void;
298+
}
299+
300+
let renderSettledDeferred: RenderSettledDeferred | null = null;
297301
/*
298302
Returns a promise which will resolve when rendering has settled. Settled in
299303
this context is defined as when all of the tags in use are "current" (e.g.
@@ -305,7 +309,9 @@ let renderSettledDeferred: RSVP.Deferred<void> | null = null;
305309
*/
306310
export function renderSettled() {
307311
if (renderSettledDeferred === null) {
308-
renderSettledDeferred = RSVP.defer();
312+
let resolve!: () => void;
313+
let promise = new Promise<void>((r) => (resolve = r));
314+
renderSettledDeferred = { promise, resolve };
309315
// if there is no current runloop, the promise created above will not have
310316
// a chance to resolve (because its resolved in backburner's "end" event)
311317
if (!_getCurrentRunLoop()) {

packages/@ember/-internals/glimmer/lib/utils/to-bool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { isHTMLSafe } from './string';
22
import { get } from '@ember/-internals/metal/lib/property_get';
33
import { tagForProperty } from '@ember/-internals/metal/lib/tags';
4-
import { isArray } from '@ember/array';
4+
import isArray from '@ember/array/lib/is-array';
55
import { isProxy } from '@ember/-internals/utils/lib/is_proxy';
66
import { consumeTag } from '@glimmer/validator/lib/tracking';
77

packages/@ember/array/index.ts

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
/**
22
@module @ember/array
33
*/
4-
import { DEBUG } from '@glimmer/env';
5-
import { PROXY_CONTENT } from '@ember/-internals/metal/lib/property_get';
64
import { objectAt } from '@ember/-internals/metal/lib/object-at';
75
import { replaceInNativeArray, replace } from '@ember/-internals/metal/lib/array';
86
import computed from '@ember/-internals/metal/lib/computed';
@@ -17,11 +15,11 @@ import { assert } from '@ember/debug';
1715
import Enumerable from '@ember/enumerable';
1816
import MutableEnumerable from '@ember/enumerable/mutable';
1917
import compare from '@ember/utils/lib/compare';
20-
import typeOf from '@ember/utils/lib/type-of';
2118
import Observable from '@ember/object/observable';
2219
import type { MethodNamesOf, MethodParams, MethodReturns } from '@ember/-internals/utility-types';
2320
import type { ComputedPropertyCallback } from '@ember/-internals/metal/lib/computed';
2421
import { isEmberArray, setEmberArray } from '@ember/array/-internals';
22+
import isArray from './lib/is-array';
2523

2624
export { default as makeArray } from './make';
2725

@@ -137,65 +135,7 @@ function insertAt<T>(array: MutableArray<T>, index: number, item: T) {
137135
return item;
138136
}
139137

140-
/**
141-
Returns true if the passed object is an array or Array-like.
142-
143-
Objects are considered Array-like if any of the following are true:
144-
145-
- the object is a native Array
146-
- the object has an objectAt property
147-
- the object is an Object, and has a length property
148-
149-
Unlike `typeOf` this method returns true even if the passed object is
150-
not formally an array but appears to be array-like (i.e. implements `Array`)
151-
152-
```javascript
153-
import { isArray } from '@ember/array';
154-
import ArrayProxy from '@ember/array/proxy';
155-
156-
isArray(); // false
157-
isArray([]); // true
158-
isArray(ArrayProxy.create({ content: [] })); // true
159-
```
160-
161-
@method isArray
162-
@static
163-
@for @ember/array
164-
@param {Object} obj The object to test
165-
@return {Boolean} true if the passed object is an array or Array-like
166-
@public
167-
*/
168-
export function isArray(obj: unknown): obj is ArrayLike<unknown> | EmberArray<unknown> {
169-
if (DEBUG && typeof obj === 'object' && obj !== null) {
170-
// SAFETY: Property read checks are safe if it's an object
171-
let possibleProxyContent = (obj as any)[PROXY_CONTENT];
172-
if (possibleProxyContent !== undefined) {
173-
obj = possibleProxyContent;
174-
}
175-
}
176-
177-
// SAFETY: Property read checks are safe if it's an object
178-
if (!obj || (obj as any).setInterval) {
179-
return false;
180-
}
181-
182-
if (Array.isArray(obj) || EmberArray.detect(obj)) {
183-
return true;
184-
}
185-
186-
let type = typeOf(obj);
187-
if ('array' === type) {
188-
return true;
189-
}
190-
191-
// SAFETY: Property read checks are safe if it's an object
192-
let length = (obj as any).length;
193-
if (typeof length === 'number' && length === length && 'object' === type) {
194-
return true;
195-
}
196-
197-
return false;
198-
}
138+
export { isArray };
199139

200140
/*
201141
This allows us to define computed properties that are not enumerable.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { DEBUG } from '@glimmer/env';
2+
import { PROXY_CONTENT } from '@ember/-internals/metal/lib/property_get';
3+
import typeOf from '@ember/utils/lib/type-of';
4+
import { isEmberArray } from '@ember/array/-internals';
5+
import type EmberArray from '@ember/array';
6+
7+
/**
8+
@module @ember/array
9+
*/
10+
11+
/**
12+
Returns true if the passed object is an array or Array-like.
13+
14+
Objects are considered Array-like if any of the following are true:
15+
16+
- the object is a native Array
17+
- the object has an objectAt property
18+
- the object is an Object, and has a length property
19+
20+
Unlike `typeOf` this method returns true even if the passed object is
21+
not formally an array but appears to be array-like (i.e. implements `Array`)
22+
23+
```javascript
24+
import { isArray } from '@ember/array';
25+
import ArrayProxy from '@ember/array/proxy';
26+
27+
isArray(); // false
28+
isArray([]); // true
29+
isArray(ArrayProxy.create({ content: [] })); // true
30+
```
31+
32+
@method isArray
33+
@static
34+
@for @ember/array
35+
@param {Object} obj The object to test
36+
@return {Boolean} true if the passed object is an array or Array-like
37+
@public
38+
*/
39+
export default function isArray(obj: unknown): obj is ArrayLike<unknown> | EmberArray<unknown> {
40+
if (DEBUG && typeof obj === 'object' && obj !== null) {
41+
// SAFETY: Property read checks are safe if it's an object
42+
let possibleProxyContent = (obj as any)[PROXY_CONTENT];
43+
if (possibleProxyContent !== undefined) {
44+
obj = possibleProxyContent;
45+
}
46+
}
47+
48+
// SAFETY: Property read checks are safe if it's an object
49+
if (!obj || (obj as any).setInterval) {
50+
return false;
51+
}
52+
53+
// EmberArray's `init` brands every instance via `setEmberArray`; the only
54+
// unbranded EmberArray objects are native arrays upgraded by `A()`, which
55+
// `Array.isArray` catches. So this matches `EmberArray.detect` without
56+
// pulling in the mixin's module.
57+
if (Array.isArray(obj) || isEmberArray(obj)) {
58+
return true;
59+
}
60+
61+
let type = typeOf(obj);
62+
if ('array' === type) {
63+
return true;
64+
}
65+
66+
// SAFETY: Property read checks are safe if it's an object
67+
let length = (obj as any).length;
68+
if (typeof length === 'number' && length === length && 'object' === type) {
69+
return true;
70+
}
71+
72+
return false;
73+
}

packages/@ember/routing/lib/generate_controller.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { get } from '@ember/-internals/metal/lib/property_get';
22
import type { InternalFactory, default as Owner } from '@ember/-internals/owner';
3-
import Controller from '@ember/controller';
3+
import type Controller from '@ember/controller';
44
import { assert, info } from '@ember/debug';
55
import { DEBUG } from '@glimmer/env';
66

@@ -65,8 +65,8 @@ export default function generateController(owner: Owner, controllerName: string)
6565
generateControllerFactory(owner, controllerName);
6666

6767
let fullName = `controller:${controllerName}` as const;
68-
let instance = owner.lookup(fullName);
69-
assert('Expected an instance of controller', instance instanceof Controller);
68+
let instance = owner.lookup(fullName) as Controller;
69+
assert('Expected an instance of controller', instance != null && instance.isController === true);
7070

7171
if (DEBUG) {
7272
if (get(instance, 'namespace.LOG_ACTIVE_GENERATION')) {

tests/node-vitest/tree-shakability.test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ it('[dev] has expected tree-shakable entrypoints', async () => {
131131
"ember-source/@ember/application/instance.js",
132132
"ember-source/@ember/application/namespace.js",
133133
"ember-source/@ember/array/index.js",
134+
"ember-source/@ember/array/lib/is-array.js",
134135
"ember-source/@ember/array/mutable.js",
135136
"ember-source/@ember/array/proxy.js",
136137
"ember-source/@ember/canary-features/index.js",
@@ -335,6 +336,7 @@ it('[prod] has expected tree-shakable entrypoints', async () => {
335336
"ember-source/@ember/application/instance.js",
336337
"ember-source/@ember/application/namespace.js",
337338
"ember-source/@ember/array/index.js",
339+
"ember-source/@ember/array/lib/is-array.js",
338340
"ember-source/@ember/array/mutable.js",
339341
"ember-source/@ember/array/proxy.js",
340342
"ember-source/@ember/canary-features/index.js",

0 commit comments

Comments
 (0)