From 8bddebebc2df55625b1d1fe92332de3d2885752c Mon Sep 17 00:00:00 2001 From: Peter Wagenet Date: Mon, 29 Aug 2022 17:00:13 -0700 Subject: [PATCH 1/2] Convert packages/ember to TS --- .../-internals/environment/lib/context.ts | 2 +- .../@ember/-internals/error-handling/index.ts | 2 +- .../@ember/-internals/glimmer/lib/helper.ts | 58 +- .../helper/type-tests/invoke-helper.test.ts | 2 +- packages/ember/index.js | 619 --------------- packages/ember/index.ts | 710 ++++++++++++++++++ packages/ember/type-tests/ember.test.ts | 7 + .../lib/test-cases/rendering.ts | 3 +- .../lib/test-cases/router-non-application.ts | 3 +- .../test-cases/test-resolver-application.ts | 2 +- packages/{ember => loader/lib}/index.d.ts | 6 - 11 files changed, 757 insertions(+), 657 deletions(-) delete mode 100644 packages/ember/index.js create mode 100644 packages/ember/index.ts create mode 100644 packages/ember/type-tests/ember.test.ts rename packages/{ember => loader/lib}/index.d.ts (63%) diff --git a/packages/@ember/-internals/environment/lib/context.ts b/packages/@ember/-internals/environment/lib/context.ts index 928a543f9d4..a6e38c12103 100644 --- a/packages/@ember/-internals/environment/lib/context.ts +++ b/packages/@ember/-internals/environment/lib/context.ts @@ -23,7 +23,7 @@ export const context = (function ( }; })(global, global.Ember); -export function getLookup(): object { +export function getLookup(): Record { return context.lookup; } diff --git a/packages/@ember/-internals/error-handling/index.ts b/packages/@ember/-internals/error-handling/index.ts index 405322b7b96..466254e7160 100644 --- a/packages/@ember/-internals/error-handling/index.ts +++ b/packages/@ember/-internals/error-handling/index.ts @@ -10,7 +10,7 @@ export function getOnerror() { return onerror; } // Ember.onerror setter -export function setOnerror(handler: Function) { +export function setOnerror(handler: Function | undefined) { onerror = handler; } diff --git a/packages/@ember/-internals/glimmer/lib/helper.ts b/packages/@ember/-internals/glimmer/lib/helper.ts index 3d34d2c6ea3..a384566051d 100644 --- a/packages/@ember/-internals/glimmer/lib/helper.ts +++ b/packages/@ember/-internals/glimmer/lib/helper.ts @@ -44,6 +44,32 @@ export interface SimpleHelper> { compute: HelperFunction; } +/** + In many cases it is not necessary to use the full `Helper` class. + The `helper` method create pure-function helpers without instances. + For example: + + ```app/helpers/format-currency.js + import { helper } from '@ember/component/helper'; + + export default helper(function([cents], {currency}) { + return `${currency}${cents * 0.01}`; + }); + ``` + + @static + @param {Function} helper The helper function + @method helper + @for @ember/component/helper + @public + @since 1.13.0 +*/ +export function helper>( + helperFn: HelperFunction +): HelperFactory> { + return new Wrapper(helperFn); +} + /** Ember Helpers are functions that can compute values, and are used in templates. For example, this code calls a helper named `format-currency`: @@ -105,6 +131,12 @@ class Helper extends FrameworkObject { static isHelperFactory = true; static [IS_CLASSIC_HELPER] = true; + // `packages/ember/index.js` was setting `Helper.helper`. This seems like + // a bad idea and probably not something we want. We've moved that definition + // here, but it should definitely be reviewed and probably removed. + /** @deprecated */ + static helper = helper; + // SAFETY: this is initialized in `init`, rather than `constructor`. It is // safe to `declare` like this *if and only if* nothing uses the constructor // directly in this class, since nothing else can run before `init`. @@ -269,30 +301,4 @@ export const SIMPLE_CLASSIC_HELPER_MANAGER = new SimpleClassicHelperManager(); setHelperManager(() => SIMPLE_CLASSIC_HELPER_MANAGER, Wrapper.prototype); -/** - In many cases it is not necessary to use the full `Helper` class. - The `helper` method create pure-function helpers without instances. - For example: - - ```app/helpers/format-currency.js - import { helper } from '@ember/component/helper'; - - export default helper(function([cents], {currency}) { - return `${currency}${cents * 0.01}`; - }); - ``` - - @static - @param {Function} helper The helper function - @method helper - @for @ember/component/helper - @public - @since 1.13.0 -*/ -export function helper>( - helperFn: HelperFunction -): HelperFactory> { - return new Wrapper(helperFn); -} - export default Helper; diff --git a/packages/@ember/helper/type-tests/invoke-helper.test.ts b/packages/@ember/helper/type-tests/invoke-helper.test.ts index 9cec53e2729..ceb8ed895f4 100644 --- a/packages/@ember/helper/type-tests/invoke-helper.test.ts +++ b/packages/@ember/helper/type-tests/invoke-helper.test.ts @@ -1,4 +1,4 @@ -import Component from '@ember/-internals/glimmer/lib/component'; +import Component from '@ember/component'; import { getValue } from '@ember/-internals/metal'; import Helper from '@ember/component/helper'; import { invokeHelper } from '@ember/helper'; diff --git a/packages/ember/index.js b/packages/ember/index.js deleted file mode 100644 index 76febd1bef6..00000000000 --- a/packages/ember/index.js +++ /dev/null @@ -1,619 +0,0 @@ -import require, { has } from 'require'; - -import { getENV, getLookup, setLookup } from '@ember/-internals/environment'; -import * as utils from '@ember/-internals/utils'; -import { Registry, Container } from '@ember/-internals/container'; -import * as instrumentation from '@ember/instrumentation'; -import { meta } from '@ember/-internals/meta'; -import * as metal from '@ember/-internals/metal'; -import { FEATURES, isEnabled } from '@ember/canary-features'; -import * as EmberDebug from '@ember/debug'; -import { assert, captureRenderTree, deprecate } from '@ember/debug'; -import Backburner from 'backburner'; -import Controller, { inject as injectController, ControllerMixin } from '@ember/controller'; -import { - _getStrings, - _setStrings, - dasherize, - camelize, - capitalize, - classify, - decamelize, - loc, - underscore, - w, -} from '@ember/string'; -import Service, { service } from '@ember/service'; - -import EmberObject, { action, computed, observer } from '@ember/object'; -import { dependentKeyCompat } from '@ember/object/compat'; - -import { - RegistryProxyMixin, - ContainerProxyMixin, - _ProxyMixin, - RSVP, - Comparable, - ActionHandler, -} from '@ember/-internals/runtime'; -import { - Component, - componentCapabilities, - modifierCapabilities, - setComponentManager, - escapeExpression, - getTemplates, - Helper, - helper, - htmlSafe, - isHTMLSafe, - setTemplates, - template, - Input, - isSerializationFirstNode, -} from '@ember/-internals/glimmer'; -import VERSION from './version'; -import * as views from '@ember/-internals/views'; -import ContainerDebugAdapter from '@ember/debug/container-debug-adapter'; -import DataAdapter from '@ember/debug/data-adapter'; -import EmberError from '@ember/error'; -import { run } from '@ember/runloop'; -import { getOnerror, setOnerror } from '@ember/-internals/error-handling'; -import { getOwner, setOwner } from '@ember/-internals/owner'; -import EmberArray, { A, NativeArray, isArray } from '@ember/array'; -import MutableArray from '@ember/array/mutable'; -import ArrayProxy from '@ember/array/proxy'; -import Application, { onLoad, runLoadHooks } from '@ember/application'; -import ApplicationInstance from '@ember/application/instance'; -import Namespace from '@ember/application/namespace'; -import Engine from '@ember/engine'; -import EngineInstance from '@ember/engine/instance'; -import Enumerable from '@ember/enumerable'; -import MutableEnumerable from '@ember/enumerable/mutable'; -import CoreObject from '@ember/object/core'; -import Evented from '@ember/object/evented'; -import Mixin, { mixin } from '@ember/object/mixin'; -import Observable from '@ember/object/observable'; -import ObjectProxy from '@ember/object/proxy'; -import PromiseProxyMixin from '@ember/object/promise-proxy-mixin'; -import { assign } from '@ember/polyfills'; -import AutoLocation from '@ember/routing/auto-location'; -import HashLocation from '@ember/routing/hash-location'; -import HistoryLocation from '@ember/routing/history-location'; -import NoneLocation from '@ember/routing/none-location'; -import EmberLocation from '@ember/routing/location'; -import Route from '@ember/routing/route'; -import Router from '@ember/routing/router'; -import { - controllerFor, - generateController, - generateControllerFactory, - DSL as RouterDSL, -} from '@ember/routing/-internals'; -import { isNone, isBlank, isEmpty, isPresent, isEqual, typeOf, compare } from '@ember/utils'; - -import { - templateOnlyComponent, - invokeHelper, - hash, - array, - concat, - get, - on, - fn, -} from '@glimmer/runtime'; - -import { - helperCapabilities, - setModifierManager, - setComponentTemplate, - getComponentTemplate, - setHelperManager, -} from '@glimmer/manager'; - -import { - assertDestroyablesDestroyed, - associateDestroyableChild, - destroy, - enableDestroyableTracking, - isDestroying, - isDestroyed, - registerDestructor, - unregisterDestructor, -} from '@ember/destroyable'; - -// ****@ember/-internals/environment**** - -const Ember = {}; - -Ember.isNamespace = true; -Ember.toString = function () { - return 'Ember'; -}; - -Object.defineProperty(Ember, 'ENV', { - get: getENV, - enumerable: false, -}); - -Object.defineProperty(Ember, 'lookup', { - get: getLookup, - set: setLookup, - enumerable: false, -}); - -// ****@ember/application**** -Ember.getOwner = getOwner; -Ember.setOwner = setOwner; -Ember.Application = Application; -Ember.ApplicationInstance = ApplicationInstance; - -// ****@ember/engine**** -Ember.Engine = Engine; -Ember.EngineInstance = EngineInstance; - -// ****@ember/polyfills**** -Ember.assign = assign; - -// ****@ember/-internals/utils**** -Ember.generateGuid = utils.generateGuid; -Ember.GUID_KEY = utils.GUID_KEY; -Ember.guidFor = utils.guidFor; -Ember.inspect = utils.inspect; -Ember.makeArray = utils.makeArray; -Ember.canInvoke = utils.canInvoke; -Ember.wrap = utils.wrap; -Ember.uuid = utils.uuid; - -// ****@ember/-internals/container**** -Ember.Container = Container; -Ember.Registry = Registry; - -// ****@ember/debug**** -Ember.assert = EmberDebug.assert; -Ember.warn = EmberDebug.warn; -Ember.debug = EmberDebug.debug; -Ember.deprecate = EmberDebug.deprecate; -Ember.deprecateFunc = EmberDebug.deprecateFunc; -Ember.runInDebug = EmberDebug.runInDebug; - -// ****@ember/error**** -Ember.Error = EmberError; - -/** - @public - @class Ember.Debug -*/ -Ember.Debug = { - registerDeprecationHandler: EmberDebug.registerDeprecationHandler, - registerWarnHandler: EmberDebug.registerWarnHandler, - isComputed: metal.isComputed, -}; - -// ****@ember/instrumentation**** -Ember.instrument = instrumentation.instrument; -Ember.subscribe = instrumentation.subscribe; -Ember.Instrumentation = { - instrument: instrumentation.instrument, - subscribe: instrumentation.subscribe, - unsubscribe: instrumentation.unsubscribe, - reset: instrumentation.reset, -}; - -// ****@ember/runloop**** - -Ember.run = run; - -// ****@ember/-internals/metal**** - -// in globals builds -Ember.computed = computed; -Ember._descriptor = metal.nativeDescDecorator; -Ember._tracked = metal.tracked; -Ember.cacheFor = metal.getCachedValueFor; -Ember.ComputedProperty = metal.ComputedProperty; -Ember._setClassicDecorator = metal.setClassicDecorator; -Ember.meta = meta; -Ember.get = metal.get; -Ember._getPath = metal._getPath; -Ember.set = metal.set; -Ember.trySet = metal.trySet; -Ember.FEATURES = Object.assign({ isEnabled }, FEATURES); -Ember._Cache = utils.Cache; -Ember.on = metal.on; -Ember.addListener = metal.addListener; -Ember.removeListener = metal.removeListener; -Ember.sendEvent = metal.sendEvent; -Ember.hasListeners = metal.hasListeners; -Ember.isNone = isNone; -Ember.isEmpty = isEmpty; -Ember.isBlank = isBlank; -Ember.isPresent = isPresent; -Ember.notifyPropertyChange = metal.notifyPropertyChange; -Ember.beginPropertyChanges = metal.beginPropertyChanges; -Ember.endPropertyChanges = metal.endPropertyChanges; -Ember.changeProperties = metal.changeProperties; -Ember.platform = { - defineProperty: true, - hasPropertyAccessors: true, -}; -Ember.defineProperty = metal.defineProperty; -Ember.destroy = destroy; -Ember.libraries = metal.libraries; -Ember.getProperties = metal.getProperties; -Ember.setProperties = metal.setProperties; -Ember.expandProperties = metal.expandProperties; -Ember.addObserver = metal.addObserver; -Ember.removeObserver = metal.removeObserver; -Ember.observer = observer; -Ember.mixin = mixin; -Ember.Mixin = Mixin; - -Ember._createCache = metal.createCache; -Ember._cacheGetValue = metal.getValue; -Ember._cacheIsConst = metal.isConst; - -Ember._registerDestructor = registerDestructor; -Ember._unregisterDestructor = unregisterDestructor; -Ember._associateDestroyableChild = associateDestroyableChild; -Ember._assertDestroyablesDestroyed = assertDestroyablesDestroyed; -Ember._enableDestroyableTracking = enableDestroyableTracking; -Ember._isDestroying = isDestroying; -Ember._isDestroyed = isDestroyed; - -/** - A function may be assigned to `Ember.onerror` to be called when Ember - internals encounter an error. This is useful for specialized error handling - and reporting code. - - ```javascript - - Ember.onerror = function(error) { - const payload = { - stack: error.stack, - otherInformation: 'whatever app state you want to provide' - }; - - fetch('/report-error', { - method: 'POST', - body: JSON.stringify(payload) - }); - }; - ``` - - Internally, `Ember.onerror` is used as Backburner's error handler. - - @event onerror - @for Ember - @param {Exception} error the error object - @public -*/ -Object.defineProperty(Ember, 'onerror', { - get: getOnerror, - set: setOnerror, - enumerable: false, -}); - -Object.defineProperty(Ember, 'testing', { - get: EmberDebug.isTesting, - set: EmberDebug.setTesting, - enumerable: false, -}); - -Ember._Backburner = Backburner; - -// ****@ember/-internals/runtime**** -Ember.A = A; -Ember.String = { - loc, - w, - dasherize, - decamelize, - camelize, - classify, - underscore, - capitalize, -}; -Ember.Object = EmberObject; -Ember._RegistryProxyMixin = RegistryProxyMixin; -Ember._ContainerProxyMixin = ContainerProxyMixin; -Ember.compare = compare; -Ember.isEqual = isEqual; - -/** -@module ember -*/ - -/** - Namespace for injection helper methods. - - @class inject - @namespace Ember - @static - @public -*/ -Ember.inject = function inject() { - assert( - `Injected properties must be created through helpers, see '${Object.keys(inject) - .map((k) => `'inject.${k}'`) - .join(' or ')}'` - ); -}; -Ember.inject.service = service; -Ember.inject.controller = injectController; - -Ember.Array = EmberArray; -Ember.Comparable = Comparable; -Ember.Enumerable = Enumerable; -Ember.ArrayProxy = ArrayProxy; -Ember.ObjectProxy = ObjectProxy; -Ember.ActionHandler = ActionHandler; -Ember.CoreObject = CoreObject; -Ember.NativeArray = NativeArray; -Ember.MutableEnumerable = MutableEnumerable; -Ember.MutableArray = MutableArray; -Ember.Evented = Evented; -Ember.PromiseProxyMixin = PromiseProxyMixin; -Ember.Observable = Observable; -Ember.typeOf = typeOf; -Ember.isArray = isArray; -Ember.Object = EmberObject; -Ember.onLoad = onLoad; -Ember.runLoadHooks = runLoadHooks; -Ember.Controller = Controller; -Ember.ControllerMixin = ControllerMixin; -Ember.Service = Service; -Ember._ProxyMixin = _ProxyMixin; -Ember.RSVP = RSVP; -Ember.Namespace = Namespace; - -Ember._action = action; -Ember._dependentKeyCompat = dependentKeyCompat; - -/** - Defines the hash of localized strings for the current language. Used by - the `String.loc` helper. To localize, add string values to this - hash. - - @property STRINGS - @for Ember - @type Object - @private -*/ -Object.defineProperty(Ember, 'STRINGS', { - configurable: false, - get: _getStrings, - set: _setStrings, -}); - -/** - Whether searching on the global for new Namespace instances is enabled. - - This is only exported here as to not break any addons. Given the new - visit API, you will have issues if you treat this as a indicator of - booted. - - Internally this is only exposing a flag in Namespace. - - @property BOOTED - @for Ember - @type Boolean - @private -*/ -Object.defineProperty(Ember, 'BOOTED', { - configurable: false, - enumerable: false, - get: metal.isNamespaceSearchDisabled, - set: metal.setNamespaceSearchDisabled, -}); - -// ****@ember/-internals/glimmer**** -Ember.Component = Component; -Helper.helper = helper; -Ember.Helper = Helper; -Ember._setComponentManager = setComponentManager; -Ember._componentManagerCapabilities = componentCapabilities; -Ember._setModifierManager = setModifierManager; -Ember._modifierManagerCapabilities = modifierCapabilities; - -Ember._getComponentTemplate = getComponentTemplate; -Ember._setComponentTemplate = setComponentTemplate; -Ember._templateOnlyComponent = templateOnlyComponent; - -Ember._Input = Input; -Ember._hash = hash; -Ember._array = array; -Ember._concat = concat; -Ember._get = get; -Ember._on = on; -Ember._fn = fn; - -Ember._helperManagerCapabilities = helperCapabilities; -Ember._setHelperManager = setHelperManager; -Ember._invokeHelper = invokeHelper; -Ember._captureRenderTree = captureRenderTree; - -const deprecateImportFromString = function ( - name, - message = `Importing ${name} from '@ember/string' is deprecated. Please import ${name} from '@ember/template' instead.` -) { - // Disabling this deprecation due to unintended errors in 3.25 - // See https://github.com/emberjs/ember.js/issues/19393 fo more information. - deprecate(message, true, { - id: 'ember-string.htmlsafe-ishtmlsafe', - for: 'ember-source', - since: { - available: '3.25', - enabled: '3.25', - }, - until: '4.0.0', - url: 'https://deprecations.emberjs.com/v3.x/#toc_ember-string-htmlsafe-ishtmlsafe', - }); -}; -Object.defineProperty(Ember.String, 'htmlSafe', { - enumerable: true, - configurable: true, - get() { - deprecateImportFromString('htmlSafe'); - return htmlSafe; - }, -}); -Object.defineProperty(Ember.String, 'isHTMLSafe', { - enumerable: true, - configurable: true, - get() { - deprecateImportFromString('isHTMLSafe'); - return isHTMLSafe; - }, -}); - -/** - Global hash of shared templates. This will automatically be populated - by the build tools so that you can store your Handlebars templates in - separate files that get loaded into JavaScript at buildtime. - - @property TEMPLATES - @for Ember - @type Object - @private -*/ -Object.defineProperty(Ember, 'TEMPLATES', { - get: getTemplates, - set: setTemplates, - configurable: false, - enumerable: false, -}); - -/** - The semantic version - - @property VERSION - @type String - @public -*/ -Ember.VERSION = VERSION; - -Ember.ViewUtils = { - isSimpleClick: views.isSimpleClick, - getElementView: views.getElementView, - getViewElement: views.getViewElement, - getViewBounds: views.getViewBounds, - getViewClientRects: views.getViewClientRects, - getViewBoundingClientRect: views.getViewBoundingClientRect, - getRootViews: views.getRootViews, - getChildViews: views.getChildViews, - isSerializationFirstNode: isSerializationFirstNode, -}; -Ember.ComponentLookup = views.ComponentLookup; -Ember.EventDispatcher = views.EventDispatcher; - -Ember.Location = EmberLocation; -Ember.AutoLocation = AutoLocation; -Ember.HashLocation = HashLocation; -Ember.HistoryLocation = HistoryLocation; -Ember.NoneLocation = NoneLocation; -Ember.controllerFor = controllerFor; -Ember.generateControllerFactory = generateControllerFactory; -Ember.generateController = generateController; -Ember.RouterDSL = RouterDSL; -Ember.Router = Router; -Ember.Route = Route; - -runLoadHooks('Ember.Application', Application); - -Ember.DataAdapter = DataAdapter; -Ember.ContainerDebugAdapter = ContainerDebugAdapter; - -let EmberHandlebars = { - template, - Utils: { - escapeExpression, - }, -}; - -let EmberHTMLBars = { - template, -}; - -function defineEmberTemplateCompilerLazyLoad(key) { - Object.defineProperty(Ember, key, { - configurable: true, - enumerable: true, - get() { - if (has('ember-template-compiler')) { - let templateCompiler = require('ember-template-compiler'); - - EmberHTMLBars.precompile = EmberHandlebars.precompile = templateCompiler.precompile; - EmberHTMLBars.compile = EmberHandlebars.compile = templateCompiler.compile; - - Object.defineProperty(Ember, 'HTMLBars', { - configurable: true, - writable: true, - enumerable: true, - value: EmberHTMLBars, - }); - Object.defineProperty(Ember, 'Handlebars', { - configurable: true, - writable: true, - enumerable: true, - value: EmberHandlebars, - }); - } - - return key === 'Handlebars' ? EmberHandlebars : EmberHTMLBars; - }, - }); -} - -defineEmberTemplateCompilerLazyLoad('HTMLBars'); -defineEmberTemplateCompilerLazyLoad('Handlebars'); - -// do this to ensure that Ember.Test is defined properly on the global -// if it is present. -function defineEmberTestingLazyLoad(key) { - Object.defineProperty(Ember, key, { - configurable: true, - enumerable: true, - get() { - if (has('ember-testing')) { - let testing = require('ember-testing'); - - let { Test, Adapter, QUnitAdapter, setupForTesting } = testing; - Test.Adapter = Adapter; - Test.QUnitAdapter = QUnitAdapter; - - Object.defineProperty(Ember, 'Test', { - configurable: true, - writable: true, - enumerable: true, - value: Test, - }); - Object.defineProperty(Ember, 'setupForTesting', { - configurable: true, - writable: true, - enumerable: true, - value: setupForTesting, - }); - - return key === 'Test' ? Test : setupForTesting; - } - - return undefined; - }, - }); -} - -defineEmberTestingLazyLoad('Test'); -defineEmberTestingLazyLoad('setupForTesting'); - -runLoadHooks('Ember'); - -Ember.__loader = { - require, - // eslint-disable-next-line no-undef - define, - // eslint-disable-next-line no-undef - registry: typeof requirejs !== 'undefined' ? requirejs.entries : require.entries, -}; - -export default Ember; diff --git a/packages/ember/index.ts b/packages/ember/index.ts new file mode 100644 index 00000000000..8490d1ed748 --- /dev/null +++ b/packages/ember/index.ts @@ -0,0 +1,710 @@ +/** +@module ember +*/ + +import require, { has } from 'require'; + +import { getENV, getLookup, setLookup } from '@ember/-internals/environment'; +import * as utils from '@ember/-internals/utils'; +import { Registry, Container } from '@ember/-internals/container'; +import * as instrumentation from '@ember/instrumentation'; +import { meta } from '@ember/-internals/meta'; +import * as metal from '@ember/-internals/metal'; +import { FEATURES, isEnabled } from '@ember/canary-features'; +import * as EmberDebug from '@ember/debug'; +import { assert, captureRenderTree } from '@ember/debug'; +import Backburner from 'backburner'; +import Controller, { inject as injectController, ControllerMixin } from '@ember/controller'; +import { + _getStrings, + _setStrings, + dasherize, + camelize, + capitalize, + classify, + decamelize, + underscore, + w, +} from '@ember/string'; +import Service, { service } from '@ember/service'; + +import EmberObject, { + action, + computed, + defineProperty, + notifyPropertyChange, + observer, + get, + getProperties, + set, + setProperties, + trySet, +} from '@ember/object'; +import { cacheFor } from '@ember/object/-internals'; +import { dependentKeyCompat } from '@ember/object/compat'; +import ComputedProperty, { expandProperties } from '@ember/object/computed'; +import { addListener, removeListener, sendEvent } from '@ember/object/events'; + +import { + RegistryProxyMixin, + ContainerProxyMixin, + _ProxyMixin, + RSVP, + Comparable, + ActionHandler, +} from '@ember/-internals/runtime'; +import { + componentCapabilities, + modifierCapabilities, + setComponentManager, + escapeExpression, + getTemplates, + setTemplates, + template, + isSerializationFirstNode, +} from '@ember/-internals/glimmer'; +import VERSION from './version'; +import * as views from '@ember/-internals/views'; +import ContainerDebugAdapter from '@ember/debug/container-debug-adapter'; +import DataAdapter from '@ember/debug/data-adapter'; +import EmberError from '@ember/error'; +import { run } from '@ember/runloop'; +import { getOnerror, setOnerror } from '@ember/-internals/error-handling'; +import EmberArray, { A, NativeArray, isArray } from '@ember/array'; +import MutableArray from '@ember/array/mutable'; +import ArrayProxy from '@ember/array/proxy'; +import Application, { getOwner, setOwner, onLoad, runLoadHooks } from '@ember/application'; +import ApplicationInstance from '@ember/application/instance'; +import Namespace from '@ember/application/namespace'; +import Component, { Input } from '@ember/component'; +import Helper from '@ember/component/helper'; +import Engine from '@ember/engine'; +import EngineInstance from '@ember/engine/instance'; +import Enumerable from '@ember/enumerable'; +import MutableEnumerable from '@ember/enumerable/mutable'; +import CoreObject from '@ember/object/core'; +import Evented, { on } from '@ember/object/evented'; +import Mixin, { mixin } from '@ember/object/mixin'; +import Observable from '@ember/object/observable'; +import { addObserver, removeObserver } from '@ember/object/observers'; +import ObjectProxy from '@ember/object/proxy'; +import PromiseProxyMixin from '@ember/object/promise-proxy-mixin'; +import { assign } from '@ember/polyfills'; +import AutoLocation from '@ember/routing/auto-location'; +import HashLocation from '@ember/routing/hash-location'; +import HistoryLocation from '@ember/routing/history-location'; +import NoneLocation from '@ember/routing/none-location'; +import EmberLocation from '@ember/routing/location'; +import Route from '@ember/routing/route'; +import Router from '@ember/routing/router'; +import { + controllerFor, + generateController, + generateControllerFactory, + DSL as RouterDSL, +} from '@ember/routing/-internals'; +import { isNone, isBlank, isEmpty, isPresent, isEqual, typeOf, compare } from '@ember/utils'; + +import * as glimmerRuntime from '@glimmer/runtime'; + +import { + helperCapabilities, + setModifierManager, + setComponentTemplate, + getComponentTemplate, + setHelperManager, +} from '@glimmer/manager'; + +import { + assertDestroyablesDestroyed, + associateDestroyableChild, + destroy, + enableDestroyableTracking, + isDestroying, + isDestroyed, + registerDestructor, + unregisterDestructor, +} from '@ember/destroyable'; + +import type * as EmberTemplateCompiler from 'ember-template-compiler'; +import type { precompile, compile } from 'ember-template-compiler'; +import type * as EmberTesting from 'ember-testing'; + +/** + Namespace for injection helper methods. + + @class inject + @namespace Ember + @static + @public +*/ +function inject() { + assert( + `Injected properties must be created through helpers, see '${Object.keys(inject) + .map((k) => `'inject.${k}'`) + .join(' or ')}'` + ); +} +// ****@ember/controller**** +inject.controller = injectController; +// ****@ember/service**** +inject.service = service; + +const PartialEmber = { + isNamespace: true, + + toString() { + return 'Ember'; + }, + + // ****@ember/-internals/container**** + Container, + Registry, + + // ****@ember/-internals/glimmer**** + // Partially re-exported from @glimmer/manager + _setComponentManager: setComponentManager, + _componentManagerCapabilities: componentCapabilities, + _modifierManagerCapabilities: modifierCapabilities, + + // ****@ember/-internals/meta**** + meta, + + // ****@ember/-internals/metal**** + _createCache: metal.createCache, // Also @glimmer/validator + _cacheGetValue: metal.getValue, // Also @glimmer/validator + _cacheIsConst: metal.isConst, // Also @glimmer/validator + _descriptor: metal.nativeDescDecorator, + _getPath: metal._getPath, + _setClassicDecorator: metal.setClassicDecorator, + _tracked: metal.tracked, // Also exported from @glimmer/tracking + beginPropertyChanges: metal.beginPropertyChanges, + changeProperties: metal.changeProperties, + endPropertyChanges: metal.endPropertyChanges, + hasListeners: metal.hasListeners, + libraries: metal.libraries, + + // ****@ember/-internals/runtime**** + _ContainerProxyMixin: ContainerProxyMixin, + _ProxyMixin, + _RegistryProxyMixin: RegistryProxyMixin, + ActionHandler, + Comparable, + RSVP, // Also from 'rsvp' directly. + + // ****@ember/-internals/view**** + ComponentLookup: views.ComponentLookup, + EventDispatcher: views.EventDispatcher, + + // ****@ember/-internals/utils**** + _Cache: utils.Cache, + GUID_KEY: utils.GUID_KEY, + canInvoke: utils.canInvoke, + inspect: utils.inspect, + generateGuid: utils.generateGuid, + guidFor: utils.guidFor, + makeArray: utils.makeArray, + uuid: utils.uuid, + wrap: utils.wrap, + + // ****@ember/application**** + getOwner, + onLoad, + runLoadHooks, + setOwner, + Application, + + // ****@ember/application/instance**** + ApplicationInstance, + + // ****@ember/application/namespace**** + Namespace, + + // ****@ember/array**** + A, + Array: EmberArray, + NativeArray, + isArray, + + // ****@ember/array/mutable**** + MutableArray, + + // ****@ember/array/proxy**** + ArrayProxy, + + // ****@ember/canary-features**** + Features: { isEnabled, ...FEATURES }, + + // ****@ember/component**** + _Input: Input, + Component, + + // ****@ember/component/helper**** + Helper, + + // ****@ember/controller**** + Controller, + ControllerMixin, + + // ****@ember/debug**** + _captureRenderTree: captureRenderTree, + assert: EmberDebug.assert, + warn: EmberDebug.warn, + debug: EmberDebug.debug, + deprecate: EmberDebug.deprecate, + deprecateFunc: EmberDebug.deprecateFunc, + runInDebug: EmberDebug.runInDebug, + + Debug: { + registerDeprecationHandler: EmberDebug.registerDeprecationHandler, + registerWarnHandler: EmberDebug.registerWarnHandler, + // ****@ember/-internals/metal**** + isComputed: metal.isComputed, + }, + + // ****@ember/debug/container-debug-adapter**** + ContainerDebugAdapter, + + // ****@ember/debug/data-adapter**** + DataAdapter, + + // ****@ember/destroyable**** + _assertDestroyablesDestroyed: assertDestroyablesDestroyed, + _associateDestroyableChild: associateDestroyableChild, + _enableDestroyableTracking: enableDestroyableTracking, + _isDestroying: isDestroying, + _isDestroyed: isDestroyed, + _registerDestructor: registerDestructor, + _unregisterDestructor: unregisterDestructor, + destroy, + + // ****@ember/engine**** + Engine, + + // ****@ember/engine/instance**** + EngineInstance, + + // ****@ember/enumerable**** + Enumerable, + + // ****@ember/enumerable/mutable**** + MutableEnumerable, + + // ****@ember/error**** + Error: EmberError, + + // ****@ember/instrumentation**** + instrument: instrumentation.instrument, + subscribe: instrumentation.subscribe, + + Instrumentation: { + instrument: instrumentation.instrument, + subscribe: instrumentation.subscribe, + unsubscribe: instrumentation.unsubscribe, + reset: instrumentation.reset, + }, + + // ****@ember/object**** + Object: EmberObject, + _action: action, + computed, + defineProperty, + get, + getProperties, + notifyPropertyChange, + observer, + set, + trySet, + setProperties, + + // ****@ember/object/-internals**** + cacheFor, + + // ****@ember/object/compat**** + _dependentKeyCompat: dependentKeyCompat, + + // ****@ember/object/computed**** + ComputedProperty, + expandProperties, + + // ****@ember/object/core**** + CoreObject, + + // ****@ember/object/evented**** + Evented, + on, + + // ****@ember/object/events**** + addListener, + removeListener, + sendEvent, + + // ****@ember/object/mixin**** + Mixin, + mixin, + + // ****@ember/object/observable**** + Observable, + + // ****@ember/object/observers**** + addObserver, + removeObserver, + + // ****@ember/object/promise-proxy-mixin**** + PromiseProxyMixin, + + // ****@ember/object/proxy**** + ObjectProxy, + + // ****@ember/polyfills**** + assign, + + // ****@ember/routing/-internals**** + RouterDSL, + controllerFor, + generateController, + generateControllerFactory, + + // ****@ember/routing/auto-location**** + AutoLocation, + + // ****@ember/routing/hash-location**** + HashLocation, + + // ****@ember/routing/history-location**** + HistoryLocation, + + // ****@ember/routing/location**** + Location: EmberLocation, + + // ****@ember/routing/none-location**** + NoneLocation, + + // ****@ember/routing/route**** + Route, + + // ****@ember/routing/router**** + Router, + + // ****@ember/runloop**** + run, + + // ****@ember/service**** + Service, + + // ****@ember/string**** + String: { + camelize, + capitalize, + classify, + decamelize, + dasherize, + underscore, + w, + }, + + // ****@ember/utils**** + compare, + isBlank, + isEmpty, + isEqual, + isNone, + isPresent, + typeOf, + + // ****@ember/version**** + /** + The semantic version + + @property VERSION + @type String + @public + */ + VERSION, + + ViewUtils: { + // ****@ember/-internals/views**** + getChildViews: views.getChildViews, + getElementView: views.getElementView, + getRootViews: views.getRootViews, + getViewBounds: views.getViewBounds, + getViewBoundingClientRect: views.getViewBoundingClientRect, + getViewClientRects: views.getViewClientRects, + getViewElement: views.getViewElement, + isSimpleClick: views.isSimpleClick, + + // ****@ember/-internals/glimmer**** + isSerializationFirstNode, + }, + + // ****@glimmer/manager**** + _getComponentTemplate: getComponentTemplate, + _helperManagerCapabilities: helperCapabilities, + _setComponentTemplate: setComponentTemplate, + _setHelperManager: setHelperManager, + _setModifierManager: setModifierManager, + + // ****@glimmer/runtime**** + _templateOnlyComponent: glimmerRuntime.templateOnlyComponent, + _invokeHelper: glimmerRuntime.invokeHelper, + _hash: glimmerRuntime.hash, + _array: glimmerRuntime.array, + _concat: glimmerRuntime.concat, + _get: glimmerRuntime.get, + _on: glimmerRuntime.on, + _fn: glimmerRuntime.fn, + + // Backburner + _Backburner: Backburner, + + // ****@ember/controller, @ember/service**** + inject, + + // Non-imported + platform: { + defineProperty: true, + hasPropertyAccessors: true, + }, + + __loader: { + require, + define, + // @ts-expect-error These properties don't appear as being defined + registry: typeof requirejs !== 'undefined' ? requirejs.entries : require.entries, + }, + + get ENV() { + return getENV(); + }, + + /** + A function may be assigned to `Ember.onerror` to be called when Ember + internals encounter an error. This is useful for specialized error handling + and reporting code. + + ```javascript + + Ember.onerror = function(error) { + const payload = { + stack: error.stack, + otherInformation: 'whatever app state you want to provide' + }; + + fetch('/report-error', { + method: 'POST', + body: JSON.stringify(payload) + }); + }; + ``` + + Internally, `Ember.onerror` is used as Backburner's error handler. + + @event onerror + @for Ember + @param {Exception} error the error object + @public + */ + // ****@ember/-internals/error-handling**** + get onerror(): Function | undefined { + return getOnerror(); + }, + + set onerror(handler: Function | undefined) { + setOnerror(handler); + }, + + // ****@ember/debug**** + get testing(): boolean { + return EmberDebug.isTesting(); + }, + + set testing(value: boolean) { + EmberDebug.setTesting(value); + }, + + // ****@ember/-internals/environment**** + get lookup() { + return getLookup(); + }, + + set lookup(value) { + setLookup(value); + }, + + /** + Defines the hash of localized strings for the current language. Used by + the `String.loc` helper. To localize, add string values to this + hash. + + @property STRINGS + @for Ember + @type Object + @private + */ + // ****@ember/string**** + get STRINGS() { + return _getStrings(); + }, + + set STRINGS(value) { + _setStrings(value); + }, + + /** + Whether searching on the global for new Namespace instances is enabled. + + This is only exported here as to not break any addons. Given the new + visit API, you will have issues if you treat this as a indicator of + booted. + + Internally this is only exposing a flag in Namespace. + + @property BOOTED + @for Ember + @type Boolean + @private + */ + get BOOTED() { + return metal.isNamespaceSearchDisabled(); + }, + + set BOOTED(value) { + metal.setNamespaceSearchDisabled(value); + }, + + /** + Global hash of shared templates. This will automatically be populated + by the build tools so that you can store your Handlebars templates in + separate files that get loaded into JavaScript at buildtime. + + @property TEMPLATES + @for Ember + @type Object + @private + */ + get TEMPLATES() { + return getTemplates(); + }, + + set TEMPLATES(value) { + setTemplates(value); + }, +} as const; + +interface EmberHandlebars { + template: typeof template; + Utils: { + escapeExpression: typeof escapeExpression; + }; + compile?: typeof compile; + precompile?: typeof precompile; +} + +interface EmberHTMLBars { + template: typeof template; + compile?: typeof compile; + precompile?: typeof precompile; +} + +type PartialEmber = typeof PartialEmber; +interface Ember extends PartialEmber { + HTMLBars: EmberHTMLBars; + Handlebars: EmberHandlebars; + Test?: typeof EmberTesting['Test'] & { + Adapter: typeof EmberTesting['Adapter']; + QUnitAdapter: typeof EmberTesting['QUnitAdapter']; + }; + setupForTesting?: typeof EmberTesting['setupForTesting']; +} +const Ember = PartialEmber as Ember; + +runLoadHooks('Ember.Application', Application); + +let EmberHandlebars: EmberHandlebars = { + template, + Utils: { + escapeExpression, + }, +}; + +let EmberHTMLBars: EmberHTMLBars = { + template, +}; + +function defineEmberTemplateCompilerLazyLoad(key: 'HTMLBars' | 'Handlebars') { + Object.defineProperty(Ember, key, { + configurable: true, + enumerable: true, + get() { + if (has('ember-template-compiler')) { + let templateCompiler = require('ember-template-compiler') as typeof EmberTemplateCompiler; + + EmberHTMLBars.precompile = EmberHandlebars.precompile = templateCompiler.precompile; + EmberHTMLBars.compile = EmberHandlebars.compile = templateCompiler.compile; + + Object.defineProperty(Ember, 'HTMLBars', { + configurable: true, + writable: true, + enumerable: true, + value: EmberHTMLBars, + }); + Object.defineProperty(Ember, 'Handlebars', { + configurable: true, + writable: true, + enumerable: true, + value: EmberHandlebars, + }); + } + + return key === 'Handlebars' ? EmberHandlebars : EmberHTMLBars; + }, + }); +} + +defineEmberTemplateCompilerLazyLoad('HTMLBars'); +defineEmberTemplateCompilerLazyLoad('Handlebars'); + +// do this to ensure that Ember.Test is defined properly on the global +// if it is present. +function defineEmberTestingLazyLoad(key: 'Test' | 'setupForTesting') { + Object.defineProperty(Ember, key, { + configurable: true, + enumerable: true, + get() { + if (has('ember-testing')) { + let testing = require('ember-testing') as typeof EmberTesting; + + let { Test, Adapter, QUnitAdapter, setupForTesting } = testing; + // @ts-expect-error We should not do this + Test.Adapter = Adapter; + // @ts-expect-error We should not do this + Test.QUnitAdapter = QUnitAdapter; + + Object.defineProperty(Ember, 'Test', { + configurable: true, + writable: true, + enumerable: true, + value: Test, + }); + Object.defineProperty(Ember, 'setupForTesting', { + configurable: true, + writable: true, + enumerable: true, + value: setupForTesting, + }); + + return key === 'Test' ? Test : setupForTesting; + } + + return undefined; + }, + }); +} + +defineEmberTestingLazyLoad('Test'); +defineEmberTestingLazyLoad('setupForTesting'); + +// @ts-expect-error Per types, runLoadHooks requires a second parameter. Should we loosen types? +runLoadHooks('Ember'); + +export default Ember; diff --git a/packages/ember/type-tests/ember.test.ts b/packages/ember/type-tests/ember.test.ts new file mode 100644 index 00000000000..2eb5a03ea6d --- /dev/null +++ b/packages/ember/type-tests/ember.test.ts @@ -0,0 +1,7 @@ +import Ember from 'ember'; + +import { expectTypeOf } from 'expect-type'; + +expectTypeOf(Ember.onerror).toEqualTypeOf(); + +expectTypeOf(Ember.HTMLBars).toMatchTypeOf(); diff --git a/packages/internal-test-helpers/lib/test-cases/rendering.ts b/packages/internal-test-helpers/lib/test-cases/rendering.ts index d3a10c10c90..8ae48049978 100644 --- a/packages/internal-test-helpers/lib/test-cases/rendering.ts +++ b/packages/internal-test-helpers/lib/test-cases/rendering.ts @@ -2,7 +2,8 @@ import type { EmberPrecompileOptions } from 'ember-template-compiler'; import { compile } from 'ember-template-compiler'; import { EventDispatcher } from '@ember/-internals/views'; import type { Renderer } from '@ember/-internals/glimmer'; -import { helper, Helper, Component, _resetRenderers } from '@ember/-internals/glimmer'; +import Component from '@ember/component'; +import { helper, Helper, _resetRenderers } from '@ember/-internals/glimmer'; import type Resolver from '../test-resolver'; import { ModuleBasedResolver } from '../test-resolver'; diff --git a/packages/internal-test-helpers/lib/test-cases/router-non-application.ts b/packages/internal-test-helpers/lib/test-cases/router-non-application.ts index a895e9732fd..c8eaff9372d 100644 --- a/packages/internal-test-helpers/lib/test-cases/router-non-application.ts +++ b/packages/internal-test-helpers/lib/test-cases/router-non-application.ts @@ -2,7 +2,8 @@ import type { EmberPrecompileOptions } from 'ember-template-compiler'; import { compile } from 'ember-template-compiler'; import { EventDispatcher } from '@ember/-internals/views'; import type { Renderer } from '@ember/-internals/glimmer'; -import { Component, _resetRenderers } from '@ember/-internals/glimmer'; +import Component from '@ember/component'; +import { _resetRenderers } from '@ember/-internals/glimmer'; import type Resolver from '../test-resolver'; import { ModuleBasedResolver } from '../test-resolver'; diff --git a/packages/internal-test-helpers/lib/test-cases/test-resolver-application.ts b/packages/internal-test-helpers/lib/test-cases/test-resolver-application.ts index a068d92ac32..2489826d32c 100644 --- a/packages/internal-test-helpers/lib/test-cases/test-resolver-application.ts +++ b/packages/internal-test-helpers/lib/test-cases/test-resolver-application.ts @@ -1,7 +1,7 @@ import AbstractApplicationTestCase from './abstract-application'; import type Resolver from '../test-resolver'; import { ModuleBasedResolver } from '../test-resolver'; -import { Component } from '@ember/-internals/glimmer'; +import Component from '@ember/component'; import type { Factory } from '@ember/-internals/owner'; export default abstract class TestResolverApplicationTestCase extends AbstractApplicationTestCase { diff --git a/packages/ember/index.d.ts b/packages/loader/lib/index.d.ts similarity index 63% rename from packages/ember/index.d.ts rename to packages/loader/lib/index.d.ts index 6544926d4c2..58443c7f54c 100644 --- a/packages/ember/index.d.ts +++ b/packages/loader/lib/index.d.ts @@ -1,9 +1,3 @@ -declare module 'ember' { - const Ember: any; - - export default Ember; -} - declare module 'require' { export function has(path: string): boolean; export default function require(path: string): any; From 9cf853d619cf8072e61388713dbe498c623690cf Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 28 Oct 2022 09:15:49 -0600 Subject: [PATCH 2/2] Revert to defineProperty for get/set on Ember namespace While we might be able to make the change over to using native getters and setters in a future PR, we want this change to be exactly and only a type conversion, exactly preserving the previous behavior. Switching back to using `Object.defineProperty()` for the getters and setters defined on the `Ember` namespace preserves the previous behavior, which our tests correctly caught for us! --- packages/@ember/-internals/glimmer/index.ts | 1 + .../glimmer/lib/template_registry.ts | 2 +- packages/ember/index.ts | 203 ++++++++++++------ 3 files changed, 137 insertions(+), 69 deletions(-) diff --git a/packages/@ember/-internals/glimmer/index.ts b/packages/@ember/-internals/glimmer/index.ts index 01f7e07067b..2149bb8d49b 100644 --- a/packages/@ember/-internals/glimmer/index.ts +++ b/packages/@ember/-internals/glimmer/index.ts @@ -459,6 +459,7 @@ export { hasTemplate, getTemplates, setTemplates, + TemplatesRegistry, } from './lib/template_registry'; export { setupEngineRegistry, setupApplicationRegistry } from './lib/setup-registry'; export { DOMChanges, NodeDOMTreeConstruction, DOMTreeConstruction } from './lib/dom'; diff --git a/packages/@ember/-internals/glimmer/lib/template_registry.ts b/packages/@ember/-internals/glimmer/lib/template_registry.ts index ba4ffd4f88c..2ccb77d1117 100644 --- a/packages/@ember/-internals/glimmer/lib/template_registry.ts +++ b/packages/@ember/-internals/glimmer/lib/template_registry.ts @@ -3,7 +3,7 @@ import type { TemplateFactory } from '@glimmer/interfaces'; // STATE within a module is frowned upon, this exists // to support Ember.TEMPLATES but shield ember internals from this legacy // global API. -interface TemplatesRegistry { +export interface TemplatesRegistry { [name: string]: TemplateFactory; } let TEMPLATES: TemplatesRegistry = {}; diff --git a/packages/ember/index.ts b/packages/ember/index.ts index 8490d1ed748..7050912263a 100644 --- a/packages/ember/index.ts +++ b/packages/ember/index.ts @@ -12,7 +12,7 @@ import { meta } from '@ember/-internals/meta'; import * as metal from '@ember/-internals/metal'; import { FEATURES, isEnabled } from '@ember/canary-features'; import * as EmberDebug from '@ember/debug'; -import { assert, captureRenderTree } from '@ember/debug'; +import { assert, captureRenderTree, deprecate } from '@ember/debug'; import Backburner from 'backburner'; import Controller, { inject as injectController, ControllerMixin } from '@ember/controller'; import { @@ -59,9 +59,12 @@ import { setComponentManager, escapeExpression, getTemplates, + htmlSafe, + isHTMLSafe, setTemplates, template, isSerializationFirstNode, + type TemplatesRegistry, } from '@ember/-internals/glimmer'; import VERSION from './version'; import * as views from '@ember/-internals/views'; @@ -233,7 +236,7 @@ const PartialEmber = { ArrayProxy, // ****@ember/canary-features**** - Features: { isEnabled, ...FEATURES }, + FEATURES: { isEnabled, ...FEATURES }, // ****@ember/component**** _Input: Input, @@ -472,10 +475,30 @@ const PartialEmber = { // @ts-expect-error These properties don't appear as being defined registry: typeof requirejs !== 'undefined' ? requirejs.entries : require.entries, }, +} as const; - get ENV() { - return getENV(); - }, +interface EmberHandlebars { + template: typeof template; + Utils: { + escapeExpression: typeof escapeExpression; + }; + compile?: typeof compile; + precompile?: typeof precompile; +} + +interface EmberHTMLBars { + template: typeof template; + compile?: typeof compile; + precompile?: typeof precompile; +} + +type PartialEmber = typeof PartialEmber; +interface Ember extends PartialEmber { + get ENV(): object; + + // ****@ember/-internals/environment**** + get lookup(): Record; + set lookup(value: Record); /** A function may be assigned to `Ember.onerror` to be called when Ember @@ -505,31 +528,11 @@ const PartialEmber = { @public */ // ****@ember/-internals/error-handling**** - get onerror(): Function | undefined { - return getOnerror(); - }, + get onerror(): Function | undefined; + set onerror(handler: Function | undefined); - set onerror(handler: Function | undefined) { - setOnerror(handler); - }, - - // ****@ember/debug**** - get testing(): boolean { - return EmberDebug.isTesting(); - }, - - set testing(value: boolean) { - EmberDebug.setTesting(value); - }, - - // ****@ember/-internals/environment**** - get lookup() { - return getLookup(); - }, - - set lookup(value) { - setLookup(value); - }, + get testing(): boolean; + set testing(value: boolean); /** Defines the hash of localized strings for the current language. Used by @@ -542,13 +545,10 @@ const PartialEmber = { @private */ // ****@ember/string**** - get STRINGS() { - return _getStrings(); - }, - - set STRINGS(value) { - _setStrings(value); - }, + get STRINGS(): { + [key: string]: string; + }; + set STRINGS(value: { [key: string]: string }); /** Whether searching on the global for new Namespace instances is enabled. @@ -564,13 +564,8 @@ const PartialEmber = { @type Boolean @private */ - get BOOTED() { - return metal.isNamespaceSearchDisabled(); - }, - - set BOOTED(value) { - metal.setNamespaceSearchDisabled(value); - }, + get BOOTED(): boolean; + set BOOTED(flag: boolean); /** Global hash of shared templates. This will automatically be populated @@ -582,32 +577,9 @@ const PartialEmber = { @type Object @private */ - get TEMPLATES() { - return getTemplates(); - }, + get TEMPLATES(): TemplatesRegistry; + set TEMPLATES(registry: TemplatesRegistry); - set TEMPLATES(value) { - setTemplates(value); - }, -} as const; - -interface EmberHandlebars { - template: typeof template; - Utils: { - escapeExpression: typeof escapeExpression; - }; - compile?: typeof compile; - precompile?: typeof precompile; -} - -interface EmberHTMLBars { - template: typeof template; - compile?: typeof compile; - precompile?: typeof precompile; -} - -type PartialEmber = typeof PartialEmber; -interface Ember extends PartialEmber { HTMLBars: EmberHTMLBars; Handlebars: EmberHandlebars; Test?: typeof EmberTesting['Test'] & { @@ -618,6 +590,101 @@ interface Ember extends PartialEmber { } const Ember = PartialEmber as Ember; +Object.defineProperty(Ember, 'ENV', { + get: getENV, + enumerable: false, +}); + +Object.defineProperty(Ember, 'lookup', { + get: getLookup, + set: setLookup, + enumerable: false, +}); + +Object.defineProperty(Ember, 'onerror', { + get: getOnerror, + set: setOnerror, + enumerable: false, +}); + +Object.defineProperty(Ember, 'testing', { + get: EmberDebug.isTesting, + set: EmberDebug.setTesting, + enumerable: false, +}); + +Object.defineProperty(Ember, 'STRINGS', { + configurable: false, + get: _getStrings, + set: _setStrings, +}); + +Object.defineProperty(Ember, 'BOOTED', { + configurable: false, + enumerable: false, + get: metal.isNamespaceSearchDisabled, + set: metal.setNamespaceSearchDisabled, +}); + +Object.defineProperty(Ember, 'TEMPLATES', { + get: getTemplates, + set: setTemplates, + configurable: false, + enumerable: false, +}); + +const deprecateImportFromString = function ( + name: string, + message = `Importing ${name} from '@ember/string' is deprecated. Please import ${name} from '@ember/template' instead.` +) { + // Disabling this deprecation due to unintended errors in 3.25 + // See https://github.com/emberjs/ember.js/issues/19393 fo more information. + deprecate(message, true, { + id: 'ember-string.htmlsafe-ishtmlsafe', + for: 'ember-source', + since: { + available: '3.25', + enabled: '3.25', + }, + until: '4.0.0', + url: 'https://deprecations.emberjs.com/v3.x/#toc_ember-string-htmlsafe-ishtmlsafe', + }); +}; +// NOTE: these are expressly *not* in the public API, because they were +// deprecated and removed. TODO: remove them after we land the TS conversion, +// and after confirming doing so is safe -- the state of the `@ember/string` +// conversion remains confused. +Object.defineProperty(Ember.String, 'htmlSafe', { + enumerable: true, + configurable: true, + get() { + deprecateImportFromString('htmlSafe'); + return htmlSafe; + }, +}); +Object.defineProperty(Ember.String, 'isHTMLSafe', { + enumerable: true, + configurable: true, + get() { + deprecateImportFromString('isHTMLSafe'); + return isHTMLSafe; + }, +}); + +Object.defineProperty(Ember, 'TEMPLATES', { + get: getTemplates, + set: setTemplates, + configurable: false, + enumerable: false, +}); + +// ****@ember/debug**** +Object.defineProperty(Ember, 'testing', { + get: EmberDebug.isTesting, + set: EmberDebug.setTesting, + enumerable: false, +}); + runLoadHooks('Ember.Application', Application); let EmberHandlebars: EmberHandlebars = {