Skip to content

Commit

Permalink
Backporting circularity fixes
Browse files Browse the repository at this point in the history
This is backporting https://github.com/emberjs/ember.js/pull/20734/files to current release (5.x).
  • Loading branch information
ef4 committed Sep 7, 2024
1 parent 628abae commit 8687287
Show file tree
Hide file tree
Showing 35 changed files with 168 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export default class CurlyComponentManager

beginTrackFrame();
let props = processComponentArgs(capturedArgs);
props[ARGS] = capturedArgs;
let argsTag = endTrackFrame();

// Alias `id` argument to `elementId` property on the component instance.
Expand Down
12 changes: 6 additions & 6 deletions packages/@ember/-internals/glimmer/lib/components/link-to.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import type Route from '@ember/routing/route';
import type { RouterState, RoutingService } from '@ember/routing/-internals';
import { isSimpleClick } from '@ember/-internals/views';
import { assert, debugFreeze, inspect, warn } from '@ember/debug';
import { getEngineParent } from '@ember/engine';
import EngineInstance from '@ember/engine/instance';
import { getEngineParent } from '@ember/engine/parent';
import type EngineInstance from '@ember/engine/instance';
import { flaggedInstrument } from '@ember/instrumentation';
import { action } from '@ember/object';
import { service } from '@ember/service';
Expand Down Expand Up @@ -494,13 +494,13 @@ class _LinkTo extends InternalComponent {
}

private get isEngine(): boolean {
let owner = this.owner;
return owner instanceof EngineInstance && getEngineParent(owner) !== undefined;
let owner = this.owner as EngineInstance;
return getEngineParent(owner) !== undefined;
}

private get engineMountPoint(): string | undefined {
let owner = this.owner;
return owner instanceof EngineInstance ? owner.mountPoint : undefined;
let owner = this.owner as EngineInstance;
return owner.mountPoint;
}

