ember-source
Version:
A JavaScript framework for creating ambitious web applications
1,285 lines (1,162 loc) • 1.83 MB
JavaScript
/*!
* @overview Ember - JavaScript Application Framework
* @copyright Copyright 2011 Tilde Inc. and contributors
* Portions Copyright 2006-2011 Strobe Inc.
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
* @license Licensed under MIT license
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
* @version 6.1.0
*/
/* eslint-disable no-var */
/* globals global globalThis self */
/* eslint-disable-next-line no-unused-vars */
var define, require;
(function () {
var globalObj =
typeof globalThis !== 'undefined'
? globalThis
: typeof self !== 'undefined'
? self
: typeof window !== 'undefined'
? window
: typeof global !== 'undefined'
? global
: null;
if (globalObj === null) {
throw new Error('unable to locate global object');
}
if (typeof globalObj.define === 'function' && typeof globalObj.require === 'function') {
define = globalObj.define;
require = globalObj.require;
return;
}
var registry = Object.create(null);
var seen = Object.create(null);
function missingModule(name, referrerName) {
if (referrerName) {
throw new Error('Could not find module ' + name + ' required by: ' + referrerName);
} else {
throw new Error('Could not find module ' + name);
}
}
function internalRequire(_name, referrerName) {
var name = _name;
var mod = registry[name];
if (!mod) {
name = name + '/index';
mod = registry[name];
}
var exports = seen[name];
if (exports !== undefined) {
return exports;
}
exports = seen[name] = {};
if (!mod) {
missingModule(_name, referrerName);
}
var deps = mod.deps;
var callback = mod.callback;
var reified = new Array(deps.length);
for (var i = 0; i < deps.length; i++) {
if (deps[i] === 'exports') {
reified[i] = exports;
} else if (deps[i] === 'require') {
reified[i] = require;
} else {
reified[i] = require(deps[i], name);
}
}
var result = callback.apply(this, reified);
if (!deps.includes('exports') || result !== undefined) {
exports = seen[name] = result;
}
return exports;
}
require = function (name) {
return internalRequire(name, null);
};
define = function (name, deps, callback) {
registry[name] = { deps: deps, callback: callback };
};
// setup `require` module
require['default'] = require;
require.has = function registryHas(moduleName) {
return Boolean(registry[moduleName]) || Boolean(registry[moduleName + '/index']);
};
require._eak_seen = require.entries = registry;
})();
(function () {
'use strict';
function d(name, mod) {
Object.defineProperty(mod, '__esModule', { value: true });
define(name, [], () => mod);
}
// check if window exists and actually is the global
const hasDOM = typeof self === 'object' && self !== null && self.Object === Object && typeof Window !== 'undefined' && self.constructor === Window && typeof document === 'object' && document !== null && self.document === document && typeof location === 'object' && location !== null && self.location === location && typeof history === 'object' && history !== null && self.history === history && typeof navigator === 'object' && navigator !== null && self.navigator === navigator && typeof navigator.userAgent === 'string';
const window$1 = hasDOM ? self : null;
const location$1 = hasDOM ? self.location : null;
const history$1 = hasDOM ? self.history : null;
const userAgent = hasDOM ? self.navigator.userAgent : 'Lynx (textmode)';
const isChrome = hasDOM ? typeof chrome === 'object' && !(typeof opera === 'object') : false;
const isFirefox = hasDOM ? /Firefox|FxiOS/.test(userAgent) : false;
const emberinternalsBrowserEnvironmentIndex = /*#__PURE__*/Object.defineProperty({
__proto__: null,
hasDOM,
history: history$1,
isChrome,
isFirefox,
location: location$1,
userAgent,
window: window$1
}, Symbol.toStringTag, { value: 'Module' });
/**
Strongly hint runtimes to intern the provided string.
When do I need to use this function?
For the most part, never. Pre-mature optimization is bad, and often the
runtime does exactly what you need it to, and more often the trade-off isn't
worth it.
Why?
Runtimes store strings in at least 2 different representations:
Ropes and Symbols (interned strings). The Rope provides a memory efficient
data-structure for strings created from concatenation or some other string
manipulation like splitting.
Unfortunately checking equality of different ropes can be quite costly as
runtimes must resort to clever string comparison algorithms. These
algorithms typically cost in proportion to the length of the string.
Luckily, this is where the Symbols (interned strings) shine. As Symbols are
unique by their string content, equality checks can be done by pointer
comparison.
How do I know if my string is a rope or symbol?
Typically (warning general sweeping statement, but truthy in runtimes at
present) static strings created as part of the JS source are interned.
Strings often used for comparisons can be interned at runtime if some
criteria are met. One of these criteria can be the size of the entire rope.
For example, in chrome 38 a rope longer then 12 characters will not
intern, nor will segments of that rope.
Some numbers: http://jsperf.com/eval-vs-keys/8
Known Trick™
@private
@return {String} interned version of the provided string
*/
function intern$1(str) {
let obj = Object.create(null);
obj[str] = 1;
for (let key in obj) {
if (key === str) {
return key;
}
}
return str;
}
/**
Returns whether Type(value) is Object.
Useful for checking whether a value is a valid WeakMap key.
Refs: https://tc39.github.io/ecma262/#sec-typeof-operator-runtime-semantics-evaluation
https://tc39.github.io/ecma262/#sec-weakmap.prototype.set
@private
@function isObject
*/
function isObject$1(value) {
return value !== null && (typeof value === 'object' || typeof value === 'function');
}
/**
@module @ember/object
*/
/**
@private
@return {Number} the uuid
*/
let _uuid$1 = 0;
/**
Generates a universally unique identifier. This method
is used internally by Ember for assisting with
the generation of GUID's and other unique identifiers.
@public
@return {Number} [description]
*/
function uuid$1() {
return ++_uuid$1;
}
/**
Prefix used for guids through out Ember.
@private
@property GUID_PREFIX
@for Ember
@type String
@final
*/
const GUID_PREFIX = 'ember';
// Used for guid generation...
const OBJECT_GUIDS = new WeakMap();
const NON_OBJECT_GUIDS = new Map();
/**
A unique key used to assign guids and other private metadata to objects.
If you inspect an object in your browser debugger you will often see these.
They can be safely ignored.
On browsers that support it, these properties are added with enumeration
disabled so they won't show up when you iterate over your properties.
@private
@property GUID_KEY
@for Ember
@type String
@final
*/
const GUID_KEY = intern$1(`__ember${Date.now()}`);
/**
Generates a new guid, optionally saving the guid to the object that you
pass in. You will rarely need to use this method. Instead you should
call `guidFor(obj)`, which return an existing guid if available.
@private
@method generateGuid
@static
@for @ember/object/internals
@param {Object} [obj] Object the guid will be used for. If passed in, the guid will
be saved on the object and reused whenever you pass the same object
again.
If no object is passed, just generate a new guid.
@param {String} [prefix] Prefix to place in front of the guid. Useful when you want to
separate the guid into separate namespaces.
@return {String} the guid
*/
function generateGuid(obj, prefix = GUID_PREFIX) {
let guid = prefix + uuid$1().toString();
if (isObject$1(obj)) {
OBJECT_GUIDS.set(obj, guid);
}
return guid;
}
/**
Returns a unique id for the object. If the object does not yet have a guid,
one will be assigned to it. You can call this on any object,
`EmberObject`-based or not.
You can also use this method on DOM Element objects.
@public
@static
@method guidFor
@for @ember/object/internals
@param {Object} obj any object, string, number, Element, or primitive
@return {String} the unique guid for this instance.
*/
function guidFor(value) {
let guid;
if (isObject$1(value)) {
guid = OBJECT_GUIDS.get(value);
if (guid === undefined) {
guid = `${GUID_PREFIX}${uuid$1()}`;
OBJECT_GUIDS.set(value, guid);
}
} else {
guid = NON_OBJECT_GUIDS.get(value);
if (guid === undefined) {
let type = typeof value;
if (type === 'string') {
guid = `st${uuid$1()}`;
} else if (type === 'number') {
guid = `nu${uuid$1()}`;
} else if (type === 'symbol') {
guid = `sy${uuid$1()}`;
} else {
guid = `(${value})`;
}
NON_OBJECT_GUIDS.set(value, guid);
}
}
return guid;
}
const GENERATED_SYMBOLS = [];
function isInternalSymbol(possibleSymbol) {
return GENERATED_SYMBOLS.indexOf(possibleSymbol) !== -1;
}
// Some legacy symbols still need to be enumerable for a variety of reasons.
// This code exists for that, and as a fallback in IE11. In general, prefer
// `symbol` below when creating a new symbol.
function enumerableSymbol(debugName) {
// TODO: Investigate using platform symbols, but we do not
// want to require non-enumerability for this API, which
// would introduce a large cost.
let id = GUID_KEY + Math.floor(Math.random() * Date.now()).toString();
let symbol = intern$1(`__${debugName}${id}__`);
return symbol;
}
const symbol = Symbol;
// the delete is meant to hint at runtimes that this object should remain in
// dictionary mode. This is clearly a runtime specific hack, but currently it
// appears worthwhile in some usecases. Please note, these deletes do increase
// the cost of creation dramatically over a plain Object.create. And as this
// only makes sense for long-lived dictionaries that aren't instantiated often.
function makeDictionary(parent) {
let dict = Object.create(parent);
dict['_dict'] = null;
delete dict['_dict'];
return dict;
}
let getDebugName;
const HAS_SUPER_PATTERN = /\.(_super|call\(this|apply\(this)/;
const fnToString = Function.prototype.toString;
const checkHasSuper = (() => {
let sourceAvailable = fnToString.call(function () {
return this;
}).indexOf('return this') > -1;
if (sourceAvailable) {
return function checkHasSuper(func) {
return HAS_SUPER_PATTERN.test(fnToString.call(func));
};
}
return function checkHasSuper() {
return true;
};
})();
const HAS_SUPER_MAP = new WeakMap();
const ROOT = Object.freeze(function () {});
HAS_SUPER_MAP.set(ROOT, false);
function hasSuper(func) {
let hasSuper = HAS_SUPER_MAP.get(func);
if (hasSuper === undefined) {
hasSuper = checkHasSuper(func);
HAS_SUPER_MAP.set(func, hasSuper);
}
return hasSuper;
}
class ObserverListenerMeta {
listeners = undefined;
observers = undefined;
}
const OBSERVERS_LISTENERS_MAP = new WeakMap();
function createObserverListenerMetaFor(fn) {
let meta = OBSERVERS_LISTENERS_MAP.get(fn);
if (meta === undefined) {
meta = new ObserverListenerMeta();
OBSERVERS_LISTENERS_MAP.set(fn, meta);
}
return meta;
}
function observerListenerMetaFor(fn) {
return OBSERVERS_LISTENERS_MAP.get(fn);
}
function setObservers(func, observers) {
let meta = createObserverListenerMetaFor(func);
meta.observers = observers;
}
function setListeners(func, listeners) {
let meta = createObserverListenerMetaFor(func);
meta.listeners = listeners;
}
const IS_WRAPPED_FUNCTION_SET = new WeakSet();
/**
Wraps the passed function so that `this._super` will point to the superFunc
when the function is invoked. This is the primitive we use to implement
calls to super.
@private
@method wrap
@for Ember
@param {Function} func The function to call
@param {Function} superFunc The super function.
@return {Function} wrapped function.
*/
function wrap$1(func, superFunc) {
if (!hasSuper(func)) {
return func;
}
// ensure an unwrapped super that calls _super is wrapped with a terminal _super
if (!IS_WRAPPED_FUNCTION_SET.has(superFunc) && hasSuper(superFunc)) {
return _wrap(func, _wrap(superFunc, ROOT));
}
return _wrap(func, superFunc);
}
function _wrap(func, superFunc) {
function superWrapper() {
let orig = this._super;
this._super = superFunc;
let ret = func.apply(this, arguments);
this._super = orig;
return ret;
}
IS_WRAPPED_FUNCTION_SET.add(superWrapper);
let meta = OBSERVERS_LISTENERS_MAP.get(func);
if (meta !== undefined) {
OBSERVERS_LISTENERS_MAP.set(superWrapper, meta);
}
return superWrapper;
}
function lookupDescriptor(obj, keyName) {
let current = obj;
do {
let descriptor = Object.getOwnPropertyDescriptor(current, keyName);
if (descriptor !== undefined) {
return descriptor;
}
current = Object.getPrototypeOf(current);
} while (current !== null);
return null;
}
/**
Checks to see if the `methodName` exists on the `obj`.
```javascript
let foo = { bar: function() { return 'bar'; }, baz: null };
Ember.canInvoke(foo, 'bar'); // true
Ember.canInvoke(foo, 'baz'); // false
Ember.canInvoke(foo, 'bat'); // false
```
@method canInvoke
@for Ember
@param {Object} obj The object to check for the method
@param {String} methodName The method name to check for
@return {Boolean}
@private
*/
function canInvoke(obj, methodName) {
return obj != null && typeof obj[methodName] === 'function';
}
/**
@module @ember/utils
*/
const NAMES = new WeakMap();
function setName(obj, name) {
if (isObject$1(obj)) NAMES.set(obj, name);
}
function getName(obj) {
return NAMES.get(obj);
}
const objectToString$1 = Object.prototype.toString;
function isNone$1(obj) {
return obj === null || obj === undefined;
}
/*
A `toString` util function that supports objects without a `toString`
method, e.g. an object created with `Object.create(null)`.
*/
function toString$1(obj) {
if (typeof obj === 'string') {
return obj;
}
if (null === obj) return 'null';
if (undefined === obj) return 'undefined';
if (Array.isArray(obj)) {
// Reimplement Array.prototype.join according to spec (22.1.3.13)
// Changing ToString(element) with this safe version of ToString.
let r = '';
for (let k = 0; k < obj.length; k++) {
if (k > 0) {
r += ',';
}
if (!isNone$1(obj[k])) {
r += toString$1(obj[k]);
}
}
return r;
}
if (typeof obj.toString === 'function') {
return obj.toString();
}
return objectToString$1.call(obj);
}
const PROXIES = new WeakSet();
function isProxy(value) {
if (isObject$1(value)) {
return PROXIES.has(value);
}
return false;
}
function setProxy(object) {
if (isObject$1(object)) {
PROXIES.add(object);
}
}
class Cache {
size = 0;
misses = 0;
hits = 0;
constructor(limit, func, store = new Map()) {
this.limit = limit;
this.func = func;
this.store = store;
}
get(key) {
if (this.store.has(key)) {
this.hits++;
// SAFETY: we know the value is present because `.has(key)` was `true`.
return this.store.get(key);
} else {
this.misses++;
return this.set(key, this.func(key));
}
}
set(key, value) {
if (this.limit > this.size) {
this.size++;
this.store.set(key, value);
}
return value;
}
purge() {
this.store.clear();
this.size = 0;
this.hits = 0;
this.misses = 0;
}
}
/* globals window, self */
// from lodash to catch fake globals
function checkGlobal(value) {
return value && value.Object === Object ? value : undefined;
}
// element ids can ruin global miss checks
function checkElementIdShadowing(value) {
return value && value.nodeType === undefined ? value : undefined;
}
// export real global
const global$1 = checkGlobal(checkElementIdShadowing(typeof global === 'object' && global)) || checkGlobal(typeof self === 'object' && self) || checkGlobal(typeof window === 'object' && window) || typeof mainContext !== 'undefined' && mainContext ||
// set before strict mode in Ember loader/wrapper
new Function('return this')(); // eval outside of strict mode
// legacy imports/exports/lookup stuff (should we keep this??)
const context$1 = function (global, Ember) {
return Ember === undefined ? {
imports: global,
exports: global,
lookup: global
} : {
// import jQuery
imports: Ember.imports || global,
// export Ember
exports: Ember.exports || global,
// search for Namespaces
lookup: Ember.lookup || global
};
}(global$1, global$1.Ember);
function getLookup() {
return context$1.lookup;
}
function setLookup(value) {
context$1.lookup = value;
}
/**
The hash of environment variables used to control various configuration
settings. To specify your own or override default settings, add the
desired properties to a global hash named `EmberENV` (or `ENV` for
backwards compatibility with earlier versions of Ember). The `EmberENV`
hash must be created before loading Ember.
@class EmberENV
@type Object
@public
*/
const ENV = {
ENABLE_OPTIONAL_FEATURES: false,
/**
Determines whether Ember should add to `Array`
native object prototypes, a few extra methods in order to provide a more
friendly API.
The behavior from setting this option to `true` was deprecated in Ember 5.10.
@property EXTEND_PROTOTYPES
@type Boolean
@default true
@for EmberENV
@private
@deprecated in v5.10
*/
EXTEND_PROTOTYPES: {
Array: false
},
/**
The `LOG_STACKTRACE_ON_DEPRECATION` property, when true, tells Ember to log
a full stack trace during deprecation warnings.
@property LOG_STACKTRACE_ON_DEPRECATION
@type Boolean
@default true
@for EmberENV
@public
*/
LOG_STACKTRACE_ON_DEPRECATION: true,
/**
The `LOG_VERSION` property, when true, tells Ember to log versions of all
dependent libraries in use.
@property LOG_VERSION
@type Boolean
@default true
@for EmberENV
@public
*/
LOG_VERSION: true,
RAISE_ON_DEPRECATION: false,
STRUCTURED_PROFILE: false,
/**
Whether to perform extra bookkeeping needed to make the `captureRenderTree`
API work.
This has to be set before the ember JavaScript code is evaluated. This is
usually done by setting `window.EmberENV = { _DEBUG_RENDER_TREE: true };`
before the "vendor" `<script>` tag in `index.html`.
Setting the flag after Ember is already loaded will not work correctly. It
may appear to work somewhat, but fundamentally broken.
This is not intended to be set directly. Ember Inspector will enable the
flag on behalf of the user as needed.
This flag is always on in development mode.
The flag is off by default in production mode, due to the cost associated
with the the bookkeeping work.
The expected flow is that Ember Inspector will ask the user to refresh the
page after enabling the feature. It could also offer a feature where the
user add some domains to the "always on" list. In either case, Ember
Inspector will inject the code on the page to set the flag if needed.
@property _DEBUG_RENDER_TREE
@for EmberENV
@type Boolean
@default false
@private
*/
_DEBUG_RENDER_TREE: false /* DEBUG */,
/**
Whether to force all deprecations to be enabled. This is used internally by
Ember to enable deprecations in tests. It is not intended to be set in
projects.
@property _ALL_DEPRECATIONS_ENABLED
@for EmberENV
@type Boolean
@default false
@private
*/
_ALL_DEPRECATIONS_ENABLED: false,
/**
Override the version of ember-source used to determine when deprecations "break".
This is used internally by Ember to test with deprecated features "removed".
This is never intended to be set by projects.
@property _OVERRIDE_DEPRECATION_VERSION
@for EmberENV
@type string | null
@default null
@private
*/
_OVERRIDE_DEPRECATION_VERSION: null,
/**
Whether the app defaults to using async observers.
This is not intended to be set directly, as the implementation may change in
the future. Use `@ember/optional-features` instead.
@property _DEFAULT_ASYNC_OBSERVERS
@for EmberENV
@type Boolean
@default false
@private
*/
_DEFAULT_ASYNC_OBSERVERS: false,
/**
Whether the app still has default record-loading behavior in the model
hook from RFC https://rfcs.emberjs.com/id/0774-implicit-record-route-loading
This will also remove the default store property from the route.
This is not intended to be set directly, as the implementation may change in
the future. Use `@ember/optional-features` instead.
@property _NO_IMPLICIT_ROUTE_MODEL
@for EmberENV
@type Boolean
@default false
@private
*/
_NO_IMPLICIT_ROUTE_MODEL: false,
/**
Controls the maximum number of scheduled rerenders without "settling". In general,
applications should not need to modify this environment variable, but please
open an issue so that we can determine if a better default value is needed.
@property _RERENDER_LOOP_LIMIT
@for EmberENV
@type number
@default 1000
@private
*/
_RERENDER_LOOP_LIMIT: 1000,
EMBER_LOAD_HOOKS: {},
FEATURES: {}
};
(EmberENV => {
if (typeof EmberENV !== 'object' || EmberENV === null) return;
for (let flag in EmberENV) {
if (!Object.prototype.hasOwnProperty.call(EmberENV, flag) || flag === 'EXTEND_PROTOTYPES' || flag === 'EMBER_LOAD_HOOKS') continue;
let defaultValue = ENV[flag];
if (defaultValue === true) {
ENV[flag] = EmberENV[flag] !== false;
} else if (defaultValue === false) {
ENV[flag] = EmberENV[flag] === true;
} else {
ENV[flag] = EmberENV[flag];
}
}
// TODO: Remove in Ember 6.5. This setting code for EXTEND_PROTOTYPES
// should stay for at least an LTS cycle so that users get the explicit
// deprecation exception when it breaks in >= 6.0.0.
let {
EXTEND_PROTOTYPES
} = EmberENV;
if (EXTEND_PROTOTYPES !== undefined) {
if (typeof EXTEND_PROTOTYPES === 'object' && EXTEND_PROTOTYPES !== null) {
ENV.EXTEND_PROTOTYPES.Array = EXTEND_PROTOTYPES.Array !== false;
} else {
ENV.EXTEND_PROTOTYPES.Array = EXTEND_PROTOTYPES !== false;
}
}
// TODO this does not seem to be used by anything,
// can we remove it? do we need to deprecate it?
let {
EMBER_LOAD_HOOKS
} = EmberENV;
if (typeof EMBER_LOAD_HOOKS === 'object' && EMBER_LOAD_HOOKS !== null) {
for (let hookName in EMBER_LOAD_HOOKS) {
if (!Object.prototype.hasOwnProperty.call(EMBER_LOAD_HOOKS, hookName)) continue;
let hooks = EMBER_LOAD_HOOKS[hookName];
if (Array.isArray(hooks)) {
ENV.EMBER_LOAD_HOOKS[hookName] = hooks.filter(hook => typeof hook === 'function');
}
}
}
let {
FEATURES
} = EmberENV;
if (typeof FEATURES === 'object' && FEATURES !== null) {
for (let feature in FEATURES) {
if (!Object.prototype.hasOwnProperty.call(FEATURES, feature)) continue;
ENV.FEATURES[feature] = FEATURES[feature] === true;
}
}
})(global$1.EmberENV);
function getENV() {
return ENV;
}
const emberinternalsEnvironmentIndex = /*#__PURE__*/Object.defineProperty({
__proto__: null,
ENV,
context: context$1,
getENV,
getLookup,
global: global$1,
setLookup
}, Symbol.toStringTag, { value: 'Module' });
let assert$1 = () => {};
let HANDLERS = {};
let registerHandler$2 = function registerHandler(_type, _callback) {};
let invoke = () => {};
const emberDebugLibHandlers = /*#__PURE__*/Object.defineProperty({
__proto__: null,
HANDLERS,
invoke,
registerHandler: registerHandler$2
}, Symbol.toStringTag, { value: 'Module' });
// This is a "global", but instead of declaring it as `declare global`, which
// will expose it to all other modules, declare it *locally* (and don't export
// it) so that it has the desired "private global" semantics -- however odd that
// particular notion is.
/**
@module @ember/debug
@public
*/
/**
Allows for runtime registration of handler functions that override the default deprecation behavior.
Deprecations are invoked by calls to [@ember/debug/deprecate](/ember/release/classes/@ember%2Fdebug/methods/deprecate?anchor=deprecate).
The following example demonstrates its usage by registering a handler that throws an error if the
message contains the word "should", otherwise defers to the default handler.
```javascript
import { registerDeprecationHandler } from '@ember/debug';
registerDeprecationHandler((message, options, next) => {
if (message.indexOf('should') !== -1) {
throw new Error(`Deprecation message with should: ${message}`);
} else {
// defer to whatever handler was registered before this one
next(message, options);
}
});
```
The handler function takes the following arguments:
<ul>
<li> <code>message</code> - The message received from the deprecation call.</li>
<li> <code>options</code> - An object passed in with the deprecation call containing additional information including:</li>
<ul>
<li> <code>id</code> - An id of the deprecation in the form of <code>package-name.specific-deprecation</code>.</li>
<li> <code>until</code> - The Ember version number the feature and deprecation will be removed in.</li>
</ul>
<li> <code>next</code> - A function that calls into the previously registered handler.</li>
</ul>
@public
@static
@method registerDeprecationHandler
@for @ember/debug
@param handler {Function} A function to handle deprecation calls.
@since 2.1.0
*/
let registerHandler$1 = () => {};
let missingOptionsDeprecation$1;
let missingOptionsIdDeprecation$1;
let missingOptionDeprecation = () => '';
let deprecate$3 = () => {};
const emberDebugLibDeprecate = /*#__PURE__*/Object.defineProperty({
__proto__: null,
default: deprecate$3,
missingOptionDeprecation,
missingOptionsDeprecation: missingOptionsDeprecation$1,
missingOptionsIdDeprecation: missingOptionsIdDeprecation$1,
registerHandler: registerHandler$1
}, Symbol.toStringTag, { value: 'Module' });
let testing = false;
function isTesting() {
return testing;
}
function setTesting(value) {
testing = Boolean(value);
}
const emberDebugLibTesting = /*#__PURE__*/Object.defineProperty({
__proto__: null,
isTesting,
setTesting
}, Symbol.toStringTag, { value: 'Module' });
let registerHandler = () => {};
let warn$1 = () => {};
let missingOptionsDeprecation;
let missingOptionsIdDeprecation;
const emberDebugLibWarn = /*#__PURE__*/Object.defineProperty({
__proto__: null,
default: warn$1,
missingOptionsDeprecation,
missingOptionsIdDeprecation,
registerHandler
}, Symbol.toStringTag, { value: 'Module' });
const {
toString: objectToString
} = Object.prototype;
const {
toString: functionToString
} = Function.prototype;
const {
isArray: isArray$4
} = Array;
const {
keys: objectKeys
} = Object;
const {
stringify: stringify$1
} = JSON;
const LIST_LIMIT = 100;
const DEPTH_LIMIT = 4;
const SAFE_KEY = /^[\w$]+$/;
/**
@module @ember/debug
*/
/**
Convenience method to inspect an object. This method will attempt to
convert the object into a useful string description.
It is a pretty simple implementation. If you want something more robust,
use something like JSDump: https://github.com/NV/jsDump
@method inspect
@static
@param {Object} obj The object you want to inspect.
@return {String} A description of the object
@since 1.4.0
@private
*/
function inspect(obj) {
// detect Node util.inspect call inspect(depth: number, opts: object)
if (typeof obj === 'number' && arguments.length === 2) {
return this;
}
return inspectValue(obj, 0);
}
function inspectValue(value, depth, seen) {
let valueIsArray = false;
switch (typeof value) {
case 'undefined':
return 'undefined';
case 'object':
if (value === null) return 'null';
if (isArray$4(value)) {
valueIsArray = true;
break;
}
// is toString Object.prototype.toString or undefined then traverse
if (value.toString === objectToString || value.toString === undefined) {
break;
}
// custom toString
return value.toString();
case 'function':
return value.toString === functionToString ? value.name ? `[Function:${value.name}]` : `[Function]` : value.toString();
case 'string':
return stringify$1(value);
case 'symbol':
case 'boolean':
case 'number':
default:
return value.toString();
}
if (seen === undefined) {
seen = new WeakSet();
} else {
if (seen.has(value)) return `[Circular]`;
}
seen.add(value);
return valueIsArray ? inspectArray(value, depth + 1, seen) : inspectObject(value, depth + 1, seen);
}
function inspectKey(key) {
return SAFE_KEY.test(key) ? key : stringify$1(key);
}
function inspectObject(obj, depth, seen) {
if (depth > DEPTH_LIMIT) {
return '[Object]';
}
let s = '{';
let keys = objectKeys(obj);
for (let i = 0; i < keys.length; i++) {
s += i === 0 ? ' ' : ', ';
if (i >= LIST_LIMIT) {
s += `... ${keys.length - LIST_LIMIT} more keys`;
break;
}
let key = keys[i];
s += `${inspectKey(String(key))}: ${inspectValue(obj[key], depth, seen)}`;
}
s += ' }';
return s;
}
function inspectArray(arr, depth, seen) {
if (depth > DEPTH_LIMIT) {
return '[Array]';
}
let s = '[';
for (let i = 0; i < arr.length; i++) {
s += i === 0 ? ' ' : ', ';
if (i >= LIST_LIMIT) {
s += `... ${arr.length - LIST_LIMIT} more items`;
break;
}
s += inspectValue(arr[i], depth, seen);
}
s += ' ]';
return s;
}
const emberDebugLibInspect = /*#__PURE__*/Object.defineProperty({
__proto__: null,
default: inspect
}, Symbol.toStringTag, { value: 'Module' });
const EMPTY_ARRAY$4 = Object.freeze([]);
function emptyArray() {
return EMPTY_ARRAY$4;
}
const EMPTY_STRING_ARRAY = emptyArray(),
EMPTY_NUMBER_ARRAY = emptyArray();
/**
* This function returns `true` if the input array is the special empty array sentinel,
* which is sometimes used for optimizations.
*/
function isEmptyArray(input) {
return input === EMPTY_ARRAY$4;
}
function* reverse(input) {
for (let i = input.length - 1; i >= 0; i--) yield input[i];
}
function* enumerate(input) {
let i = 0;
for (const item of input) yield [i++, item];
}
// import Logger from './logger';
// let alreadyWarned = false;
function debugAssert(test, msg) {
// if (!alreadyWarned) {
// alreadyWarned = true;
// Logger.warn("Don't leave debug assertions on in public builds");
// }
if (!test) throw new Error(msg || "assertion failure");
}
function deprecate$2(desc) {
LOCAL_LOGGER.warn(`DEPRECATION: ${desc}`);
}
function keys(obj) {
return Object.keys(obj);
}
function unwrap$1(val) {
if (null == val) throw new Error("Expected value to be present");
return val;
}
function expect(val, message) {
if (null == val) throw new Error(message);
return val;
}
function unreachable(message = "unreachable") {
return new Error(message);
}
function exhausted(value) {
throw new Error(`Exhausted ${String(value)}`);
}
const tuple = (...args) => args;
function isPresent$2(value) {
return null != value;
}
function assertPresent(value, message) {
if (!isPresent$2(value)) throw new Error(`Expected present, got ${"string" == typeof value ? value : message}`);
}
function isPresentArray(list) {
return list.length > 0;
}
function ifPresent(list, ifPresent, otherwise) {
return isPresentArray(list) ? ifPresent(list) : otherwise();
}
function arrayToOption(list) {
return isPresentArray(list) ? list : null;
}
function assertPresentArray(list, message = "unexpected empty list") {
if (!isPresentArray(list)) throw new Error(message);
}
function asPresentArray(list, message = "unexpected empty list") {
return assertPresentArray(list, message), list;
}
function getLast(list) {
return 0 === list.length ? void 0 : list[list.length - 1];
}
function getFirst(list) {
return 0 === list.length ? void 0 : list[0];
}
function mapPresentArray(list, mapper) {
if (null === list) return null;
let out = [];
for (let item of list) out.push(mapper(item));
return out;
}
function dict() {
return Object.create(null);
}
function isDict(u) {
return null != u;
}
function isObject(u) {
return "function" == typeof u || "object" == typeof u && null !== u;
}
class StackImpl {
stack;
current = null;
constructor(values = []) {
this.stack = values;
}
get size() {
return this.stack.length;
}
push(item) {
this.current = item, this.stack.push(item);
}
pop() {
let item = this.stack.pop();
return this.current = getLast(this.stack) ?? null, void 0 === item ? null : item;
}
nth(from) {
let len = this.stack.length;
return len < from ? null : unwrap$1(this.stack[len - from]);
}
isEmpty() {
return 0 === this.stack.length;
}
toArray() {
return this.stack;
}
}
/// <reference types="qunit" />
let beginTestSteps, endTestSteps, verifySteps, logStep, debugToString;
var debugToString$1 = debugToString;
function clearElement(parent) {
let current = parent.firstChild;
for (; current;) {
let next = current.nextSibling;
parent.removeChild(current), current = next;
}
}
const RAW_NODE = -1,
ELEMENT_NODE = 1,
TEXT_NODE = 3,
COMMENT_NODE = 8,
DOCUMENT_NODE = 9,
DOCUMENT_TYPE_NODE = 10,
DOCUMENT_FRAGMENT_NODE = 11,
NS_HTML = "http://www.w3.org/1999/xhtml",
NS_MATHML = "http://www.w3.org/1998/Math/MathML",
NS_SVG = "http://www.w3.org/2000/svg",
NS_XLINK = "http://www.w3.org/1999/xlink",
NS_XML = "http://www.w3.org/XML/1998/namespace",
NS_XMLNS = "http://www.w3.org/2000/xmlns/",
INSERT_BEFORE_BEGIN = "beforebegin",
INSERT_AFTER_BEGIN = "afterbegin",
INSERT_BEFORE_END = "beforeend",
INSERT_AFTER_END = "afterend";
/*
Encoding notes
We use 30 bit integers for encoding, so that we don't ever encode a non-SMI
integer to push on the stack.
Handles are >= 0
Immediates are < 0
True, False, Undefined and Null are pushed as handles into the symbol table,
with well known handles (0, 1, 2, 3)
The negative space is divided into positives and negatives. Positives are
higher numbers (-1, -2, -3, etc), negatives are lower.
We only encode immediates for two reasons:
1. To transfer over the wire, so they're smaller in general
2. When pushing values onto the stack from the low level/inner VM, which may
be converted into WASM one day.
This allows the low-level VM to always use SMIs, and to minimize using JS
values via handles for things like the stack pointer and frame pointer.
Externally, most code pushes values as JS values, except when being pulled
from the append byte code where it was already encoded.
Logically, this is because the low level VM doesn't really care about these
higher level values. For instance, the result of a userland helper may be a
number, or a boolean, or undefined/null, but it's extra work to figure that
out and push it correctly, vs. just pushing the value as a JS value with a
handle.
Note: The details could change here in the future, this is just the current
strategy.
*/
let ImmediateConstants = function (ImmediateConstants) {
return ImmediateConstants[ImmediateConstants.MAX_SMI = 1073741823] = "MAX_SMI", ImmediateConstants[ImmediateConstants.MIN_SMI = -1073741824] = "MIN_SMI", ImmediateConstants[ImmediateConstants.SIGN_BIT = -536870913] = "SIGN_BIT", ImmediateConstants[ImmediateConstants.MAX_INT = 536870911] = "MAX_INT", ImmediateConstants[ImmediateConstants.MIN_INT = -536870912] = "MIN_INT", ImmediateConstants[ImmediateConstants.FALSE_HANDLE = 0] = "FALSE_HANDLE", ImmediateConstants[ImmediateConstants.TRUE_HANDLE = 1] = "TRUE_HANDLE", ImmediateConstants[ImmediateConstants.NULL_HANDLE = 2] = "NULL_HANDLE", ImmediateConstants[ImmediateConstants.UNDEFINED_HANDLE = 3] = "UNDEFINED_HANDLE", ImmediateConstants[ImmediateConstants.ENCODED_FALSE_HANDLE = 0] = "ENCODED_FALSE_HANDLE", ImmediateConstants[ImmediateConstants.ENCODED_TRUE_HANDLE = 1] = "ENCODED_TRUE_HANDLE", ImmediateConstants[ImmediateConstants.ENCODED_NULL_HANDLE = 2] = "ENCODED_NULL_HANDLE", ImmediateConstants[ImmediateConstants.ENCODED_UNDEFINED_HANDLE = 3] = "ENCODED_UNDEFINED_HANDLE", ImmediateConstants;
}({});
function isHandle(value) {
return value >= 0;
}
function isNonPrimitiveHandle(value) {
return value > ImmediateConstants.ENCODED_UNDEFINED_HANDLE;
}
function constants(...values) {
return [!1, !0, null, void 0, ...values];
}
function isSmallInt(value) {
return value % 1 == 0 && value <= ImmediateConstants.MAX_INT && value >= ImmediateConstants.MIN_INT;
}
function encodeNegative(num) {
return num & ImmediateConstants.SIGN_BIT;
}
function decodeNegative(num) {
return num | ~ImmediateConstants.SIGN_BIT;
}
function encodePositive(num) {
return ~num;
}
function decodePositive(num) {
return ~num;
}
function encodeHandle(num) {
return num;
}
function decodeHandle(num) {
return num;
}
function encodeImmediate(num) {
return (num |= 0) < 0 ? encodeNegative(num) : encodePositive(num);
}
function decodeImmediate(num) {
return (num |= 0) > ImmediateConstants.SIGN_BIT ? decodePositive(num) : decodeNegative(num);
}
/**
Strongly hint runtimes to intern the provided string.
When do I need to use this function?
For the most part, never. Pre-mature optimization is bad, and often the
runtime does exactly what you need it to, and more often the trade-off isn't
worth it.
Why?
Runtimes store strings in at least 2 different representations:
Ropes and Symbols (interned strings). The Rope provides a memory efficient
data-structure for strings created from concatenation or some other string
manipulation like splitting.
Unfortunately checking equality of different ropes can be quite costly as
runtimes must resort to clever string comparison algorithms. These
algorithms typically cost in proportion to the length of the string.
Luckily, this is where the Symbols (interned strings) shine. As Symbols are
unique by their string content, equality checks can be done by pointer
comparison.
How do I know if my string is a rope or symbol?
Typically (warning general sweeping statement, but truthy in runtimes at
present) static strings created as part of the JS source are interned.
Strings often used for comparisons can be interned at runtime if some
criteria are met.