private classFor(state: 'active' | 'loading' | 'disabled'): string {
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/-internals/glimmer/lib/templates/input.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { precompileTemplate } from '@ember/template-compilation';
import { on } from '@ember/modifier';
import { on } from '@ember/modifier/on';
export default precompileTemplate(
`<input
{{!-- for compatibility --}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { precompileTemplate } from '@ember/template-compilation';
import { on } from '@ember/modifier';
import { on } from '@ember/modifier/on';

export default precompileTemplate(
`<a
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { precompileTemplate } from '@ember/template-compilation';
import { on } from '@ember/modifier';
import { on } from '@ember/modifier/on';

export default precompileTemplate(
`<textarea
Expand Down
3 changes: 0 additions & 3 deletions packages/@ember/-internals/glimmer/lib/utils/process-args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { CapturedNamedArguments } from '@glimmer/interfaces';
import type { Reference } from '@glimmer/reference';
import { isUpdatableRef, updateRef, valueForRef } from '@glimmer/reference';
import { assert } from '@ember/debug';
import { ARGS } from '../component-managers/curly';
import { ACTIONS } from '../helpers/action';

// ComponentArgs takes EvaluatedNamedArgs and converts them into the
Expand All @@ -13,8 +12,6 @@ export function processComponentArgs(namedArgs: CapturedNamedArguments) {
let attrs = Object.create(null);
let props = Object.create(null);

props[ARGS] = namedArgs;

for (let name in namedArgs) {
let ref = namedArgs[name];
assert('expected ref', ref);
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/-internals/glimmer/lib/utils/to-bool.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isHTMLSafe } from '@ember/-internals/glimmer';
import { isHTMLSafe } from './string';
import { get, tagForProperty } from '@ember/-internals/metal';
import { isArray } from '@ember/array';
import { isProxy } from '@ember/-internals/utils';
Expand Down
8 changes: 1 addition & 7 deletions packages/@ember/-internals/metal/lib/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@ interface ObservedObject {
_revalidate?: () => void;
}

export function objectAt<T>(array: T[] | EmberArray<T>, index: number): T | undefined {
if (Array.isArray(array)) {
return array[index];
} else {
return array.objectAt(index);
}
}
export { objectAt } from './object-at';

// Ideally, we'd use MutableArray.detect but for unknown reasons this causes
// the node tests to fail strangely.
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/-internals/metal/lib/chain-tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
updateTag,
validateTag,
} from '@glimmer/validator';
import { objectAt } from './array';
import { objectAt } from './object-at';
import { tagForProperty } from './tags';

export const CHAIN_PASS_THROUGH = new WeakSet();
Expand Down
9 changes: 9 additions & 0 deletions packages/@ember/-internals/metal/lib/object-at.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type EmberArray from '@ember/array';

export function objectAt<T>(array: T[] | EmberArray<T>, index: number): T | undefined {
if (Array.isArray(array)) {
return array[index];
} else {
return array.objectAt(index);
}
}
8 changes: 4 additions & 4 deletions packages/@ember/-internals/metal/lib/observer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ENV } from '@ember/-internals/environment';
import { peekMeta } from '@ember/-internals/meta';
import { schedule } from '@ember/runloop';
import type { schedule } from '@ember/runloop';
import { registerDestructor } from '@glimmer/destroyable';
import type { Tag } from '@glimmer/validator';
import { CURRENT_TAG, tagMetaFor, validateTag, valueForTag } from '@glimmer/validator';
Expand Down Expand Up @@ -187,7 +187,7 @@ export function revalidateObservers(target: object) {

let lastKnownRevision = 0;

export function flushAsyncObservers(shouldSchedule = true) {
export function flushAsyncObservers(_schedule: typeof schedule | false) {
let currentRevision = valueForTag(CURRENT_TAG);
if (lastKnownRevision === currentRevision) {
return;
Expand All @@ -213,8 +213,8 @@ export function flushAsyncObservers(shouldSchedule = true) {
}
};

if (shouldSchedule) {
schedule('actions', sendObserver);
if (_schedule) {
_schedule('actions', sendObserver);
} else {
sendObserver();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getOwner } from '@ember/-internals/owner';
import { assert } from '@ember/debug';
import { get, set } from '@ember/-internals/metal';
import EmberObject from '@ember/object';
import { getElementView } from '@ember/-internals/views';
import { getElementView } from './utils';
import ActionManager from './action_manager';
import type { BootEnvironment } from '@ember/-internals/glimmer/lib/views/outlet';
import type Component from '@ember/component';
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/array/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type { MethodNamesOf, MethodParams, MethodReturns } from '@ember/-interna
import type { ComputedPropertyCallback } from '@ember/-internals/metal';
import { isEmberArray, setEmberArray } from '@ember/array/-internals';

export { default as makeArray } from './lib/make-array';
export { default as makeArray } from './make';

export type EmberArrayLike<T> = EmberArray<T> | NativeArray<T>;

Expand Down
1 change: 1 addition & 0 deletions packages/@ember/array/make.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './lib/make-array';
1 change: 1 addition & 0 deletions packages/@ember/array/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
".": "./index.ts",
"./-internals": "./-internals.ts",
"./proxy": "./proxy.ts",
"./make": "./make.ts",
"./mutable": "./mutable.ts"
},
"dependencies": {
Expand Down
57 changes: 4 additions & 53 deletions packages/@ember/debug/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import _deprecate from './lib/deprecate';
import { isTesting } from './lib/testing';
import type { WarnFunc } from './lib/warn';
import _warn from './lib/warn';
import { assert, setAssert } from './lib/assert';

export { registerHandler as registerWarnHandler } from './lib/warn';
export {
Expand All @@ -27,10 +28,6 @@ export type DebugFunctionType =
| 'runInDebug'
| 'deprecateFunc';

export interface AssertFunc {
(desc: string, condition: unknown): asserts condition;
(desc: string): never;
}
export type DebugFunc = (message: string) => void;
export type DebugSealFunc = (obj: object) => void;
export type DebugFreezeFunc = (obj: object) => void;
Expand All @@ -43,7 +40,7 @@ export type DeprecateFuncFunc = (
) => Function;

export type GetDebugFunction = {
(type: 'assert'): AssertFunc;
(type: 'assert'): typeof assert;
(type: 'info'): InfoFunc;
(type: 'warn'): WarnFunc;
(type: 'debug'): DebugFunc;
Expand All @@ -55,7 +52,7 @@ export type GetDebugFunction = {
};

export type SetDebugFunction = {
(type: 'assert', func: AssertFunc): AssertFunc;
(type: 'assert', func: typeof assert): typeof assert;
(type: 'info', func: InfoFunc): InfoFunc;
(type: 'warn', func: WarnFunc): WarnFunc;
(type: 'debug', func: DebugFunc): DebugFunc;
Expand All @@ -71,7 +68,6 @@ const noop = () => {};

// SAFETY: these casts are just straight-up lies, but the point is that they do
// not do anything in production builds.
let assert: AssertFunc = noop as unknown as AssertFunc;
let info: InfoFunc = noop;
let warn: WarnFunc = noop;
let debug: DebugFunc = noop;
Expand All @@ -90,7 +86,7 @@ if (DEBUG) {
setDebugFunction = function (type: DebugFunctionType, callback: Function) {
switch (type) {
case 'assert':
return (assert = callback as AssertFunc);
return setAssert(callback as typeof assert);
case 'info':
return (info = callback as InfoFunc);
case 'warn':
Expand Down Expand Up @@ -139,51 +135,6 @@ if (DEBUG) {
*/

if (DEBUG) {
/**
Verify that a certain expectation is met, or throw a exception otherwise.
This is useful for communicating assumptions in the code to other human
readers as well as catching bugs that accidentally violates these
expectations.
Assertions are removed from production builds, so they can be freely added
for documentation and debugging purposes without worries of incuring any
performance penalty. However, because of that, they should not be used for
checks that could reasonably fail during normal usage. Furthermore, care
should be taken to avoid accidentally relying on side-effects produced from
evaluating the condition itself, since the code will not run in production.
```javascript
import { assert } from '@ember/debug';
// Test for truthiness
assert('Must pass a string', typeof str === 'string');
// Fail unconditionally
assert('This code path should never be run');
```
@method assert
@static
@for @ember/debug
@param {String} description Describes the expectation. This will become the
text of the Error thrown if the assertion fails.
@param {any} condition Must be truthy for the assertion to pass. If
falsy, an exception will be thrown.
@public
@since 1.0.0
*/
function assert(desc: string): never;
function assert(desc: string, test: unknown): asserts test;
// eslint-disable-next-line no-inner-declarations
function assert(desc: string, test?: unknown): asserts test {
if (!test) {
throw new Error(`Assertion Failed: ${desc}`);
}
}

setDebugFunction('assert', assert);

/**
Display a debug notice.
Expand Down
53 changes: 53 additions & 0 deletions packages/@ember/debug/lib/assert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { DEBUG } from '@glimmer/env';

export interface AssertFunc {
(desc: string, condition: unknown): asserts condition;
(desc: string): never;
}

export let assert: AssertFunc = (() => {}) as unknown as AssertFunc;

export function setAssert(implementation: typeof assert): typeof assert {
assert = implementation;
return implementation;
}

if (DEBUG) {
/**
Verify that a certain expectation is met, or throw a exception otherwise.
This is useful for communicating assumptions in the code to other human
readers as well as catching bugs that accidentally violates these
expectations.
Assertions are removed from production builds, so they can be freely added
for documentation and debugging purposes without worries of incuring any
performance penalty. However, because of that, they should not be used for
checks that could reasonably fail during normal usage. Furthermore, care
should be taken to avoid accidentally relying on side-effects produced from
evaluating the condition itself, since the code will not run in production.
```javascript
import { assert } from '@ember/debug';
// Test for truthiness
assert('Must pass a string', typeof str === 'string');
// Fail unconditionally
assert('This code path should never be run');
```
@method assert
@static
@for @ember/debug
@param {String} description Describes the expectation. This will become the
text of the Error thrown if the assertion fails.
@param {any} condition Must be truthy for the assertion to pass. If
falsy, an exception will be thrown.
@public
@since 1.0.0
*/
function assert(desc: string): never;
function assert(desc: string, test: unknown): asserts test;
// eslint-disable-next-line no-inner-declarations
function assert(desc: string, test?: unknown): asserts test {
if (!test) {
throw new Error(`Assertion Failed: ${desc}`);
}
}
setAssert(assert);
}
2 changes: 1 addition & 1 deletion packages/@ember/debug/lib/deprecate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ENV } from '@ember/-internals/environment';
import { DEBUG } from '@glimmer/env';

import { assert } from '../index';
import { assert } from './assert';
import type { HandlerCallback } from './handlers';
import { invoke, registerHandler as genericRegisterHandler } from './handlers';

Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/debug/lib/inspect.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { assert } from '@ember/debug';
import { assert } from './assert';
const { toString: objectToString } = Object.prototype;
const { toString: functionToString } = Function.prototype;
const { isArray } = Array;
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/debug/lib/warn.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DEBUG } from '@glimmer/env';

import { assert } from '../index';
import { assert } from './assert';
import type { HandlerCallback } from './handlers';
import { invoke, registerHandler as genericRegisterHandler } from './handlers';

Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/engine/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { getEngineParent, setEngineParent } from './lib/engine-parent';
export { getEngineParent, setEngineParent } from './parent';

import { canInvoke } from '@ember/-internals/utils';
import Controller from '@ember/controller';
Expand Down
8 changes: 3 additions & 5 deletions packages/@ember/engine/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { RSVP } from '@ember/-internals/runtime';
import { assert } from '@ember/debug';
import { Registry, privatize as P } from '@ember/-internals/container';
import { guidFor } from '@ember/-internals/utils';
import { ENGINE_PARENT, getEngineParent, setEngineParent } from './lib/engine-parent';
import { ENGINE_PARENT, getEngineParent, setEngineParent } from './parent';
import { ContainerProxyMixin, RegistryProxyMixin } from '@ember/-internals/runtime';
import type { InternalOwner } from '@ember/-internals/owner';
import type Owner from '@ember/-internals/owner';
import { type FullName, isFactory } from '@ember/-internals/owner';
import Engine from '@ember/engine';
import type Engine from '@ember/engine';
import type Application from '@ember/application';
import type { BootEnvironment } from '@ember/-internals/glimmer';
import type { SimpleElement } from '@simple-dom/interface';
Expand Down Expand Up @@ -199,16 +199,14 @@ class EngineInstance extends EmberObject.extend(RegistryProxyMixin, ContainerPro
@return {EngineInstance,Error}
*/
buildChildEngineInstance(name: string, options: EngineInstanceOptions = {}): EngineInstance {
let ChildEngine = this.lookup(`engine:${name}`);
let ChildEngine = this.lookup(`engine:${name}`) as Engine;

if (!ChildEngine) {
throw new Error(
`You attempted to mount the engine '${name}', but it is not registered with its parent.`
);
}

assert('expected an Engine', ChildEngine instanceof Engine);

let engineInstance = ChildEngine.buildInstance(options);

setEngineParent(engineInstance, this);
Expand Down
Loading

0 comments on commit 8687287

Please sign in to comment.