diff --git a/.eslintrc.js b/.eslintrc.js
index 3cb5fd6ea66..3771c46ac3d 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -5,6 +5,7 @@ module.exports = {
ecmaVersion: 6,
sourceType: 'module',
},
+ parser: 'babel-eslint',
extends: 'eslint:recommended',
env: {
'browser': true,
@@ -41,7 +42,7 @@ module.exports = {
'curly': ['error', 'all'],
'eol-last': 'error',
'no-trailing-spaces': 'error',
- 'comma-dangle': ['error', 'never'],
+ 'comma-dangle': ['off', 'never'],
'space-before-blocks': ['error', 'always'],
'indent': ['error', 2, {
'SwitchCase': 1,
diff --git a/.gitignore b/.gitignore
index 3fa6bc6e064..1912672e155 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@ tmp/
tests/source/
dist/
*.iml
+yarn-error.log
benchmarks/results/*.json
diff --git a/.travis.yml b/.travis.yml
index d9a6b400138..df0bb6adf1d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -56,8 +56,8 @@ jobs:
# runs tests against each supported Ember version
- stage: older version tests
- env: EMBER_TRY_SCENARIO=ember-lts-2.12
- - env: EMBER_TRY_SCENARIO=ember-lts-2.16
+ env: EMBER_TRY_SCENARIO=ember-lts-2.16
+ - env: EMBER_TRY_SCENARIO=ember-lts-2.18
- env: EMBER_TRY_SCENARIO=ember-release
- env: EMBER_TRY_SCENARIO=ember-beta
- env: EMBER_TRY_SCENARIO=ember-canary
diff --git a/addon/-private/system/many-array.js b/addon/-private/system/many-array.js
index f2b8a38ebf6..46b18aa7ef2 100644
--- a/addon/-private/system/many-array.js
+++ b/addon/-private/system/many-array.js
@@ -63,7 +63,7 @@ export default EmberObject.extend(MutableArray, Evented, {
@property {Boolean} isLoaded
*/
- this.isLoaded = false;
+ this.isLoaded = this.isLoaded || false;
this.length = 0;
/**
diff --git a/addon/-private/system/model/internal-model.js b/addon/-private/system/model/internal-model.js
index 936a6385402..bbf0662cb6f 100644
--- a/addon/-private/system/model/internal-model.js
+++ b/addon/-private/system/model/internal-model.js
@@ -137,7 +137,7 @@ export default class InternalModel {
this.store = store;
this.modelName = modelName;
- this._loadingPromise = null;
+ this._promiseProxy = null;
this._record = null;
this._isDestroyed = false;
this.isError = false;
@@ -538,11 +538,11 @@ export default class InternalModel {
this.dematerializeRecord();
if (this._scheduledDestroy === null) {
- // TODO: use run.schedule once we drop 1.13
- if (!run.currentRunLoop) {
- assert('You have turned on testing mode, which disabled the run-loop\'s autorun.\n You will need to wrap any code with asynchronous side-effects in a run', Ember.testing);
- }
- this._scheduledDestroy = run.backburner.schedule('destroy', this, '_checkForOrphanedInternalModels')
+ this._scheduledDestroy = run.backburner.schedule(
+ 'destroy',
+ this,
+ '_checkForOrphanedInternalModels'
+ );
}
}
diff --git a/addon/-private/system/model/states.js b/addon/-private/system/model/states.js
index 84085f14fe4..48ccdcf7543 100644
--- a/addon/-private/system/model/states.js
+++ b/addon/-private/system/model/states.js
@@ -495,7 +495,7 @@ const RootState = {
// EVENTS
loadingData(internalModel, promise) {
- internalModel._loadingPromise = promise;
+ internalModel._promiseProxy = promise;
internalModel.transitionTo('loading');
},
@@ -522,7 +522,7 @@ const RootState = {
isLoading: true,
exit(internalModel) {
- internalModel._loadingPromise = null;
+ internalModel._promiseProxy = null;
},
// EVENTS
diff --git a/addon/-private/system/record-array-manager.js b/addon/-private/system/record-array-manager.js
index 71b686dbee2..1327cb5d3a5 100644
--- a/addon/-private/system/record-array-manager.js
+++ b/addon/-private/system/record-array-manager.js
@@ -4,7 +4,7 @@
import { A } from '@ember/array';
import { set, get } from '@ember/object';
-import { run as emberRun } from '@ember/runloop';
+import { run as emberRunloop } from '@ember/runloop';
import { assert } from '@ember/debug';
import cloneNull from './clone-null';
import {
@@ -12,6 +12,8 @@ import {
AdapterPopulatedRecordArray
} from './record-arrays';
+const emberRun = emberRunloop.backburner;
+
const {
_flush,
array_remove,
diff --git a/addon/-private/system/references/belongs-to.js b/addon/-private/system/references/belongs-to.js
index 20a285bbb44..710ad589985 100644
--- a/addon/-private/system/references/belongs-to.js
+++ b/addon/-private/system/references/belongs-to.js
@@ -346,15 +346,17 @@ export default class BelongsToReference extends Reference {
@return {Promise} a promise that resolves with the record in this belongs-to relationship.
*/
load() {
- if (this.remoteType() === "id") {
- return this.belongsToRelationship.getRecord();
- }
+ let rel = this.belongsToRelationship;
+
+ rel.getData();
- if (this.remoteType() === "link") {
- return this.belongsToRelationship.findLink().then((internalModel) => {
+ if (rel.fetchPromise !== null) {
+ return rel.fetchPromise.then(() => {
return this.value();
});
}
+
+ return resolve(this.value());
}
/**
diff --git a/addon/-private/system/references/has-many.js b/addon/-private/system/references/has-many.js
index 5e88af85754..1606a06819c 100644
--- a/addon/-private/system/references/has-many.js
+++ b/addon/-private/system/references/has-many.js
@@ -354,8 +354,9 @@ export default class HasManyReference extends Reference {
this has-many relationship.
*/
load() {
+ // TODO this can be simplified
if (!this._isLoaded()) {
- return this.hasManyRelationship.getRecords();
+ return this.hasManyRelationship.getData();
}
return resolve(this.hasManyRelationship.manyArray);
diff --git a/addon/-private/system/relationships/belongs-to.js b/addon/-private/system/relationships/belongs-to.js
index 8256a5737ee..421d7132f96 100644
--- a/addon/-private/system/relationships/belongs-to.js
+++ b/addon/-private/system/relationships/belongs-to.js
@@ -115,12 +115,12 @@ export default function belongsTo(modelName, options) {
});
}
- return this._internalModel._relationships.get(key).getRecord();
+ return this._internalModel._relationships.get(key).getData();
},
set(key, value) {
this._internalModel.setDirtyBelongsTo(key, value);
- return this._internalModel._relationships.get(key).getRecord();
- }
+ return this._internalModel._relationships.get(key).getData();
+ },
}).meta(meta);
}
diff --git a/addon/-private/system/relationships/has-many.js b/addon/-private/system/relationships/has-many.js
index 6a575466a41..aee415ece85 100644
--- a/addon/-private/system/relationships/has-many.js
+++ b/addon/-private/system/relationships/has-many.js
@@ -140,12 +140,12 @@ export default function hasMany(type, options) {
return computed({
get(key) {
- return this._internalModel._relationships.get(key).getRecords();
+ return this._internalModel._relationships.get(key).getData();
},
set(key, records) {
this._internalModel.setDirtyHasMany(key, records);
- return this._internalModel._relationships.get(key).getRecords();
- }
+ return this._internalModel._relationships.get(key).getData();
+ },
}).meta(meta);
}
diff --git a/addon/-private/system/relationships/state/belongs-to.js b/addon/-private/system/relationships/state/belongs-to.js
index c1d813fe829..0e64ae6a1e5 100644
--- a/addon/-private/system/relationships/state/belongs-to.js
+++ b/addon/-private/system/relationships/state/belongs-to.js
@@ -1,17 +1,31 @@
-import { Promise as EmberPromise } from 'rsvp';
+import { resolve } from 'rsvp';
import { assert, inspect } from '@ember/debug';
import { assertPolymorphicType } from 'ember-data/-debug';
-import {
- PromiseBelongsTo
-} from "../../promise-proxies";
-import Relationship from "./relationship";
+import { PromiseBelongsTo, PromiseObject } from '../../promise-proxies';
+import Relationship from './relationship';
export default class BelongsToRelationship extends Relationship {
constructor(store, internalModel, inverseKey, relationshipMeta) {
super(store, internalModel, inverseKey, relationshipMeta);
this.inverseInternalModel = null;
this.canonicalState = null;
- this._loadingPromise = null;
+ this._promiseProxy = null;
+ }
+
+ /**
+ * Flag indicating whether all inverse records are available
+ *
+ * true if the inverse exists and is loaded (not empty)
+ * true if there is no inverse
+ * false if the inverse exists and is not loaded (empty)
+ *
+ * @returns {boolean}
+ */
+ get allInverseRecordsAreLoaded() {
+ let internalModel = this.inverseInternalModel;
+ let isEmpty = internalModel !== null && internalModel.isEmpty();
+
+ return !isEmpty;
}
setInternalModel(internalModel) {
@@ -23,7 +37,6 @@ export default class BelongsToRelationship extends Relationship {
this.setHasAnyRelationshipData(true);
this.setRelationshipIsStale(false);
this.setRelationshipIsEmpty(false);
- this.setHasRelatedResources(!this.localStateIsEmpty());
}
setCanonicalInternalModel(internalModel) {
@@ -91,6 +104,7 @@ export default class BelongsToRelationship extends Relationship {
}
if (this.inverseInternalModel !== this.canonicalState) {
this.inverseInternalModel = this.canonicalState;
+ this._promiseProxy = null;
this.notifyBelongsToChanged();
}
@@ -111,15 +125,23 @@ export default class BelongsToRelationship extends Relationship {
this.notifyBelongsToChanged();
}
- setRecordPromise(newPromise) {
- let content = newPromise.get && newPromise.get('content');
- assert("You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.", content !== undefined);
+ setRecordPromise(belongsToPromise) {
+ assert(
+ 'You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.',
+ belongsToPromise instanceof PromiseObject
+ );
+
+ let content = belongsToPromise.get('content');
+ let promise = belongsToPromise.get('promise');
+
this.setInternalModel(content ? content._internalModel : content);
+ this._updateLoadingPromise(promise, content);
}
removeInternalModelFromOwn(internalModel) {
if (!this.members.has(internalModel)) { return;}
this.inverseInternalModel = null;
+ this._promiseProxy = null;
super.removeInternalModelFromOwn(internalModel);
this.notifyBelongsToChanged();
}
@@ -127,6 +149,7 @@ export default class BelongsToRelationship extends Relationship {
removeAllInternalModelsFromOwn() {
super.removeAllInternalModelsFromOwn();
this.inverseInternalModel = null;
+ this._promiseProxy = null;
this.notifyBelongsToChanged();
}
@@ -145,91 +168,95 @@ export default class BelongsToRelationship extends Relationship {
this.canonicalState = null;
}
- findRecord() {
- if (this.inverseInternalModel) {
- return this.store._findByInternalModel(this.inverseInternalModel);
- } else {
- return EmberPromise.resolve(null);
+ // called by `getData()` when a request is needed
+ // but no link is available
+ _fetchRecord() {
+ let { inverseInternalModel, shouldForceReload } = this;
+
+ if (inverseInternalModel) {
+ let promise;
+
+ if (shouldForceReload && !inverseInternalModel.isEmpty() && inverseInternalModel.hasRecord) {
+ // reload record, if it is already loaded
+ // if we have a link, we would already be in `findLink()`
+ promise = inverseInternalModel.getRecord().reload();
+ } else {
+ promise = this.store._findByInternalModel(inverseInternalModel);
+ }
+
+ return promise;
}
+
+ // TODO is this actually an error case?
+ return resolve(null);
}
- fetchLink() {
- return this.store.findBelongsTo(this.internalModel, this.link, this.relationshipMeta).then((internalModel) => {
- if (internalModel) {
- this.addInternalModel(internalModel);
- }
- return internalModel;
- });
+ // called by `getData()` when a request is needed
+ // and a link is available
+ _fetchLink() {
+ return this.store
+ .findBelongsTo(this.internalModel, this.link, this.relationshipMeta)
+ .then(internalModel => {
+ if (internalModel) {
+ this.addInternalModel(internalModel);
+ }
+ return internalModel;
+ });
}
- getRecord() {
+ getData() {
//TODO(Igor) flushCanonical here once our syncing is not stupid
- if (this.isAsync) {
+ let record = this.inverseInternalModel ? this.inverseInternalModel.getRecord() : null;
+
+ if (this.shouldMakeRequest()) {
let promise;
- if (this._shouldFindViaLink()) {
- promise = this.findLink().then(() => this.findRecord());
+ if (this.link) {
+ promise = this._fetchLink();
} else {
- promise = this.findRecord();
+ promise = this._fetchRecord();
}
- let record = this.inverseInternalModel ? this.inverseInternalModel.getRecord() : null
-
- return this._updateLoadingPromise(promise, record);
- } else {
- if (this.inverseInternalModel === null) {
- return null;
- }
- let toReturn = this.inverseInternalModel.getRecord();
- assert("You looked up the '" + this.key + "' relationship on a '" + this.internalModel.modelName + "' with id " + this.internalModel.id + " but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)", toReturn === null || !toReturn.get('isEmpty'));
- return toReturn;
- }
- }
+ promise = promise.then(() => handleCompletedFind(this), e => handleCompletedFind(this, e));
- _updateLoadingPromise(promise, content) {
- if (this._loadingPromise) {
- if (content !== undefined) {
- this._loadingPromise.set('content', content)
- }
- this._loadingPromise.set('promise', promise)
- } else {
- this._loadingPromise = PromiseBelongsTo.create({
- _belongsToState: this,
- promise,
- content
+ promise = promise.then(internalModel => {
+ return internalModel ? internalModel.getRecord() : null;
});
- }
- return this._loadingPromise;
- }
-
- reload() {
- // we've already fired off a request
- if (this._loadingPromise) {
- if (this._loadingPromise.get('isPending')) {
- return this._loadingPromise;
- }
+ this.fetchPromise = promise;
+ this._updateLoadingPromise(promise);
}
- let promise;
- this.setRelationshipIsStale(true);
+ if (this.isAsync) {
+ if (this._promiseProxy === null) {
+ let promise = resolve(this.inverseInternalModel).then(internalModel => {
+ return internalModel ? internalModel.getRecord() : null;
+ });
+ this._updateLoadingPromise(promise, record);
+ }
- if (this.link) {
- promise = this.fetchLink();
- } else if (this.inverseInternalModel && this.inverseInternalModel.hasRecord) {
- // reload record, if it is already loaded
- promise = this.inverseInternalModel.getRecord().reload();
+ return this._promiseProxy;
} else {
- promise = this.findRecord();
+ assert(
+ "You looked up the '" +
+ this.key +
+ "' relationship on a '" +
+ this.internalModel.modelName +
+ "' with id " +
+ this.internalModel.id +
+ ' but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)',
+ record === null || !record.get('isEmpty')
+ );
+ return record;
}
-
- return this._updateLoadingPromise(promise);
}
- localStateIsEmpty() {
- let internalModel = this.inverseInternalModel;
-
- return !internalModel || internalModel.isEmpty();
+ _createProxy(promise, content) {
+ return PromiseBelongsTo.create({
+ _belongsToState: this,
+ promise,
+ content,
+ });
}
updateData(data, initial) {
@@ -242,3 +269,21 @@ export default class BelongsToRelationship extends Relationship {
}
}
}
+
+function handleCompletedFind(relationship, error) {
+ let internalModel = relationship.inverseInternalModel;
+
+ relationship.fetchPromise = null;
+ relationship.setShouldForceReload(false);
+
+ if (error) {
+ relationship.setHasFailedLoadAttempt(true);
+ throw error;
+ }
+
+ relationship.setHasFailedLoadAttempt(false);
+ // only set to not stale if no error is thrown
+ relationship.setRelationshipIsStale(false);
+
+ return internalModel;
+}
diff --git a/addon/-private/system/relationships/state/has-many.js b/addon/-private/system/relationships/state/has-many.js
index 6a73365e369..c7af8e60fae 100755
--- a/addon/-private/system/relationships/state/has-many.js
+++ b/addon/-private/system/relationships/state/has-many.js
@@ -4,6 +4,7 @@ import { PromiseManyArray } from '../../promise-proxies';
import Relationship from './relationship';
import OrderedSet from '../../ordered-set';
import ManyArray from '../../many-array';
+import { resolve } from 'rsvp';
export default class ManyRelationship extends Relationship {
constructor(store, internalModel, inverseKey, relationshipMeta) {
@@ -16,31 +17,58 @@ export default class ManyRelationship extends Relationship {
// we create a new many array, but in the interim it will be updated if
// inverse internal models are unloaded.
this._retainedManyArray = null;
- this._loadingPromise = null;
+ this._promiseProxy = null;
this._willUpdateManyArray = false;
this._pendingManyArrayUpdates = null;
}
- _updateLoadingPromise(promise, content) {
- if (this._loadingPromise) {
- if (content) {
- this._loadingPromise.set('content', content)
- }
- this._loadingPromise.set('promise', promise)
- } else {
- this._loadingPromise = PromiseManyArray.create({
- promise,
- content
- });
- }
+ get currentState() {
+ return this.members.list;
+ }
+
+ /**
+ * Flag indicating whether all inverse records are available
+ *
+ * true if inverse records exist and are all loaded (all not empty)
+ * true if there are no inverse records
+ * false if the inverse records exist and any are not loaded (any empty)
+ *
+ * @returns {boolean}
+ */
+ get allInverseRecordsAreLoaded() {
+ // check currentState for unloaded records
+ let hasEmptyRecords = this.currentState.reduce((hasEmptyModel, i) => {
+ return hasEmptyModel || i.isEmpty();
+ }, false);
+
+ // check un-synced state for unloaded records
+ if (!hasEmptyRecords && this.willSync) {
+ hasEmptyRecords = this.canonicalState.reduce((hasEmptyModel, i) => {
+ return hasEmptyModel || !i.isEmpty();
+ }, false);
+ }
+
+ return !hasEmptyRecords;
+ }
- return this._loadingPromise;
+ _createProxy(promise, content) {
+ return PromiseManyArray.create({
+ promise,
+ content,
+ });
}
get manyArray() {
- assert(`Error: relationship ${this.parentType}:${this.key} has both many array and retained many array`, this._manyArray === null || this._retainedManyArray === null);
+ assert(
+ `Error: relationship ${this.parentType}:${
+ this.key
+ } has both many array and retained many array`,
+ this._manyArray === null || this._retainedManyArray === null
+ );
+
+ if (!this._manyArray && !this.isDestroying) {
+ let isLoaded = this.hasFailedLoadAttempt || this.isNew || this.allInverseRecordsAreLoaded;
- if (!this._manyArray) {
this._manyArray = ManyArray.create({
canonicalState: this.canonicalState,
store: this.store,
@@ -48,7 +76,8 @@ export default class ManyRelationship extends Relationship {
type: this.store.modelFor(this.belongsToType),
record: this.internalModel,
meta: this.meta,
- isPolymorphic: this.isPolymorphic
+ isPolymorphic: this.isPolymorphic,
+ isLoaded,
});
if (this._retainedManyArray !== null) {
@@ -67,8 +96,8 @@ export default class ManyRelationship extends Relationship {
this._manyArray = null;
}
- if (this._loadingPromise) {
- this._loadingPromise.destroy();
+ if (this._promiseProxy) {
+ this._promiseProxy.destroy();
}
}
@@ -243,28 +272,6 @@ export default class ManyRelationship extends Relationship {
this.internalModel.notifyHasManyAdded(this.key, internalModel, idx);
}
- reload() {
- let manyArray = this.manyArray;
-
- if (this._loadingPromise) {
- if (this._loadingPromise.get('isPending')) {
- return this._loadingPromise;
- }
- }
-
- this.setRelationshipIsStale(true);
-
- let promise;
- if (this.link) {
- promise = this.fetchLink();
- } else {
- promise = this.store._scheduleFetchMany(manyArray.currentState).then(() => manyArray);
- }
-
- this._updateLoadingPromise(promise);
- return this._loadingPromise;
- }
-
computeChanges(internalModels = []) {
let members = this.canonicalMembers;
let internalModelsToRemove = [];
@@ -304,60 +311,84 @@ export default class ManyRelationship extends Relationship {
this.canonicalState = this.canonicalMembers.toArray();
}
- fetchLink() {
- return this.store.findHasMany(this.internalModel, this.link, this.relationshipMeta).then(records => {
- if (records.hasOwnProperty('meta')) {
- this.updateMeta(records.meta);
- }
- this.store._backburner.join(() => {
- this.updateInternalModelsFromAdapter(records);
- this.manyArray.set('isLoaded', true);
- });
- return this.manyArray;
- });
- }
+ // called by `getData()` when a request is needed
+ // but no link is available
+ _fetchRecords() {
+ let internalModels = this.currentState;
+ let { shouldForceReload } = this;
+ let promise;
- findRecords() {
- let manyArray = this.manyArray;
- let internalModels = manyArray.currentState;
+ if (shouldForceReload === true) {
+ promise = this.store._scheduleFetchMany(internalModels);
+ } else {
+ promise = this.store.findMany(internalModels);
+ }
- //TODO CLEANUP
- return this.store.findMany(internalModels).then(() => {
- if (!manyArray.get('isDestroyed')) {
- //Goes away after the manyArray refactor
- manyArray.set('isLoaded', true);
- }
- return manyArray;
- });
+ return promise;
}
- notifyHasManyChanged() {
- this.internalModel.notifyHasManyAdded(this.key);
+ // called by `getData()` when a request is needed
+ // and a link is available
+ _fetchLink() {
+ return this.store
+ .findHasMany(this.internalModel, this.link, this.relationshipMeta)
+ .then(records => {
+ if (records.hasOwnProperty('meta')) {
+ this.updateMeta(records.meta);
+ }
+ this.store._backburner.join(() => {
+ this.updateInternalModelsFromAdapter(records);
+ });
+ return records;
+ });
}
- getRecords() {
+ getData() {
//TODO(Igor) sync server here, once our syncing is not stupid
let manyArray = this.manyArray;
- if (this.isAsync) {
+ if (this.shouldMakeRequest()) {
let promise;
- if (this._shouldFindViaLink()) {
- promise = this.findLink().then(() => this.findRecords());
+ if (this.link) {
+ promise = this._fetchLink();
} else {
- promise = this.findRecords();
+ promise = this._fetchRecords();
}
- return this._updateLoadingPromise(promise, manyArray);
- } else {
- assert(`You looked up the '${this.key}' relationship on a '${this.internalModel.type.modelName}' with id ${this.internalModel.id} but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async ('DS.hasMany({ async: true })')`, manyArray.isEvery('isEmpty', false));
+ promise = promise.then(
+ () => handleCompletedRequest(this),
+ e => handleCompletedRequest(this, e)
+ );
+
+ this.fetchPromise = promise;
+ this._updateLoadingPromise(promise, manyArray);
+ }
- manyArray.set('isLoaded', true);
+ if (this.isAsync) {
+ if (this._promiseProxy === null) {
+ this._updateLoadingPromise(resolve(manyArray), manyArray);
+ }
+
+ return this._promiseProxy;
+ } else {
+ assert(
+ `You looked up the '${this.key}' relationship on a '${
+ this.internalModel.type.modelName
+ }' with id ${
+ this.internalModel.id
+ } but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (\`DS.hasMany({ async: true })\`)`,
+ this.allInverseRecordsAreLoaded
+ );
return manyArray;
}
}
+ notifyHasManyChanged() {
+ this.internalModel.notifyHasManyAdded(this.key);
+ }
+
updateData(data, initial) {
let internalModels = this.store._pushResourceIdentifiers(this, data);
if (initial) {
@@ -367,20 +398,6 @@ export default class ManyRelationship extends Relationship {
}
}
- localStateIsEmpty() {
- let manyArray = this.manyArray;
- let internalModels = manyArray.currentState;
- let manyArrayIsLoaded = manyArray.get('isLoaded');
-
- if (!manyArrayIsLoaded && internalModels.length) {
- manyArrayIsLoaded = internalModels.reduce((hasNoEmptyModel, i) => {
- return hasNoEmptyModel && !i.isEmpty();
- }, true);
- }
-
- return !manyArrayIsLoaded;
- }
-
destroy() {
super.destroy();
let manyArray = this._manyArray;
@@ -389,15 +406,38 @@ export default class ManyRelationship extends Relationship {
this._manyArray = null;
}
- let proxy = this._loadingPromise;
+ let proxy = this._promiseProxy;
if (proxy) {
proxy.destroy();
- this._loadingPromise = null;
+ this._promiseProxy = null;
}
}
}
+function handleCompletedRequest(relationship, error) {
+ let manyArray = relationship.manyArray;
+
+ //Goes away after the manyArray refactor
+ if (!manyArray.get('isDestroyed')) {
+ relationship.manyArray.set('isLoaded', true);
+ }
+
+ relationship.fetchPromise = null;
+ relationship.setShouldForceReload(false);
+
+ if (error) {
+ relationship.setHasFailedLoadAttempt(true);
+ throw error;
+ }
+
+ relationship.setHasFailedLoadAttempt(false);
+ // only set to not stale if no error is thrown
+ relationship.setRelationshipIsStale(false);
+
+ return manyArray;
+}
+
function setForArray(array) {
var set = new OrderedSet();
diff --git a/addon/-private/system/relationships/state/relationship.js b/addon/-private/system/relationships/state/relationship.js
index 4d2bef4c5a4..45081c5af33 100644
--- a/addon/-private/system/relationships/state/relationship.js
+++ b/addon/-private/system/relationships/state/relationship.js
@@ -12,7 +12,6 @@ const {
addInternalModel,
addInternalModels,
clear,
- findLink,
flushCanonical,
flushCanonicalLater,
newRelationship,
@@ -34,7 +33,6 @@ const {
'addInternalModel',
'addInternalModels',
'clear',
- 'findLink',
'flushCanonical',
'flushCanonicalLater',
'newRelationship',
@@ -69,15 +67,34 @@ export default class Relationship {
//This probably breaks for polymorphic relationship in complex scenarios, due to
//multiple possible modelNames
this.inverseKeyForImplicit = this.internalModel.modelName + this.key;
- this.linkPromise = null;
+ this.fetchPromise = null;
+ this._promiseProxy = null;
this.meta = null;
this.__inverseMeta = undefined;
+ /*
+ This flag forces fetch. `true` for a single request once `reload()`
+ has been called `false` at all other times.
+ */
+ this.shouldForceReload = false;
+
/*
This flag indicates whether we should
re-fetch the relationship the next time
it is accessed.
+ The difference between this flag and `shouldForceReload`
+ is in how we treat the presence of partially missing data:
+ - for a forced reload, we will reload the link or EVERY record
+ - for a stale reload, we will reload the link (if present) else only MISSING records
+
+ Ideally these flags could be merged, but because we don't give the
+ request layer the option of deciding how to resolve the data being queried
+ we are forced to differentiate for now.
+
+ It is also possible for a relationship to remain stale after a forced reload; however,
+ in this case `hasFailedLoadAttempt` ought to be `true`.
+
false when
=> internalModel.isNew() on initial setup
=> a previously triggered request has resolved
@@ -86,10 +103,9 @@ export default class Relationship {
true when
=> !internalModel.isNew() on initial setup
=> an inverse has been unloaded
- => relationship.reload() has been called
=> we get a new link for the relationship
*/
- this.relationshipIsStale = !internalModel.isNew();
+ this.relationshipIsStale = !this.isNew;
/*
This flag indicates whether we should consider the content
@@ -137,6 +153,12 @@ export default class Relationship {
*/
this.relationshipIsEmpty = true;
+ /*
+ Flag that indicates whether we have explicitly attempted a load for the relationship
+ (which may have failed)
+ */
+ this.hasFailedLoadAttempt = false;
+
/*
true when
=> hasAnyRelationshipData is true
@@ -145,7 +167,10 @@ export default class Relationship {
TODO, consider changing the conditional here from !isEmpty to !hiddenFromRecordArrays
*/
- this.hasRelatedResources = false;
+ }
+
+ get isNew() {
+ return this.internalModel.isNew();
}
_inverseIsSync() {
@@ -188,7 +213,7 @@ export default class Relationship {
}
inverseDidDematerialize(inverseInternalModel) {
- this.linkPromise = null;
+ this.fetchPromise = null;
this.setRelationshipIsStale(true);
if (!this.isAsync) {
@@ -489,7 +514,7 @@ export default class Relationship {
assert(`You have pushed a record of type '${this.internalModel.modelName}' with '${this.key}' as a link, but the value of that link is not a string.`, typeof link === 'string' || link === null);
this.link = link;
- this.linkPromise = null;
+ this.fetchPromise = null;
this.setRelationshipIsStale(true);
if (!initial) {
@@ -497,24 +522,99 @@ export default class Relationship {
}
}
- _shouldFindViaLink() {
- if (!this.link) {
- return false;
+ reload() {
+ if (this._promiseProxy) {
+ if (this._promiseProxy.get('isPending')) {
+ return this._promiseProxy;
+ }
}
- return this.relationshipIsStale ||
- !this.hasRelatedResources;
+ this.setHasFailedLoadAttempt(false);
+ this.setShouldForceReload(true);
+ this.getData();
+
+ return this._promiseProxy;
}
- findLink() {
- heimdall.increment(findLink);
- if (this.linkPromise) {
- return this.linkPromise;
+ shouldMakeRequest() {
+ let {
+ relationshipIsStale,
+ hasFailedLoadAttempt,
+ allInverseRecordsAreLoaded,
+ hasAnyRelationshipData,
+ shouldForceReload,
+ relationshipIsEmpty,
+ isAsync,
+ isNew,
+ fetchPromise,
+ } = this;
+
+ // never make a request if this record doesn't exist server side yet
+ if (isNew === true) {
+ return false;
+ }
+
+ // do not re-request if we are already awaiting a request
+ if (fetchPromise !== null) {
+ return false;
+ }
+
+ // Always make a request when forced
+ // failed attempts must call `reload()`.
+ //
+ // For legacy reasons, when a relationship is missing only
+ // some of it's data we rely on individual `findRecord`
+ // calls which may resolve from cache in the non-link case.
+ // This determination is made elsewhere.
+ //
+ if (shouldForceReload === true || relationshipIsStale === true) {
+ return !hasFailedLoadAttempt;
+ }
+
+ // never make a request if we've explicitly attempted to at least once
+ // since the last update to canonical state
+ // this includes failed attempts
+ // e.g. to re-attempt `reload()` must be called force the attempt.
+ if (hasFailedLoadAttempt === true) {
+ return false;
+ }
+
+ // we were explicitly told that there is no inverse relationship
+ if (relationshipIsEmpty === true) {
+ return false;
+ }
+
+ // we were explicitly told what the inverse is, and we have the inverse records available
+ if (hasAnyRelationshipData === true && allInverseRecordsAreLoaded === true) {
+ return false;
+ }
+
+ // if this is a sync relationship, we should not need to fetch, so getting here is an error
+ assert(
+ `You looked up the '${this.key}' relationship on a '${
+ this.internalModel.type.modelName
+ }' with id ${
+ this.internalModel.id
+ } but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (\`DS.${
+ this.relationshipMeta.kind
+ }({ async: true })\`)`,
+ isAsync === true
+ );
+
+ return true;
+ }
+
+ _updateLoadingPromise(promise, content) {
+ if (this._promiseProxy) {
+ if (content !== undefined) {
+ this._promiseProxy.set('content', content);
+ }
+ this._promiseProxy.set('promise', promise);
} else {
- let promise = this.fetchLink();
- this.linkPromise = promise;
- return promise.then((result) => result);
+ this._promiseProxy = this._createProxy(promise, content);
}
+
+ return this._promiseProxy;
}
updateInternalModelsFromAdapter(internalModels) {
@@ -531,8 +631,8 @@ export default class Relationship {
this.hasAnyRelationshipData = value;
}
- setHasRelatedResources(v) {
- this.hasRelatedResources = v;
+ setHasFailedLoadAttempt(value) {
+ this.hasFailedLoadAttempt = value;
}
setRelationshipIsStale(value) {
@@ -543,6 +643,10 @@ export default class Relationship {
this.relationshipIsEmpty = value;
}
+ setShouldForceReload(value) {
+ this.shouldForceReload = value;
+ }
+
/*
`push` for a relationship allows the store to push a JSON API Relationship
Object onto the relationship. The relationship will then extract and set the
@@ -585,12 +689,12 @@ export default class Relationship {
relationshipIsEmpty -> true if is empty array (has-many) or is null (belongs-to)
hasAnyRelationshipData -> true
relationshipIsStale -> false
- hasRelatedResources -> run-check-to-determine
+ allInverseRecordsAreLoaded -> run-check-to-determine
IF contains only links
relationshipIsStale -> true
*/
-
+ this.setHasFailedLoadAttempt(false);
if (hasRelationshipDataProperty) {
let relationshipIsEmpty = payload.data === null ||
(Array.isArray(payload.data) && payload.data.length === 0);
@@ -598,14 +702,15 @@ export default class Relationship {
this.setHasAnyRelationshipData(true);
this.setRelationshipIsStale(false);
this.setRelationshipIsEmpty(relationshipIsEmpty);
- this.setHasRelatedResources(
- relationshipIsEmpty || !this.localStateIsEmpty()
- );
} else if (hasLink) {
this.setRelationshipIsStale(true);
}
}
+ getData() {}
+
+ _createProxy() {}
+
updateData() {}
destroy() {
diff --git a/addon/-private/system/store.js b/addon/-private/system/store.js
index ce00f19d97c..3d07bbea9e4 100644
--- a/addon/-private/system/store.js
+++ b/addon/-private/system/store.js
@@ -5,7 +5,7 @@
import { A } from '@ember/array';
import EmberError from '@ember/error';
import MapWithDefault from './map-with-default';
-import { run as emberRun } from '@ember/runloop';
+import { run as emberRunLoop } from '@ember/runloop';
import { set, get, computed } from '@ember/object';
import { assign } from '@ember/polyfills';
import { default as RSVP, Promise } from 'rsvp';
@@ -55,7 +55,7 @@ import InternalModel from "./model/internal-model";
import edBackburner from './backburner';
const badIdFormatAssertion = '`id` passed to `findRecord()` has to be non-empty string or number';
-
+const emberRun = emberRunLoop.backburner;
const { ENV } = Ember;
//Get the materialized model from the internalModel/promise that returns
@@ -740,7 +740,7 @@ Store = Service.extend({
//TODO double check about reloading
if (internalModel.isLoading()) {
- return internalModel._loadingPromise;
+ return internalModel._promiseProxy;
}
return Promise.resolve(internalModel);
@@ -802,8 +802,8 @@ Store = Service.extend({
},
_scheduleFetch(internalModel, options) {
- if (internalModel._loadingPromise) {
- return internalModel._loadingPromise;
+ if (internalModel._promiseProxy) {
+ return internalModel._promiseProxy;
}
let { id, modelName } = internalModel;
@@ -1792,7 +1792,7 @@ Store = Service.extend({
snapshot: snapshot,
resolver: resolver
});
- emberRun.once(this, this.flushPendingSave);
+ emberRun.scheduleOnce('actions', this, this.flushPendingSave);
},
/**
diff --git a/addon/-private/system/store/common.js b/addon/-private/system/store/common.js
index 007671f5114..6e13ab24fbc 100644
--- a/addon/-private/system/store/common.js
+++ b/addon/-private/system/store/common.js
@@ -1,7 +1,7 @@
import { get } from '@ember/object';
import { DEBUG } from '@glimmer/env';
import Ember from 'ember';
-import { Promise } from 'rsvp';
+import { resolve } from 'rsvp';
const {
__bind,
@@ -23,7 +23,7 @@ export function _bind(fn, ...args) {
export function _guard(promise, test) {
heimdall.increment(__guard);
- let guarded = promise['finally'](function() {
+ let guarded = promise.finally(() => {
if (!test()) {
guarded._subscribers.length = 0;
}
@@ -49,7 +49,12 @@ if (DEBUG) {
}
export function guardDestroyedStore(promise, store, label) {
- promise = Promise.resolve(promise, label);
+ let wrapperPromise = resolve(promise, label).then(v => promise);
- return _guard(promise, () => { if (DEBUG) { ASYNC_REQUEST_COUNT--; } return _objectIsAlive(store); });
+ return _guard(wrapperPromise, () => {
+ if (DEBUG) {
+ ASYNC_REQUEST_COUNT--;
+ }
+ return _objectIsAlive(store);
+ });
}
diff --git a/addon/-private/system/store/finders.js b/addon/-private/system/store/finders.js
index d9923eaf29a..db3593f8d4b 100644
--- a/addon/-private/system/store/finders.js
+++ b/addon/-private/system/store/finders.js
@@ -26,7 +26,9 @@ export function _find(adapter, store, modelClass, id, internalModel, options) {
if (DEBUG) { incrementRequestCount(); }
let snapshot = internalModel.createSnapshot(options);
let { modelName } = internalModel;
- let promise = Promise.resolve().then(() => adapter.findRecord(store, modelClass, id, snapshot));
+ let promise = Promise.resolve().then(() => {
+ return adapter.findRecord(store, modelClass, id, snapshot);
+ });
let label = `DS: Handle Adapter#findRecord of '${modelName}' with id: '${id}'`;
promise = guardDestroyedStore(promise, store, label);
diff --git a/config/ember-try.js b/config/ember-try.js
index 44c3e0be73e..1e16b022a3d 100644
--- a/config/ember-try.js
+++ b/config/ember-try.js
@@ -17,20 +17,20 @@ module.exports = function() {
npm: { }
},
{
- name: 'ember-lts-2.12',
+ name: 'ember-lts-2.16',
npm: {
devDependencies: {
- 'ember-source': '~2.12.0'
- }
- }
+ 'ember-source': '~2.16.0',
+ },
+ },
},
{
- name: 'ember-lts-2.16',
+ name: 'ember-lts-2.18',
npm: {
devDependencies: {
- 'ember-source': '~2.16.0'
- }
- }
+ 'ember-source': '~2.18.0',
+ },
+ },
},
{
name: 'ember-release',
diff --git a/package.json b/package.json
index bb758bcb710..f9a9d6e0698 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"scripts": {
"build": "ember build",
"build:production": "ember build --environment=production",
+ "lint:js": "eslint .",
"start": "ember server",
"test": "ember test",
"test:all": "ember try:each",
@@ -53,6 +54,9 @@
},
"devDependencies": {
"babel-plugin-debug-macros": "^0.1.7",
+ "@ember-decorators/babel-transforms": "^2.0.0",
+ "@ember-decorators/data": "^2.1.0",
+ "babel-eslint": "^8.0.0",
"babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
"babel-plugin-transform-es2015-classes": "^6.23.0",
"babel-plugin-transform-es2015-computed-properties": "^6.22.0",
@@ -72,7 +76,7 @@
"broccoli-yuidoc": "^3.0.0",
"co": "^4.6.0",
"common-tags": "^1.4.0",
- "ember-cli": "^2.11.1",
+ "ember-cli": "^3.1.4",
"ember-cli-app-version": "^3.0.0",
"ember-cli-blueprint-test-helpers": "^0.18.3",
"ember-cli-dependency-checker": "^2.1.0",
@@ -87,11 +91,13 @@
"ember-cli-shims": "^1.0.2",
"ember-cli-sri": "^2.1.0",
"ember-cli-test-loader": "^1.1.0",
- "ember-cli-uglify": "^1.2.0",
+ "ember-cli-uglify": "2.0.0-beta.1",
+ "ember-decorators": "^2.1.0",
"ember-disable-prototype-extensions": "^1.1.0",
"ember-disable-proxy-controllers": "^1.0.0",
"ember-export-application-global": "^1.0.5",
"ember-load-initializers": "^0.6.0",
+ "ember-maybe-import-regenerator": "^0.1.6",
"ember-publisher": "0.0.7",
"ember-qunit-assert-helpers": "^0.2.1",
"ember-resolver": "^4.1.0",
@@ -99,11 +105,15 @@
"ember-source-channel-url": "^1.0.1",
"ember-try": "^0.2.23",
"ember-watson": "^0.7.0",
+ "eslint-config-prettier": "^2.9.0",
+ "eslint-plugin-node": "^6.0.1",
+ "eslint-plugin-prettier": "^2.6.0",
"github": "^1.1.1",
"glob": "^5.0.13",
"loader.js": "^4.5.0",
"mocha": "^2.4.5",
"mocha-only-detector": "0.0.2",
+ "prettier": "^1.12.1",
"rimraf": "2.5.2",
"rsvp": "4.8.0",
"testdouble": "^3.2.6",
diff --git a/testem.js b/testem.js
index 158a909be30..2833711ad47 100644
--- a/testem.js
+++ b/testem.js
@@ -14,8 +14,11 @@ module.exports = {
Chrome: {
mode: 'ci',
args: [
- '--disable-gpu',
'--headless',
+ '--disable-gpu',
+ '--disable-dev-shm-usage',
+ '--disable-software-rasterizer',
+ '--mute-audio',
'--remote-debugging-port=0',
'--window-size=1440,900',
'--no-sandbox'
diff --git a/tests/acceptance/relationships/has-many-test.js b/tests/acceptance/relationships/has-many-test.js
new file mode 100644
index 00000000000..b62329848c1
--- /dev/null
+++ b/tests/acceptance/relationships/has-many-test.js
@@ -0,0 +1,664 @@
+/* eslint-disable */
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import JSONAPIAdapter from 'ember-data/adapters/json-api';
+import Model from 'ember-data/model';
+import { render } from '@ember/test-helpers';
+import hbs from 'htmlbars-inline-precompile';
+import { attr, hasMany, belongsTo } from '@ember-decorators/data';
+import JSONAPISerializer from 'ember-data/serializers/json-api';
+import Store from 'ember-data/store';
+import { resolve, reject } from 'rsvp';
+import { ServerError } from 'ember-data/adapters/errors';
+import Ember from 'ember';
+
+function domListToArray(domList) {
+ return Array.prototype.slice.call(domList);
+}
+
+class Person extends Model {
+ @attr name;
+ @hasMany('person', { async: true, inverse: 'parent' })
+ children;
+ @belongsTo('person', { async: true, inverse: 'children' })
+ parent;
+}
+
+class TestAdapter extends JSONAPIAdapter {
+ setupPayloads(assert, arr) {
+ this.assert = assert;
+ this._payloads = arr;
+ }
+
+ shouldBackgroundReload() {
+ return false;
+ }
+
+ _nextPayload() {
+ let payload = this._payloads.shift();
+
+ if (payload === undefined) {
+ this.assert.ok(false, 'Too many adapter requests have been made!');
+ return resolve({ data: null });
+ }
+
+ if (payload instanceof ServerError) {
+ return reject(payload);
+ }
+ return resolve(payload);
+ }
+
+ // find by link
+ findHasMany() {
+ return this._nextPayload();
+ }
+
+ // find by data with coalesceFindRequests set to true
+ findMany() {
+ return this._nextPayload();
+ }
+
+ // find by partial data / individual records
+ findRecord() {
+ return this._nextPayload();
+ }
+}
+
+function makePeopleWithRelationshipData() {
+ let people = [
+ {
+ type: 'person',
+ id: '1:no-children-or-parent',
+ attributes: { name: 'Chris Has No Children or Parent' },
+ relationships: {
+ children: { data: [] },
+ parent: { data: null },
+ },
+ },
+ {
+ type: 'person',
+ id: '2:has-1-child-no-parent',
+ attributes: {
+ name: 'James has one child and no parent',
+ },
+ relationships: {
+ children: {
+ data: [{ type: 'person', id: '3:has-2-children-and-parent' }],
+ },
+ parent: { data: null },
+ },
+ },
+ {
+ type: 'person',
+ id: '3:has-2-children-and-parent',
+ attributes: {
+ name: 'Kevin has two children and one parent',
+ },
+ relationships: {
+ children: {
+ data: [
+ { type: 'person', id: '4:has-parent-no-children' },
+ { type: 'person', id: '5:has-parent-no-children' },
+ ],
+ },
+ parent: {
+ data: {
+ type: 'person',
+ id: '2:has-1-child-no-parent',
+ },
+ },
+ },
+ },
+ {
+ type: 'person',
+ id: '4:has-parent-no-children',
+ attributes: {
+ name: 'Selena has a parent',
+ },
+ relationships: {
+ children: {
+ data: [],
+ },
+ parent: {
+ data: {
+ type: 'person',
+ id: '3:has-2-children-and-parent',
+ },
+ },
+ },
+ },
+ {
+ type: 'person',
+ id: '5:has-parent-no-children',
+ attributes: {
+ name: 'Sedona has a parent',
+ },
+ relationships: {
+ children: {
+ data: [],
+ },
+ parent: {
+ data: {
+ type: 'person',
+ id: '3:has-2-children-and-parent',
+ },
+ },
+ },
+ },
+ ];
+
+ let peopleHash = {};
+ people.forEach(person => {
+ peopleHash[person.id] = person;
+ });
+
+ return {
+ dict: peopleHash,
+ all: people,
+ };
+}
+
+function makePeopleWithRelationshipLinks(removeData = true) {
+ let people = makePeopleWithRelationshipData();
+ let linkPayloads = (people.links = {});
+
+ people.all.map(person => {
+ Object.keys(person.relationships).forEach(relName => {
+ let rel = person.relationships[relName];
+ let data = rel.data;
+
+ if (removeData === true) {
+ delete rel.data;
+ }
+
+ if (Array.isArray(data)) {
+ data = data.map(ref => people.dict[ref.id]);
+ } else {
+ if (data !== null) {
+ data = people.dict[data.id];
+ }
+ }
+
+ rel.links = {
+ related: `./${person.type}/${person.id}/${relName}`,
+ };
+ linkPayloads[rel.links.related] = {
+ data,
+ };
+ });
+ });
+
+ return people;
+}
+
+module('async has-many rendering tests', function(hooks) {
+ let store;
+ let adapter;
+ setupRenderingTest(hooks);
+
+ hooks.beforeEach(function() {
+ let { owner } = this;
+ owner.register('model:person', Person);
+ owner.register('adapter:application', TestAdapter);
+ owner.register('serializer:application', JSONAPISerializer);
+ owner.register('service:store', Store);
+ store = owner.lookup('service:store');
+ adapter = store.adapterFor('application');
+ });
+
+ module('for data-no-link scenarios', function() {
+ test('We can render an async hasMany', async function(assert) {
+ let people = makePeopleWithRelationshipData();
+ let parent = store.push({
+ data: people.dict['3:has-2-children-and-parent'],
+ });
+
+ adapter.setupPayloads(assert, [
+ { data: people.dict['4:has-parent-no-children'] },
+ { data: people.dict['5:has-parent-no-children'] },
+ ]);
+
+ // render
+ this.set('parent', parent);
+
+ await render(hbs`
+
+ {{#each parent.children as |child|}}
+ - {{child.name}}
+ {{/each}}
+
+ `);
+
+ let items = this.element.querySelectorAll('li');
+ let names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent', 'Sedona has a parent'],
+ 'We rendered the names'
+ );
+ });
+
+ test('Re-rendering an async hasMany does not cause a new fetch', async function(assert) {
+ let people = makePeopleWithRelationshipData();
+ let parent = store.push({
+ data: people.dict['3:has-2-children-and-parent'],
+ });
+
+ adapter.setupPayloads(assert, [
+ { data: people.dict['4:has-parent-no-children'] },
+ { data: people.dict['5:has-parent-no-children'] },
+ ]);
+
+ // render
+ this.set('parent', parent);
+
+ await render(hbs`
+
+ {{#each parent.children as |child|}}
+ - {{child.name}}
+ {{/each}}
+
+ `);
+
+ let items = this.element.querySelectorAll('li');
+ let names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent', 'Sedona has a parent'],
+ 'We rendered the names'
+ );
+
+ this.set('parent', null);
+
+ items = this.element.querySelectorAll('li');
+ assert.ok(items.length === 0, 'We have no items');
+
+ this.set('parent', parent);
+
+ items = this.element.querySelectorAll('li');
+ names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent', 'Sedona has a parent'],
+ 'We rendered the names'
+ );
+ });
+
+ test('Rendering an async hasMany whose fetch fails does not trigger a new request', async function(assert) {
+ assert.expect(12);
+ let people = makePeopleWithRelationshipData();
+ let parent = store.push({
+ data: people.dict['3:has-2-children-and-parent'],
+ });
+
+ adapter.setupPayloads(assert, [
+ { data: people.dict['4:has-parent-no-children'] },
+ new ServerError([], 'hard error while finding 5:has-parent-no-children'),
+ ]);
+
+ // render
+ this.set('parent', parent);
+
+ let originalOnError = Ember.onerror;
+ Ember.onerror = function(e) {
+ assert.ok(true, 'Children promise did reject');
+ assert.equal(
+ e.message,
+ 'hard error while finding 5:has-parent-no-children',
+ 'Rejection has the correct message'
+ );
+ };
+
+ // needed for LTS 2.12 and 2.16
+ Ember.Test.adapter.exception = e => {
+ assert.ok(true, 'Children promise did reject');
+ assert.equal(
+ e.message,
+ 'hard error while finding 5:has-parent-no-children',
+ 'Rejection has the correct message'
+ );
+ };
+
+ await render(hbs`
+
+ {{#each parent.children as |child|}}
+ - {{child.name}}
+ {{/each}}
+
+ `);
+
+ let items = this.element.querySelectorAll('li');
+ let names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent'],
+ 'We rendered only the names for successful requests'
+ );
+
+ let relationshipState = parent.hasMany('children').hasManyRelationship;
+
+ assert.equal(relationshipState.isAsync, true, 'The relationship is async');
+ assert.equal(relationshipState.relationshipIsEmpty, false, 'The relationship is not empty');
+ assert.equal(relationshipState.relationshipIsStale, true, 'The relationship is still stale');
+ assert.equal(
+ relationshipState.allInverseRecordsAreLoaded,
+ false,
+ 'The relationship is missing some or all related resources'
+ );
+ assert.equal(
+ relationshipState.hasAnyRelationshipData,
+ true,
+ 'The relationship knows which record it needs'
+ );
+ assert.equal(
+ relationshipState.fetchPromise === null,
+ true,
+ 'The relationship has no fetchPromise'
+ );
+ assert.equal(
+ relationshipState.hasFailedLoadAttempt === true,
+ true,
+ 'The relationship has attempted a load'
+ );
+ assert.equal(
+ relationshipState._promiseProxy !== null,
+ true,
+ 'The relationship has a loadingPromise'
+ );
+ assert.equal(!!relationshipState.link, false, 'The relationship does not have a link');
+
+ Ember.onerror = originalOnError;
+ });
+ });
+
+ module('for link-no-data scenarios', function() {
+ test('We can render an async hasMany with a link', async function(assert) {
+ let people = makePeopleWithRelationshipLinks(true);
+ let parent = store.push({
+ data: people.dict['3:has-2-children-and-parent'],
+ });
+
+ adapter.setupPayloads(assert, [
+ people.links['./person/3:has-2-children-and-parent/children'],
+ ]);
+
+ // render
+ this.set('parent', parent);
+
+ await render(hbs`
+
+ {{#each parent.children as |child|}}
+ - {{child.name}}
+ {{/each}}
+
+ `);
+
+ let items = this.element.querySelectorAll('li');
+ let names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent', 'Sedona has a parent'],
+ 'We rendered the names'
+ );
+ });
+
+ test('Re-rendering an async hasMany with a link does not cause a new fetch', async function(assert) {
+ let people = makePeopleWithRelationshipLinks(true);
+ let parent = store.push({
+ data: people.dict['3:has-2-children-and-parent'],
+ });
+
+ adapter.setupPayloads(assert, [
+ people.links['./person/3:has-2-children-and-parent/children'],
+ ]);
+
+ // render
+ this.set('parent', parent);
+
+ await render(hbs`
+
+ {{#each parent.children as |child|}}
+ - {{child.name}}
+ {{/each}}
+
+ `);
+
+ let items = this.element.querySelectorAll('li');
+ let names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent', 'Sedona has a parent'],
+ 'We rendered the names'
+ );
+
+ this.set('parent', null);
+
+ items = this.element.querySelectorAll('li');
+ assert.ok(items.length === 0, 'We have no items');
+
+ this.set('parent', parent);
+
+ items = this.element.querySelectorAll('li');
+ names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent', 'Sedona has a parent'],
+ 'We rendered the names'
+ );
+ });
+
+ test('Rendering an async hasMany with a link whose fetch fails does not trigger a new request', async function(assert) {
+ assert.expect(12);
+ let people = makePeopleWithRelationshipLinks(true);
+ let parent = store.push({
+ data: people.dict['3:has-2-children-and-parent'],
+ });
+
+ adapter.setupPayloads(assert, [
+ people.links['./person/3:has-2-children-and-parent/children'],
+ ]);
+
+ adapter.setupPayloads(assert, [
+ new ServerError(
+ [],
+ 'hard error while finding link ./person/3:has-2-children-and-parent/children'
+ ),
+ ]);
+
+ // render
+ this.set('parent', parent);
+
+ let originalOnError = Ember.onerror;
+ Ember.onerror = function(e) {
+ assert.ok(true, 'Children promise did reject');
+ assert.equal(
+ e.message,
+ 'hard error while finding link ./person/3:has-2-children-and-parent/children',
+ 'Rejection has the correct message'
+ );
+ };
+
+ // needed for LTS 2.12 and 2.16
+ Ember.Test.adapter.exception = e => {
+ assert.ok(true, 'Children promise did reject');
+ assert.equal(
+ e.message,
+ 'hard error while finding link ./person/3:has-2-children-and-parent/children',
+ 'Rejection has the correct message'
+ );
+ };
+
+ await render(hbs`
+
+ {{#each parent.children as |child|}}
+ - {{child.name}}
+ {{/each}}
+
+ `);
+
+ let items = this.element.querySelectorAll('li');
+ let names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(names, [], 'We rendered no names');
+
+ let relationshipState = parent.hasMany('children').hasManyRelationship;
+
+ assert.equal(relationshipState.isAsync, true, 'The relationship is async');
+ assert.equal(
+ relationshipState.relationshipIsEmpty,
+ true,
+ 'The relationship is empty because no signal has been received as to true state'
+ );
+ assert.equal(relationshipState.relationshipIsStale, true, 'The relationship is still stale');
+ assert.equal(
+ relationshipState.allInverseRecordsAreLoaded,
+ true,
+ 'The relationship is missing some or all related resources'
+ );
+ assert.equal(
+ relationshipState.hasAnyRelationshipData,
+ false,
+ 'The relationship knows which record it needs'
+ );
+ assert.equal(
+ relationshipState.fetchPromise === null,
+ true,
+ 'The relationship has no fetchPromise'
+ );
+ assert.equal(
+ relationshipState.hasFailedLoadAttempt === true,
+ true,
+ 'The relationship has attempted a load'
+ );
+ assert.equal(
+ relationshipState._promiseProxy !== null,
+ true,
+ 'The relationship has a loadingPromise'
+ );
+ assert.equal(!!relationshipState.link, true, 'The relationship has a link');
+
+ Ember.onerror = originalOnError;
+ });
+ });
+
+ module('for link-and-data scenarios', function() {
+ test('We can render an async hasMany with a link and data', async function(assert) {
+ let people = makePeopleWithRelationshipLinks(false);
+ let parent = store.push({
+ data: people.dict['3:has-2-children-and-parent'],
+ });
+
+ adapter.setupPayloads(assert, [
+ people.links['./person/3:has-2-children-and-parent/children'],
+ ]);
+
+ // render
+ this.set('parent', parent);
+
+ await render(hbs`
+
+ {{#each parent.children as |child|}}
+ - {{child.name}}
+ {{/each}}
+
+ `);
+
+ let items = this.element.querySelectorAll('li');
+ let names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent', 'Sedona has a parent'],
+ 'We rendered the names'
+ );
+ });
+
+ test('Rendering an async hasMany with a link and data where data has been side-loaded does not fetch the link', async function(assert) {
+ let people = makePeopleWithRelationshipLinks(false);
+ let parent = store.push({
+ data: people.dict['3:has-2-children-and-parent'],
+ included: [
+ people.dict['4:has-parent-no-children'],
+ people.dict['5:has-parent-no-children'],
+ ],
+ });
+
+ // no requests should be made
+ adapter.setupPayloads(assert, []);
+
+ // render
+ this.set('parent', parent);
+
+ await render(hbs`
+
+ {{#each parent.children as |child|}}
+ - {{child.name}}
+ {{/each}}
+
+ `);
+
+ let items = this.element.querySelectorAll('li');
+ let names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent', 'Sedona has a parent'],
+ 'We rendered the names'
+ );
+ });
+
+ test('Re-rendering an async hasMany with a link and data does not cause a new fetch', async function(assert) {
+ let people = makePeopleWithRelationshipLinks(false);
+ let parent = store.push({
+ data: people.dict['3:has-2-children-and-parent'],
+ });
+
+ adapter.setupPayloads(assert, [
+ people.links['./person/3:has-2-children-and-parent/children'],
+ ]);
+
+ // render
+ this.set('parent', parent);
+
+ await render(hbs`
+
+ {{#each parent.children as |child|}}
+ - {{child.name}}
+ {{/each}}
+
+ `);
+
+ let items = this.element.querySelectorAll('li');
+ let names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent', 'Sedona has a parent'],
+ 'We rendered the names'
+ );
+
+ this.set('parent', null);
+
+ items = this.element.querySelectorAll('li');
+ assert.ok(items.length === 0, 'We have no items');
+
+ this.set('parent', parent);
+
+ items = this.element.querySelectorAll('li');
+ names = domListToArray(items).map(e => e.textContent);
+
+ assert.deepEqual(
+ names,
+ ['Selena has a parent', 'Sedona has a parent'],
+ 'We rendered the names'
+ );
+ });
+ });
+});
diff --git a/tests/helpers/model-factory-injection.js b/tests/helpers/model-factory-injection.js
index 1a364a43163..1096af16f2e 100644
--- a/tests/helpers/model-factory-injection.js
+++ b/tests/helpers/model-factory-injection.js
@@ -1,5 +1,5 @@
import Ember from 'ember';
-import hasEmberVersion from 'ember-test-helpers/has-ember-version';
+import hasEmberVersion from '@ember/test-helpers/has-ember-version';
const ORIGINAL_MODEL_FACTORY_INJECTIONS = Ember.MODEL_FACTORY_INJECTIONS;
diff --git a/tests/integration/adapter/json-api-adapter-test.js b/tests/integration/adapter/json-api-adapter-test.js
index c945eeb51cf..932ed18bd94 100644
--- a/tests/integration/adapter/json-api-adapter-test.js
+++ b/tests/integration/adapter/json-api-adapter-test.js
@@ -299,13 +299,21 @@ test('find a single record with belongsTo link as object { related }', function(
return run(() => {
return store.findRecord('post', 1).then(post => {
- assert.equal(passedUrl[0], '/posts/1');
+ assert.equal(
+ passedUrl[0],
+ '/posts/1',
+ 'The primary record post:1 was fetched by the correct url'
+ );
assert.equal(post.get('id'), '1');
assert.equal(post.get('title'), 'Ember.js rocks');
return post.get('author').then(author => {
- assert.equal(passedUrl[1], 'http://example.com/user/2');
+ assert.equal(
+ passedUrl[1],
+ 'http://example.com/user/2',
+ 'The relationship user:2 was fetched by the correct url'
+ );
assert.equal(author.get('id'), '2');
assert.equal(author.get('firstName'), 'Yehuda');
@@ -344,13 +352,21 @@ test('find a single record with belongsTo link as object { data }', function(ass
return run(() => {
return store.findRecord('post', 1).then(post => {
- assert.equal(passedUrl[0], '/posts/1');
+ assert.equal(
+ passedUrl[0],
+ '/posts/1',
+ 'The primary record post:1 was fetched by the correct url'
+ );
assert.equal(post.get('id'), '1');
assert.equal(post.get('title'), 'Ember.js rocks');
return post.get('author').then(author => {
- assert.equal(passedUrl[1], '/users/2');
+ assert.equal(
+ passedUrl[1],
+ '/users/2',
+ 'The relationship user:2 was fetched by the correct url'
+ );
assert.equal(author.get('id'), '2');
assert.equal(author.get('firstName'), 'Yehuda');
@@ -435,7 +451,11 @@ test('find a single record with sideloaded belongsTo link as object { data }', f
return run(() => {
return store.findRecord('post', 1).then(post => {
- assert.equal(passedUrl[0], '/posts/1');
+ assert.equal(
+ passedUrl[0],
+ '/posts/1',
+ 'The primary record post:1 was fetched by the correct url'
+ );
assert.equal(post.get('id'), '1');
assert.equal(post.get('title'), 'Ember.js rocks');
diff --git a/tests/integration/relationships/has-many-test.js b/tests/integration/relationships/has-many-test.js
index f73db1f5c7d..28d1204677d 100644
--- a/tests/integration/relationships/has-many-test.js
+++ b/tests/integration/relationships/has-many-test.js
@@ -5,22 +5,12 @@ import {
reset as resetModelFactoryInjections
} from 'dummy/tests/helpers/model-factory-injection';
import { A } from '@ember/array';
-
-import {
- resolve,
- Promise as EmberPromise,
- all,
- reject,
- hash
-} from 'rsvp';
+import { resolve, Promise as EmberPromise, all, reject, hash } from 'rsvp';
import { get } from '@ember/object';
import { run } from '@ember/runloop';
-
import setupStore from 'dummy/tests/helpers/store';
-
import testInDebug from 'dummy/tests/helpers/test-in-debug';
-import { module, test } from 'qunit';
-
+import { module, test, skip } from 'qunit';
import DS from 'ember-data';
let env, store, User, Contact, Email, Phone, Message, Post, Comment;
@@ -867,57 +857,75 @@ test("A hasMany relationship can be reloaded if it was fetched via ids", functio
});
});
-test("A hasMany relationship can be reloaded even if it failed at the first time", function(assert) {
- assert.expect(4);
+test(
+ 'A hasMany relationship can be reloaded even if it failed at the first time',
+ async function(assert) {
+ assert.expect(6);
- Post.reopen({
- comments: DS.hasMany('comment', { async: true })
- });
+ const { store, adapter } = env;
- env.adapter.findRecord = function(store, type, id) {
- return resolve({
- data: {
- id: 1,
- type: 'post',
- relationships: {
- comments: {
- links: { related: "/posts/1/comments" }
- }
- }
- }
+ Post.reopen({
+ comments: DS.hasMany('comment', { async: true }),
});
- };
- let loadingCount = -1;
- env.adapter.findHasMany = function(store, record, link, relationship) {
- loadingCount++;
- if (loadingCount % 2 === 0) {
- return reject();
- } else {
- return resolve({ data: [
- { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } },
- { id: 2, type: 'comment', attributes: { body: "Second" } }
- ]});
- }
- };
- run(function() {
- env.store.findRecord('post', 1).then(function(post) {
- let comments = post.get('comments');
- return comments.catch(function() {
- return comments.reload();
- }).then(function(manyArray) {
- assert.equal(manyArray.get('isLoaded'), true, "the reload worked, comments are now loaded");
- return manyArray.reload().catch(function () {
- assert.equal(manyArray.get('isLoaded'), true, "the second reload failed, comments are still loaded though");
- return manyArray.reload().then(function(reloadedManyArray) {
- assert.equal(reloadedManyArray.get('isLoaded'), true, "the third reload worked, comments are loaded again");
- assert.ok(reloadedManyArray === manyArray, "the many array stays the same");
- });
- });
+ adapter.findRecord = function(store, type, id) {
+ return resolve({
+ data: {
+ id: 1,
+ type: 'post',
+ relationships: {
+ comments: {
+ links: { related: '/posts/1/comments' },
+ },
+ },
+ },
});
+ };
+
+ let loadingCount = -1;
+ adapter.findHasMany = function(store, record, link, relationship) {
+ loadingCount++;
+ if (loadingCount % 2 === 0) {
+ return reject({ data: null });
+ } else {
+ return resolve({
+ data: [
+ { id: 1, type: 'comment', attributes: { body: 'FirstUpdated' } },
+ { id: 2, type: 'comment', attributes: { body: 'Second' } },
+ ],
+ });
+ }
+ };
+
+ let post = await store.findRecord('post', 1);
+ let comments = post.get('comments');
+ let manyArray = await comments.catch(() => {
+ assert.ok(true, 'An error was thrown on the first reload of comments');
+ return comments.reload();
});
- });
-});
+
+ assert.equal(manyArray.get('isLoaded'), true, 'the reload worked, comments are now loaded');
+
+ await manyArray.reload().catch(() => {
+ assert.ok(true, 'An error was thrown on the second reload via manyArray');
+ });
+
+ assert.equal(
+ manyArray.get('isLoaded'),
+ true,
+ 'the second reload failed, comments are still loaded though'
+ );
+
+ let reloadedManyArray = await manyArray.reload();
+
+ assert.equal(
+ reloadedManyArray.get('isLoaded'),
+ true,
+ 'the third reload worked, comments are loaded again'
+ );
+ assert.ok(reloadedManyArray === manyArray, 'the many array stays the same');
+ }
+);
test("A hasMany relationship can be directly reloaded if it was fetched via links", function(assert) {
assert.expect(6);
@@ -1863,70 +1871,81 @@ test("dual non-async HM <-> BT", function(assert) {
});
});
-test("When an unloaded record is added to the hasMany, it gets fetched once the hasMany is accessed even if the hasMany has been already fetched", function(assert) {
+test('When an unloaded record is added to the hasMany, it gets fetched once the hasMany is accessed even if the hasMany has been already fetched', async function(assert) {
+ assert.expect(6);
Post.reopen({
comments: DS.hasMany('comment', { async: true })
});
- env.adapter.findMany = function(store, type, ids, snapshots) {
- return resolve({ data: [
- { id: 1, type: 'comment', attributes: { body: 'first' } },
- { id: 2, type: 'comment', attributes: { body: 'second' } }
- ]});
+ const { store, adapter } = env;
+
+ let findManyCalls = 0;
+ let findRecordCalls = 0;
+
+ adapter.findMany = function(store, type, ids, snapshots) {
+ assert.ok(true, `findMany called ${++findManyCalls}x`);
+ return resolve({
+ data: [
+ { id: 1, type: 'comment', attributes: { body: 'first' } },
+ { id: 2, type: 'comment', attributes: { body: 'second' } },
+ ],
+ });
};
- env.adapter.findRecord = function(store, type, id, snapshot) {
+ adapter.findRecord = function(store, type, id, snapshot) {
+ assert.ok(true, `findRecord called ${++findRecordCalls}x`);
+
return resolve({ data: { id: 3, type: 'comment', attributes: { body: 'third' } } });
};
- let post;
- run(() => {
- env.store.push({
- data: {
- type: 'post',
- id: '1',
- relationships: {
- comments: {
- data: [
- { type: 'comment', id: '1' },
- { type: 'comment', id: '2' }
- ]
- }
- }
- }
- });
- post = env.store.peekRecord('post', 1);
+ let post = store.push({
+ data: {
+ type: 'post',
+ id: '1',
+ relationships: {
+ comments: {
+ data: [{ type: 'comment', id: '1' }, { type: 'comment', id: '2' }],
+ },
+ },
+ },
});
- return run(() => {
- return post.get('comments').then(fetchedComments => {
- assert.equal(fetchedComments.get('length'), 2, 'comments fetched successfully');
- assert.equal(fetchedComments.objectAt(0).get('body'), 'first', 'first comment loaded successfully');
- env.store.push({
- data: {
- type: 'post',
- id: '1',
- relationships: {
- comments: {
- data: [
- { type: 'comment', id: '1' },
- { type: 'comment', id: '2' },
- { type: 'comment', id: '3' }
- ]
- }
- }
- }
- });
+ let fetchedComments = await post.get('comments');
- return post.get('comments').then(newlyFetchedComments => {
- assert.equal(newlyFetchedComments.get('length'), 3, 'all three comments fetched successfully');
- assert.equal(newlyFetchedComments.objectAt(2).get('body'), 'third', 'third comment loaded successfully');
- });
- });
+ assert.equal(fetchedComments.get('length'), 2, 'comments fetched successfully');
+ assert.equal(
+ fetchedComments.objectAt(0).get('body'),
+ 'first',
+ 'first comment loaded successfully'
+ );
+
+ store.push({
+ data: {
+ type: 'post',
+ id: '1',
+ relationships: {
+ comments: {
+ data: [
+ { type: 'comment', id: '1' },
+ { type: 'comment', id: '2' },
+ { type: 'comment', id: '3' },
+ ],
+ },
+ },
+ },
});
+
+ let newlyFetchedComments = await post.get('comments');
+
+ assert.equal(newlyFetchedComments.get('length'), 3, 'all three comments fetched successfully');
+ assert.equal(
+ newlyFetchedComments.objectAt(2).get('body'),
+ 'third',
+ 'third comment loaded successfully'
+ );
});
-testInDebug('A sync hasMany errors out if there are unlaoded records in it', function(assert) {
+skip('A sync hasMany errors out if there are unloaded records in it', function(assert) {
let post = run(() => {
env.store.push({
data: {
@@ -1947,7 +1966,7 @@ testInDebug('A sync hasMany errors out if there are unlaoded records in it', fun
assert.expectAssertion(() => {
run(post, 'get', 'comments');
- }, /You looked up the 'comments' relationship on a 'post' with id 1 but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async \('DS.hasMany\({ async: true }\)'\)/);
+ }, /You looked up the 'comments' relationship on a 'post' with id 1 but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async \(`DS.hasMany\({ async: true }\)`\)/);
});
test('After removing and unloading a record, a hasMany relationship should still be valid', function(assert) {
diff --git a/tests/integration/relationships/json-api-links-test.js b/tests/integration/relationships/json-api-links-test.js
index d92ea3d1879..247f950cbbf 100644
--- a/tests/integration/relationships/json-api-links-test.js
+++ b/tests/integration/relationships/json-api-links-test.js
@@ -1638,31 +1638,35 @@ test(`get+unload+get hasMany with missing data setup from the other side, no lin
attributes: {
name: '@runspired'
},
- relationships: {}
+ relationships: {},
},
included: [
{
type: 'pet',
id: '1',
attributes: {
- name: 'Shen'
+ name: 'Shen',
},
relationships: {
owner: {
data: {
type: 'user',
- id: '1'
- }
- }
- }
- }
- ]
+ id: '1',
+ },
+ },
+ },
+ },
+ ],
}));
+
+ // should trigger a fetch bc we don't consider `pets` to have complete knowledge
let pets = run(() => user.get('pets'));
assert.ok(!!pets, 'We found our pets');
run(() => pets.objectAt(0).unloadRecord());
+
+ // should trigger a findRecord for the unloaded pet
run(() => user.get('pets'));
});
test(`get+reload belongsTo with missing data setup from the other side, no links`, function(assert) {
@@ -1912,12 +1916,12 @@ test('We should not fetch a hasMany relationship with links that we know is empt
// should not fire a request
requestedUser = null;
- failureDescription = 'We fetched the link for a known empty relationship';
+ failureDescription = 'We improperly fetched the link for a known empty relationship';
run(() => user1.get('pets'));
// still should not fire a request
requestedUser = null;
- failureDescription = 'We fetched the link (again) for a known empty relationship';
+ failureDescription = 'We improperly fetched the link (again) for a known empty relationship';
run(() => user1.get('pets'));
// should fire a request
@@ -1926,6 +1930,7 @@ test('We should not fetch a hasMany relationship with links that we know is empt
// should not fire a request
requestedUser = null;
- failureDescription = 'We fetched the link for a previously fetched and found to be empty relationship';
+ failureDescription =
+ 'We improperly fetched the link for a previously fetched and found to be empty relationship';
run(() => user2.get('pets'));
});
diff --git a/tests/integration/relationships/one-to-one-test.js b/tests/integration/relationships/one-to-one-test.js
index c65f848b149..e4b0626cb8c 100644
--- a/tests/integration/relationships/one-to-one-test.js
+++ b/tests/integration/relationships/one-to-one-test.js
@@ -442,10 +442,18 @@ test("Setting a BelongsTo to a promise unwraps the promise before setting- async
run(function() {
newFriend.set('bestFriend', stanleysFriend.get('bestFriend'));
stanley.get('bestFriend').then(function(fetchedUser) {
- assert.equal(fetchedUser, newFriend, 'User relationship was updated correctly');
+ assert.equal(
+ fetchedUser,
+ newFriend,
+ `Stanley's bestFriend relationship was updated correctly to newFriend`
+ );
});
newFriend.get('bestFriend').then(function(fetchedUser) {
- assert.equal(fetchedUser, stanley, 'User relationship was updated correctly');
+ assert.equal(
+ fetchedUser,
+ stanley,
+ `newFriend's bestFriend relationship was updated correctly to be Stanley`
+ );
});
});
});
diff --git a/yarn.lock b/yarn.lock
index 194ada067a3..ed91d3b00c4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,134 @@
# yarn lockfile v1
+"@babel/code-frame@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9"
+ dependencies:
+ "@babel/highlight" "7.0.0-beta.44"
+
+"@babel/generator@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42"
+ dependencies:
+ "@babel/types" "7.0.0-beta.44"
+ jsesc "^2.5.1"
+ lodash "^4.2.0"
+ source-map "^0.5.0"
+ trim-right "^1.0.1"
+
+"@babel/helper-function-name@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd"
+ dependencies:
+ "@babel/helper-get-function-arity" "7.0.0-beta.44"
+ "@babel/template" "7.0.0-beta.44"
+ "@babel/types" "7.0.0-beta.44"
+
+"@babel/helper-get-function-arity@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15"
+ dependencies:
+ "@babel/types" "7.0.0-beta.44"
+
+"@babel/helper-split-export-declaration@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc"
+ dependencies:
+ "@babel/types" "7.0.0-beta.44"
+
+"@babel/highlight@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5"
+ dependencies:
+ chalk "^2.0.0"
+ esutils "^2.0.2"
+ js-tokens "^3.0.0"
+
+"@babel/template@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f"
+ dependencies:
+ "@babel/code-frame" "7.0.0-beta.44"
+ "@babel/types" "7.0.0-beta.44"
+ babylon "7.0.0-beta.44"
+ lodash "^4.2.0"
+
+"@babel/traverse@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966"
+ dependencies:
+ "@babel/code-frame" "7.0.0-beta.44"
+ "@babel/generator" "7.0.0-beta.44"
+ "@babel/helper-function-name" "7.0.0-beta.44"
+ "@babel/helper-split-export-declaration" "7.0.0-beta.44"
+ "@babel/types" "7.0.0-beta.44"
+ babylon "7.0.0-beta.44"
+ debug "^3.1.0"
+ globals "^11.1.0"
+ invariant "^2.2.0"
+ lodash "^4.2.0"
+
+"@babel/types@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757"
+ dependencies:
+ esutils "^2.0.2"
+ lodash "^4.2.0"
+ to-fast-properties "^2.0.0"
+
+"@ember-decorators/babel-transforms@^2.0.0":
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/@ember-decorators/babel-transforms/-/babel-transforms-2.0.1.tgz#75b668cfe996fa920c940ad723be015cddf904db"
+ dependencies:
+ babel-plugin-transform-class-properties "^6.24.1"
+ babel-plugin-transform-decorators-legacy "^1.3.4"
+ ember-cli-babel "^6.6.0"
+ ember-cli-version-checker "^2.1.0"
+
+"@ember-decorators/component@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/@ember-decorators/component/-/component-2.1.0.tgz#846ad4197a06c9814d02654e947c023d35107cee"
+ dependencies:
+ "@ember-decorators/utils" "^2.1.0"
+ ember-cli-babel "^6.6.0"
+
+"@ember-decorators/controller@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/@ember-decorators/controller/-/controller-2.1.0.tgz#57a7be3d4eaa18e5021096d404417b1b943e7124"
+ dependencies:
+ "@ember-decorators/utils" "^2.1.0"
+ ember-cli-babel "^6.6.0"
+
+"@ember-decorators/data@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/@ember-decorators/data/-/data-2.1.0.tgz#df29cc4bb21b7f246a02f810e2c7b56bd6f25294"
+ dependencies:
+ "@ember-decorators/utils" "^2.1.0"
+ ember-cli-babel "^6.6.0"
+
+"@ember-decorators/object@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/@ember-decorators/object/-/object-2.1.0.tgz#725c790c030299a4bc8c15f21048c3c0abc1499c"
+ dependencies:
+ "@ember-decorators/utils" "^2.1.0"
+ ember-cli-babel "^6.6.0"
+ ember-compatibility-helpers "^1.0.0"
+
+"@ember-decorators/service@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/@ember-decorators/service/-/service-2.1.0.tgz#c6bbfd34fbb9fb19317ab2be351d8577701e5315"
+ dependencies:
+ "@ember-decorators/utils" "^2.1.0"
+ ember-cli-babel "^6.6.0"
+
+"@ember-decorators/utils@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/@ember-decorators/utils/-/utils-2.1.0.tgz#cd354ff59ce0d5faa74880c15db0f72fefe6dc70"
+ dependencies:
+ ember-cli-babel "^6.6.0"
+ ember-compatibility-helpers "^1.0.0"
+
"@ember/ordered-set@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@ember/ordered-set/-/ordered-set-1.0.0.tgz#cf9ab5fd7510bcad370370ebcded705f6d1c542b"
@@ -105,9 +233,9 @@ amd-name-resolver@0.0.7:
dependencies:
ensure-posix-path "^1.0.1"
-amd-name-resolver@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/amd-name-resolver/-/amd-name-resolver-1.0.0.tgz#0e593b28d6fa3326ab1798107edaea961046e8d8"
+amd-name-resolver@1.2.0, amd-name-resolver@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/amd-name-resolver/-/amd-name-resolver-1.2.0.tgz#fc41b3848824b557313897d71f8d5a0184fbe679"
dependencies:
ensure-posix-path "^1.0.1"
@@ -299,7 +427,7 @@ async-each@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
-async-promise-queue@^1.0.3:
+async-promise-queue@^1.0.3, async-promise-queue@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/async-promise-queue/-/async-promise-queue-1.0.4.tgz#308baafbc74aff66a0bb6e7f4a18d4fe8434440c"
dependencies:
@@ -441,6 +569,17 @@ babel-core@^6.14.0, babel-core@^6.26.0:
slash "^1.0.0"
source-map "^0.5.6"
+babel-eslint@^8.0.0:
+ version "8.2.3"
+ resolved "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.3.tgz#1a2e6681cc9bc4473c32899e59915e19cd6733cf"
+ dependencies:
+ "@babel/code-frame" "7.0.0-beta.44"
+ "@babel/traverse" "7.0.0-beta.44"
+ "@babel/types" "7.0.0-beta.44"
+ babylon "7.0.0-beta.44"
+ eslint-scope "~3.7.1"
+ eslint-visitor-keys "^1.0.0"
+
babel-generator@^6.26.0:
version "6.26.1"
resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
@@ -655,6 +794,14 @@ babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
+babel-plugin-syntax-class-properties@^6.8.0:
+ version "6.13.0"
+ resolved "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
+
+babel-plugin-syntax-decorators@^6.1.18:
+ version "6.13.0"
+ resolved "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b"
+
babel-plugin-syntax-exponentiation-operator@^6.8.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
@@ -671,6 +818,23 @@ babel-plugin-transform-async-to-generator@^6.22.0:
babel-plugin-syntax-async-functions "^6.8.0"
babel-runtime "^6.22.0"
+babel-plugin-transform-class-properties@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
+ dependencies:
+ babel-helper-function-name "^6.24.1"
+ babel-plugin-syntax-class-properties "^6.8.0"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+
+babel-plugin-transform-decorators-legacy@^1.3.4:
+ version "1.3.5"
+ resolved "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz#0e492dffa0edd70529072887f8aa86d4dd8b40a1"
+ dependencies:
+ babel-plugin-syntax-decorators "^6.1.18"
+ babel-runtime "^6.2.0"
+ babel-template "^6.3.0"
+
babel-plugin-transform-es2015-arrow-functions@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
@@ -876,7 +1040,7 @@ babel-plugin-undefined-to-void@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/babel-plugin-undefined-to-void/-/babel-plugin-undefined-to-void-1.1.6.tgz#7f578ef8b78dfae6003385d8417a61eda06e2f81"
-babel-polyfill@^6.16.0:
+babel-polyfill@^6.16.0, babel-polyfill@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153"
dependencies:
@@ -919,6 +1083,41 @@ babel-preset-env@^1.5.1:
invariant "^2.2.2"
semver "^5.3.0"
+babel-preset-env@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a"
+ dependencies:
+ babel-plugin-check-es2015-constants "^6.22.0"
+ babel-plugin-syntax-trailing-function-commas "^6.22.0"
+ babel-plugin-transform-async-to-generator "^6.22.0"
+ babel-plugin-transform-es2015-arrow-functions "^6.22.0"
+ babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
+ babel-plugin-transform-es2015-block-scoping "^6.23.0"
+ babel-plugin-transform-es2015-classes "^6.23.0"
+ babel-plugin-transform-es2015-computed-properties "^6.22.0"
+ babel-plugin-transform-es2015-destructuring "^6.23.0"
+ babel-plugin-transform-es2015-duplicate-keys "^6.22.0"
+ babel-plugin-transform-es2015-for-of "^6.23.0"
+ babel-plugin-transform-es2015-function-name "^6.22.0"
+ babel-plugin-transform-es2015-literals "^6.22.0"
+ babel-plugin-transform-es2015-modules-amd "^6.22.0"
+ babel-plugin-transform-es2015-modules-commonjs "^6.23.0"
+ babel-plugin-transform-es2015-modules-systemjs "^6.23.0"
+ babel-plugin-transform-es2015-modules-umd "^6.23.0"
+ babel-plugin-transform-es2015-object-super "^6.22.0"
+ babel-plugin-transform-es2015-parameters "^6.23.0"
+ babel-plugin-transform-es2015-shorthand-properties "^6.22.0"
+ babel-plugin-transform-es2015-spread "^6.22.0"
+ babel-plugin-transform-es2015-sticky-regex "^6.22.0"
+ babel-plugin-transform-es2015-template-literals "^6.22.0"
+ babel-plugin-transform-es2015-typeof-symbol "^6.23.0"
+ babel-plugin-transform-es2015-unicode-regex "^6.22.0"
+ babel-plugin-transform-exponentiation-operator "^6.22.0"
+ babel-plugin-transform-regenerator "^6.22.0"
+ browserslist "^3.2.6"
+ invariant "^2.2.2"
+ semver "^5.3.0"
+
babel-register@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
@@ -937,14 +1136,14 @@ babel-runtime@^5.0.0:
dependencies:
core-js "^1.0.0"
-babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
dependencies:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
-babel-template@^6.24.1, babel-template@^6.26.0:
+babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
dependencies:
@@ -985,6 +1184,10 @@ babel6-plugin-strip-heimdall@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/babel6-plugin-strip-heimdall/-/babel6-plugin-strip-heimdall-6.0.1.tgz#35f80eddec1f7fffdc009811dfbd46d9965072b6"
+babylon@7.0.0-beta.44:
+ version "7.0.0-beta.44"
+ resolved "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d"
+
babylon@^5.8.38:
version "5.8.38"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-5.8.38.tgz#ec9b120b11bf6ccd4173a18bf217e60b79859ffd"
@@ -1211,11 +1414,20 @@ broccoli-babel-transpiler@^6.0.0, broccoli-babel-transpiler@^6.1.2:
rsvp "^3.5.0"
workerpool "^2.3.0"
-broccoli-brocfile-loader@^0.18.0:
- version "0.18.0"
- resolved "https://registry.yarnpkg.com/broccoli-brocfile-loader/-/broccoli-brocfile-loader-0.18.0.tgz#2e86021c805c34ffc8d29a2fb721cf273e819e4b"
+broccoli-babel-transpiler@^6.4.2:
+ version "6.4.3"
+ resolved "https://registry.npmjs.org/broccoli-babel-transpiler/-/broccoli-babel-transpiler-6.4.3.tgz#06e399298d41700cdc10d675b1d808a89ef6b2d0"
dependencies:
- findup-sync "^0.4.2"
+ babel-core "^6.26.0"
+ broccoli-funnel "^2.0.1"
+ broccoli-merge-trees "^2.0.0"
+ broccoli-persistent-filter "^1.4.3"
+ clone "^2.0.0"
+ hash-for-dep "^1.2.3"
+ heimdalljs-logger "^0.1.7"
+ json-stable-stringify "^1.0.0"
+ rsvp "^4.8.2"
+ workerpool "^2.3.0"
broccoli-builder@^0.18.8:
version "0.18.11"
@@ -1291,7 +1503,7 @@ broccoli-config-replace@^1.1.2:
debug "^2.2.0"
fs-extra "^0.24.0"
-broccoli-debug@^0.6.1, broccoli-debug@^0.6.2, broccoli-debug@^0.6.3:
+broccoli-debug@^0.6.1, broccoli-debug@^0.6.2, broccoli-debug@^0.6.3, broccoli-debug@^0.6.4:
version "0.6.4"
resolved "https://registry.yarnpkg.com/broccoli-debug/-/broccoli-debug-0.6.4.tgz#986eb3d2005e00e3bb91f9d0a10ab137210cd150"
dependencies:
@@ -1413,9 +1625,9 @@ broccoli-merge-trees@^2.0.0:
broccoli-plugin "^1.3.0"
merge-trees "^1.0.1"
-broccoli-middleware@^1.0.0:
+broccoli-middleware@^1.2.1:
version "1.2.1"
- resolved "https://registry.yarnpkg.com/broccoli-middleware/-/broccoli-middleware-1.2.1.tgz#a21f255f8bfe5a21c2f0fbf2417addd9d24c9436"
+ resolved "https://registry.npmjs.org/broccoli-middleware/-/broccoli-middleware-1.2.1.tgz#a21f255f8bfe5a21c2f0fbf2417addd9d24c9436"
dependencies:
handlebars "^4.0.4"
mime-types "^2.1.18"
@@ -1424,7 +1636,7 @@ broccoli-node-info@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/broccoli-node-info/-/broccoli-node-info-1.1.0.tgz#3aa2e31e07e5bdb516dd25214f7c45ba1c459412"
-broccoli-persistent-filter@^1.0.3, broccoli-persistent-filter@^1.1.5, broccoli-persistent-filter@^1.1.6, broccoli-persistent-filter@^1.2.0, broccoli-persistent-filter@^1.4.0, broccoli-persistent-filter@^1.4.2:
+broccoli-persistent-filter@^1.0.3, broccoli-persistent-filter@^1.1.5, broccoli-persistent-filter@^1.1.6, broccoli-persistent-filter@^1.2.0, broccoli-persistent-filter@^1.4.0, broccoli-persistent-filter@^1.4.2, broccoli-persistent-filter@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-1.4.3.tgz#3511bc52fc53740cda51621f58a28152d9911bc1"
dependencies:
@@ -1537,7 +1749,7 @@ broccoli-test-helper@^1.2.0:
rimraf "^2.5.4"
walk-sync "^0.3.1"
-broccoli-uglify-sourcemap@^1.0.0, broccoli-uglify-sourcemap@^1.0.1:
+broccoli-uglify-sourcemap@^1.0.1:
version "1.5.2"
resolved "https://registry.yarnpkg.com/broccoli-uglify-sourcemap/-/broccoli-uglify-sourcemap-1.5.2.tgz#04f84ab0db539031fa868ccfa563c9932d50cedb"
dependencies:
@@ -1551,6 +1763,22 @@ broccoli-uglify-sourcemap@^1.0.0, broccoli-uglify-sourcemap@^1.0.1:
uglify-js "^2.7.0"
walk-sync "^0.1.3"
+broccoli-uglify-sourcemap@^2.0.0-beta.1:
+ version "2.2.0"
+ resolved "https://registry.npmjs.org/broccoli-uglify-sourcemap/-/broccoli-uglify-sourcemap-2.2.0.tgz#2ff49389bdf342a550c3596750ba2dde95a8f7d4"
+ dependencies:
+ async-promise-queue "^1.0.4"
+ broccoli-plugin "^1.2.1"
+ debug "^3.1.0"
+ lodash.defaultsdeep "^4.6.0"
+ matcher-collection "^1.0.5"
+ mkdirp "^0.5.0"
+ source-map-url "^0.4.0"
+ symlink-or-copy "^1.0.1"
+ terser "^3.7.5"
+ walk-sync "^0.3.2"
+ workerpool "^2.3.0"
+
broccoli-writer@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/broccoli-writer/-/broccoli-writer-0.1.1.tgz#d4d71aa8f2afbc67a3866b91a2da79084b96ab2d"
@@ -1595,6 +1823,13 @@ browserslist@^2.1.2:
caniuse-lite "^1.0.30000792"
electron-to-chromium "^1.3.30"
+browserslist@^3.2.6:
+ version "3.2.8"
+ resolved "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6"
+ dependencies:
+ caniuse-lite "^1.0.30000844"
+ electron-to-chromium "^1.3.47"
+
bser@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719"
@@ -1696,6 +1931,10 @@ caniuse-lite@^1.0.30000792:
version "1.0.30000813"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000813.tgz#7b25e27fdfb8d133f3c932b01f77452140fcc6c9"
+caniuse-lite@^1.0.30000844:
+ version "1.0.30000856"
+ resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000856.tgz#ecc16978135a6f219b138991eb62009d25ee8daa"
+
capture-exit@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f"
@@ -1777,7 +2016,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1:
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
dependencies:
@@ -1966,7 +2205,7 @@ commander@2.8.x:
dependencies:
graceful-readlink ">= 1.0.0"
-commander@^2.5.0, commander@^2.6.0:
+commander@^2.5.0, commander@^2.6.0, commander@~2.14.1:
version "2.14.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa"
@@ -2074,9 +2313,9 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
-console-ui@^2.0.0:
+console-ui@^2.1.0:
version "2.2.2"
- resolved "https://registry.yarnpkg.com/console-ui/-/console-ui-2.2.2.tgz#b294a2934de869dd06789ab4be69555411edef29"
+ resolved "https://registry.npmjs.org/console-ui/-/console-ui-2.2.2.tgz#b294a2934de869dd06789ab4be69555411edef29"
dependencies:
chalk "^2.1.0"
inquirer "^2"
@@ -2417,6 +2656,10 @@ electron-to-chromium@^1.3.30:
version "1.3.36"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.36.tgz#0eabf71a9ebea9013fb1cc35a390e068624f27e8"
+electron-to-chromium@^1.3.47:
+ version "1.3.49"
+ resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.49.tgz#651384b0d81f078a96639b2b36975141b7915004"
+
ember-cli-app-version@^3.0.0:
version "3.1.3"
resolved "https://registry.yarnpkg.com/ember-cli-app-version/-/ember-cli-app-version-3.1.3.tgz#26d25f5e653ff0106f0b39da6d75518ba8ed282d"
@@ -2452,6 +2695,24 @@ ember-cli-babel@^5.0.0, ember-cli-babel@^5.1.10, ember-cli-babel@^5.1.5, ember-c
ember-cli-version-checker "^1.0.2"
resolve "^1.1.2"
+ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.6.0:
+ version "6.14.1"
+ resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-6.14.1.tgz#796339229035910b625593caffbc2683792ada68"
+ dependencies:
+ amd-name-resolver "1.2.0"
+ babel-plugin-debug-macros "^0.1.11"
+ babel-plugin-ember-modules-api-polyfill "^2.3.0"
+ babel-plugin-transform-es2015-modules-amd "^6.24.0"
+ babel-polyfill "^6.26.0"
+ babel-preset-env "^1.7.0"
+ broccoli-babel-transpiler "^6.4.2"
+ broccoli-debug "^0.6.4"
+ broccoli-funnel "^2.0.0"
+ broccoli-source "^1.1.0"
+ clone "^2.0.0"
+ ember-cli-version-checker "^2.1.2"
+ semver "^5.5.0"
+
ember-cli-blueprint-test-helpers@^0.18.3:
version "0.18.3"
resolved "https://registry.yarnpkg.com/ember-cli-blueprint-test-helpers/-/ember-cli-blueprint-test-helpers-0.18.3.tgz#945c606d855f0263f5e8c03522e4040a74f259cc"
@@ -2496,10 +2757,6 @@ ember-cli-get-component-path-option@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ember-cli-get-component-path-option/-/ember-cli-get-component-path-option-1.0.0.tgz#0d7b595559e2f9050abed804f1d8eff1b08bc771"
-ember-cli-get-dependency-depth@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/ember-cli-get-dependency-depth/-/ember-cli-get-dependency-depth-1.0.0.tgz#e0afecf82a2d52f00f28ab468295281aec368d11"
-
ember-cli-htmlbars-inline-precompile@^0.4.3:
version "0.4.4"
resolved "https://registry.yarnpkg.com/ember-cli-htmlbars-inline-precompile/-/ember-cli-htmlbars-inline-precompile-0.4.4.tgz#24a7617152630d64a047e553b72e00963a4f8d73"
@@ -2571,28 +2828,6 @@ ember-cli-is-package-missing@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ember-cli-is-package-missing/-/ember-cli-is-package-missing-1.0.0.tgz#6e6184cafb92635dd93ca6c946b104292d4e3390"
-ember-cli-legacy-blueprints@^0.2.0:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/ember-cli-legacy-blueprints/-/ember-cli-legacy-blueprints-0.2.1.tgz#480f37cb83f1eda2d46bbc7d07c59ea2e8ce9b84"
- dependencies:
- chalk "^2.3.0"
- ember-cli-get-component-path-option "^1.0.0"
- ember-cli-get-dependency-depth "^1.0.0"
- ember-cli-is-package-missing "^1.0.0"
- ember-cli-lodash-subset "^2.0.1"
- ember-cli-normalize-entity-name "^1.0.0"
- ember-cli-path-utils "^1.0.0"
- ember-cli-string-utils "^1.0.0"
- ember-cli-test-info "^1.0.0"
- ember-cli-valid-component-name "^1.0.0"
- ember-cli-version-checker "^2.1.0"
- ember-router-generator "^1.0.0"
- exists-sync "0.0.3"
- fs-extra "^4.0.0"
- inflection "^1.7.1"
- rsvp "^4.7.0"
- silent-error "^1.0.0"
-
ember-cli-lodash-subset@^1.0.7:
version "1.0.12"
resolved "https://registry.yarnpkg.com/ember-cli-lodash-subset/-/ember-cli-lodash-subset-1.0.12.tgz#af2e77eba5dcb0d77f3308d3a6fd7d3450f6e537"
@@ -2685,11 +2920,12 @@ ember-cli-test-loader@^2.2.0:
dependencies:
ember-cli-babel "^6.8.1"
-ember-cli-uglify@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/ember-cli-uglify/-/ember-cli-uglify-1.2.0.tgz#3208c32b54bc2783056e8bb0d5cfe9bbaf17ffb2"
+ember-cli-uglify@2.0.0-beta.1:
+ version "2.0.0-beta.1"
+ resolved "https://registry.npmjs.org/ember-cli-uglify/-/ember-cli-uglify-2.0.0-beta.1.tgz#9cb509f7f3f3342271df4a59b41176f0ffbda48a"
dependencies:
- broccoli-uglify-sourcemap "^1.0.0"
+ broccoli-uglify-sourcemap "^2.0.0-beta.1"
+ lodash.defaultsdeep "^4.6.0"
ember-cli-valid-component-name@^1.0.0:
version "1.0.0"
@@ -2710,16 +2946,22 @@ ember-cli-version-checker@^2.0.0, ember-cli-version-checker@^2.1.0:
resolve "^1.3.3"
semver "^5.3.0"
-ember-cli@^2.11.1:
- version "2.18.2"
- resolved "https://registry.yarnpkg.com/ember-cli/-/ember-cli-2.18.2.tgz#bb15313a15139a85248a86d203643f918ba40f57"
+ember-cli-version-checker@^2.1.1, ember-cli-version-checker@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-2.1.2.tgz#305ce102390c66e4e0f1432dea9dc5c7c19fed98"
+ dependencies:
+ resolve "^1.3.3"
+ semver "^5.3.0"
+
+ember-cli@^3.1.4:
+ version "3.1.4"
+ resolved "https://registry.npmjs.org/ember-cli/-/ember-cli-3.1.4.tgz#95f7ff4302d535619b5d5ff1c7040877a67d4468"
dependencies:
- amd-name-resolver "1.0.0"
+ amd-name-resolver "^1.2.0"
babel-plugin-transform-es2015-modules-amd "^6.24.0"
bower-config "^1.3.0"
bower-endpoint-parser "0.2.2"
broccoli-babel-transpiler "^6.0.0"
- broccoli-brocfile-loader "^0.18.0"
broccoli-builder "^0.18.8"
broccoli-concat "^3.2.2"
broccoli-config-loader "^1.0.0"
@@ -2728,7 +2970,7 @@ ember-cli@^2.11.1:
broccoli-funnel "^2.0.0"
broccoli-funnel-reducer "^1.0.0"
broccoli-merge-trees "^2.0.0"
- broccoli-middleware "^1.0.0"
+ broccoli-middleware "^1.2.1"
broccoli-source "^1.1.0"
broccoli-stew "^1.2.0"
calculate-cache-key-for-tree "^1.0.0"
@@ -2737,32 +2979,31 @@ ember-cli@^2.11.1:
clean-base-url "^1.0.0"
compression "^1.4.4"
configstore "^3.0.0"
- console-ui "^2.0.0"
+ console-ui "^2.1.0"
core-object "^3.1.3"
dag-map "^2.0.2"
diff "^3.2.0"
ember-cli-broccoli-sane-watcher "^2.0.4"
ember-cli-is-package-missing "^1.0.0"
- ember-cli-legacy-blueprints "^0.2.0"
ember-cli-lodash-subset "^2.0.1"
ember-cli-normalize-entity-name "^1.0.0"
ember-cli-preprocess-registry "^3.1.0"
ember-cli-string-utils "^1.0.0"
- ember-try "^0.2.15"
ensure-posix-path "^1.0.2"
- execa "^0.8.0"
+ execa "^0.9.0"
exists-sync "0.0.4"
exit "^0.1.2"
express "^4.12.3"
filesize "^3.1.3"
find-up "^2.1.0"
- fs-extra "^4.0.0"
+ find-yarn-workspace-root "^1.0.0"
+ fs-extra "^5.0.0"
fs-tree-diff "^0.5.2"
get-caller-file "^1.0.0"
git-repo-info "^1.4.1"
- glob "7.1.1"
+ glob "^7.1.2"
heimdalljs "^0.2.3"
- heimdalljs-fs-monitor "^0.1.0"
+ heimdalljs-fs-monitor "^0.2.0"
heimdalljs-graph "^0.3.1"
heimdalljs-logger "^0.1.7"
http-proxy "^1.9.0"
@@ -2797,7 +3038,16 @@ ember-cli@^2.11.1:
uuid "^3.0.0"
validate-npm-package-name "^3.0.0"
walk-sync "^0.3.0"
- yam "0.0.22"
+ watch-detector "^0.1.0"
+ yam "^0.0.24"
+
+ember-compatibility-helpers@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/ember-compatibility-helpers/-/ember-compatibility-helpers-1.0.0.tgz#616b22d2e14b4c6a1f4441e5390a49abf52b3c68"
+ dependencies:
+ babel-plugin-debug-macros "^0.1.11"
+ ember-cli-version-checker "^2.1.1"
+ semver "^5.4.1"
ember-compatibility-helpers@^1.0.0-beta.2:
version "1.0.0-beta.2"
@@ -2807,6 +3057,18 @@ ember-compatibility-helpers@^1.0.0-beta.2:
ember-cli-version-checker "^2.0.0"
semver "^5.4.1"
+ember-decorators@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/ember-decorators/-/ember-decorators-2.1.0.tgz#4910835da3517c633532c8d6fcfcf026e13701c0"
+ dependencies:
+ "@ember-decorators/component" "^2.1.0"
+ "@ember-decorators/controller" "^2.1.0"
+ "@ember-decorators/data" "^2.1.0"
+ "@ember-decorators/object" "^2.1.0"
+ "@ember-decorators/service" "^2.1.0"
+ ember-cli-babel "^6.0.0"
+ semver "^5.5.0"
+
ember-disable-prototype-extensions@^1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/ember-disable-prototype-extensions/-/ember-disable-prototype-extensions-1.1.3.tgz#1969135217654b5e278f9fe2d9d4e49b5720329e"
@@ -2835,6 +3097,15 @@ ember-load-initializers@^0.6.0:
dependencies:
ember-cli-babel "^5.1.6"
+ember-maybe-import-regenerator@^0.1.6:
+ version "0.1.6"
+ resolved "https://registry.npmjs.org/ember-maybe-import-regenerator/-/ember-maybe-import-regenerator-0.1.6.tgz#35d41828afa6d6a59bc0da3ce47f34c573d776ca"
+ dependencies:
+ broccoli-funnel "^1.0.1"
+ broccoli-merge-trees "^1.0.0"
+ ember-cli-babel "^6.0.0-beta.4"
+ regenerator-runtime "^0.9.5"
+
ember-publisher@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/ember-publisher/-/ember-publisher-0.0.7.tgz#865ca69ef47bafb38120a84244aa58b950ca4850"
@@ -2880,7 +3151,7 @@ ember-rfc176-data@^0.3.0, ember-rfc176-data@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/ember-rfc176-data/-/ember-rfc176-data-0.3.1.tgz#6a5a4b8b82ec3af34f3010965fa96b936ca94519"
-ember-router-generator@^1.0.0, ember-router-generator@^1.2.3:
+ember-router-generator@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/ember-router-generator/-/ember-router-generator-1.2.3.tgz#8ed2ca86ff323363120fc14278191e9e8f1315ee"
dependencies:
@@ -2926,7 +3197,7 @@ ember-try-config@^2.2.0:
rsvp "^3.2.1"
semver "^5.1.0"
-ember-try@^0.2.15, ember-try@^0.2.23:
+ember-try@^0.2.23:
version "0.2.23"
resolved "https://registry.yarnpkg.com/ember-try/-/ember-try-0.2.23.tgz#39b57141b4907541d0ac8b503d211e6946b08718"
dependencies:
@@ -3098,6 +3369,39 @@ escope@^3.6.0:
esrecurse "^4.1.0"
estraverse "^4.1.1"
+eslint-config-prettier@^2.9.0:
+ version "2.9.0"
+ resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3"
+ dependencies:
+ get-stdin "^5.0.1"
+
+eslint-plugin-node@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz#bf19642298064379315d7a4b2a75937376fa05e4"
+ dependencies:
+ ignore "^3.3.6"
+ minimatch "^3.0.4"
+ resolve "^1.3.3"
+ semver "^5.4.1"
+
+eslint-plugin-prettier@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7"
+ dependencies:
+ fast-diff "^1.1.1"
+ jest-docblock "^21.0.0"
+
+eslint-scope@~3.7.1:
+ version "3.7.1"
+ resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
+ dependencies:
+ esrecurse "^4.1.0"
+ estraverse "^4.1.1"
+
+eslint-visitor-keys@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
+
eslint@^2.13.0:
version "2.13.1"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-2.13.1.tgz#e4cc8fa0f009fb829aaae23855a29360be1f6c11"
@@ -3222,18 +3526,6 @@ exec-sh@^0.2.0:
dependencies:
merge "^1.1.3"
-execa@^0.8.0:
- version "0.8.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da"
- dependencies:
- cross-spawn "^5.0.1"
- get-stream "^3.0.0"
- is-stream "^1.1.0"
- npm-run-path "^2.0.0"
- p-finally "^1.0.0"
- signal-exit "^3.0.0"
- strip-eof "^1.0.0"
-
execa@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.9.0.tgz#adb7ce62cf985071f60580deb4a88b9e34712d01"
@@ -3393,6 +3685,10 @@ fake-xml-http-request@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-1.6.0.tgz#bd0ac79ae3e2660098282048a12c730a6f64d550"
+fast-diff@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
+
fast-levenshtein@~2.0.4:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
@@ -3504,6 +3800,13 @@ find-up@^2.1.0:
dependencies:
locate-path "^2.0.0"
+find-yarn-workspace-root@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.1.0.tgz#9817b6748cb90719f4dc37b4538bb200c697356f"
+ dependencies:
+ fs-extra "^4.0.3"
+ micromatch "^3.1.4"
+
findup-sync@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
@@ -3513,15 +3816,6 @@ findup-sync@2.0.0:
micromatch "^3.0.4"
resolve-dir "^1.0.1"
-findup-sync@^0.4.2:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.4.3.tgz#40043929e7bc60adf0b7f4827c4c6e75a0deca12"
- dependencies:
- detect-file "^0.1.0"
- is-glob "^2.0.1"
- micromatch "^2.3.7"
- resolve-dir "^0.1.0"
-
findup-sync@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-1.0.0.tgz#6f7e4b57b6ee3a4037b4414eaedea3f58f71e0ec"
@@ -3667,9 +3961,17 @@ fs-extra@^2.0.0:
graceful-fs "^4.1.2"
jsonfile "^2.1.0"
-fs-extra@^4.0.0:
+fs-extra@^4.0.0, fs-extra@^4.0.2, fs-extra@^4.0.3:
version "4.0.3"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
+ resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
+ dependencies:
+ graceful-fs "^4.1.2"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
+
+fs-extra@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd"
dependencies:
graceful-fs "^4.1.2"
jsonfile "^4.0.0"
@@ -3761,6 +4063,10 @@ get-stdin@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+get-stdin@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
+
get-stream@3.0.0, get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
@@ -3819,17 +4125,6 @@ glob@3.2.11:
inherits "2"
minimatch "0.3"
-glob@7.1.1:
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.0.2"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
glob@^4.3.2:
version "4.5.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f"
@@ -3849,7 +4144,7 @@ glob@^5.0.10, glob@^5.0.13, glob@^5.0.15:
once "^1.3.0"
path-is-absolute "^1.0.0"
-glob@^7.0.0, glob@^7.0.3, glob@^7.0.4, glob@^7.0.5, glob@^7.1.0:
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.4, glob@^7.0.5, glob@^7.1.0, glob@^7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
dependencies:
@@ -3894,6 +4189,10 @@ global-prefix@^1.0.1:
is-windows "^1.0.1"
which "^1.2.14"
+globals@^11.1.0:
+ version "11.7.0"
+ resolved "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673"
+
globals@^6.4.0:
version "6.4.1"
resolved "https://registry.yarnpkg.com/globals/-/globals-6.4.1.tgz#8498032b3b6d1cc81eebc5f79690d8fe29fabf4f"
@@ -4045,7 +4344,7 @@ has-values@^1.0.0:
is-number "^3.0.0"
kind-of "^4.0.0"
-hash-for-dep@^1.0.2:
+hash-for-dep@^1.0.2, hash-for-dep@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/hash-for-dep/-/hash-for-dep-1.2.3.tgz#5ec69fca32c23523972d52acb5bb65ffc3664cab"
dependencies:
@@ -4072,9 +4371,9 @@ hawk@3.1.3, hawk@~3.1.3:
hoek "2.x.x"
sntp "1.x.x"
-heimdalljs-fs-monitor@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/heimdalljs-fs-monitor/-/heimdalljs-fs-monitor-0.1.0.tgz#d404a65688c6714c485469ed3495da4853440272"
+heimdalljs-fs-monitor@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.npmjs.org/heimdalljs-fs-monitor/-/heimdalljs-fs-monitor-0.2.1.tgz#b4079cfb85fb8326b8c75a7538fdbfa3d8afaa63"
dependencies:
heimdalljs "^0.2.0"
heimdalljs-logger "^0.1.7"
@@ -4083,7 +4382,7 @@ heimdalljs-graph@^0.3.1:
version "0.3.4"
resolved "https://registry.yarnpkg.com/heimdalljs-graph/-/heimdalljs-graph-0.3.4.tgz#0bd75797beeaa20b0ed59017aed3b2d95312acee"
-heimdalljs-logger@^0.1.7:
+heimdalljs-logger@^0.1.7, heimdalljs-logger@^0.1.9:
version "0.1.9"
resolved "https://registry.yarnpkg.com/heimdalljs-logger/-/heimdalljs-logger-0.1.9.tgz#d76ada4e45b7bb6f786fc9c010a68eb2e2faf176"
dependencies:
@@ -4194,6 +4493,10 @@ ignore@^3.1.2:
version "3.3.7"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
+ignore@^3.3.6:
+ version "3.3.10"
+ resolved "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
+
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
@@ -4212,7 +4515,7 @@ inflected@^1.1.6:
version "1.1.7"
resolved "https://registry.yarnpkg.com/inflected/-/inflected-1.1.7.tgz#c393df6e28472d0d77b3082ec3aa2091f4bc96f9"
-inflection@^1.12.0, inflection@^1.7.0, inflection@^1.7.1, inflection@^1.8.0:
+inflection@^1.12.0, inflection@^1.7.0, inflection@^1.8.0:
version "1.12.0"
resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416"
@@ -4285,6 +4588,12 @@ into-stream@^3.1.0:
from2 "^2.1.1"
p-is-promise "^1.1.0"
+invariant@^2.2.0:
+ version "2.2.4"
+ resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
+ dependencies:
+ loose-envify "^1.0.0"
+
invariant@^2.2.2:
version "2.2.3"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.3.tgz#1a827dfde7dcbd7c323f0ca826be8fa7c5e9d688"
@@ -4601,6 +4910,10 @@ jade@0.26.3:
commander "0.6.1"
mkdirp "0.3.0"
+jest-docblock@^21.0.0:
+ version "21.2.0"
+ resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414"
+
jmespath@0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
@@ -4640,6 +4953,10 @@ jsesc@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
+jsesc@^2.5.1:
+ version "2.5.1"
+ resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe"
+
jsesc@~0.3.x:
version "0.3.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.3.0.tgz#1bf5ee63b4539fe2e26d0c1e99c240b97a457972"
@@ -4986,6 +5303,10 @@ lodash.defaults@~2.3.0:
lodash._objecttypes "~2.3.0"
lodash.keys "~2.3.0"
+lodash.defaultsdeep@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.0.tgz#bec1024f85b1bd96cbea405b23c14ad6443a6f81"
+
lodash.escape@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-2.3.0.tgz#844c38c58f844e1362ebe96726159b62cf5f2a58"
@@ -5058,7 +5379,7 @@ lodash.keys@~2.3.0:
lodash._shimkeys "~2.3.0"
lodash.isobject "~2.3.0"
-lodash.merge@^4.3.0, lodash.merge@^4.4.0, lodash.merge@^4.5.1, lodash.merge@^4.6.0:
+lodash.merge@^4.3.0, lodash.merge@^4.5.1, lodash.merge@^4.6.0:
version "4.6.1"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54"
@@ -5134,6 +5455,10 @@ lodash@^4.0.0, lodash@^4.14.0, lodash@^4.16.1, lodash@^4.17.2, lodash@^4.17.4, l
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+lodash@^4.2.0:
+ version "4.17.10"
+ resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
+
log-symbols@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
@@ -5232,7 +5557,7 @@ markdown-it@^8.3.0, markdown-it@^8.3.1:
mdurl "^1.0.1"
uc.micro "^1.0.5"
-matcher-collection@^1.0.0, matcher-collection@^1.0.4:
+matcher-collection@^1.0.0, matcher-collection@^1.0.4, matcher-collection@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/matcher-collection/-/matcher-collection-1.0.5.tgz#2ee095438372cb8884f058234138c05c644ec339"
dependencies:
@@ -5340,6 +5665,24 @@ micromatch@^3.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
+micromatch@^3.1.4:
+ version "3.1.10"
+ resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
+ dependencies:
+ arr-diff "^4.0.0"
+ array-unique "^0.3.2"
+ braces "^2.3.1"
+ define-property "^2.0.2"
+ extend-shallow "^3.0.2"
+ extglob "^2.0.4"
+ fragment-cache "^0.2.1"
+ kind-of "^6.0.2"
+ nanomatch "^1.2.9"
+ object.pick "^1.3.0"
+ regex-not "^1.0.0"
+ snapdragon "^0.8.1"
+ to-regex "^3.0.2"
+
"mime-db@>= 1.33.0 < 2", mime-db@~1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
@@ -5965,6 +6308,10 @@ pretender@^1.4.2:
fake-xml-http-request "^1.6.0"
route-recognizer "^0.3.3"
+prettier@^1.12.1:
+ version "1.13.5"
+ resolved "https://registry.npmjs.org/prettier/-/prettier-1.13.5.tgz#7ae2076998c8edce79d63834e9b7b09fead6bfd0"
+
printf@^0.2.3:
version "0.2.5"
resolved "https://registry.yarnpkg.com/printf/-/printf-0.2.5.tgz#c438ca2ca33e3927671db4ab69c0e52f936a4f0f"
@@ -6225,6 +6572,10 @@ regenerator-runtime@^0.11.0:
version "0.11.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+regenerator-runtime@^0.9.5:
+ version "0.9.6"
+ resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz#d33eb95d0d2001a4be39659707c51b0cb71ce029"
+
regenerator-transform@^0.10.0:
version "0.10.1"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
@@ -6458,9 +6809,9 @@ rsvp@^3.0.14, rsvp@^3.0.16, rsvp@^3.0.17, rsvp@^3.0.18, rsvp@^3.0.21, rsvp@^3.0.
version "3.6.2"
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
-rsvp@^4.7.0:
+rsvp@^4.7.0, rsvp@^4.8.2:
version "4.8.2"
- resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.2.tgz#9d5647108735784eb13418cdddb56f75b919d722"
+ resolved "https://registry.npmjs.org/rsvp/-/rsvp-4.8.2.tgz#9d5647108735784eb13418cdddb56f75b919d722"
rsvp@~3.0.6:
version "3.0.21"
@@ -6538,7 +6889,7 @@ sax@>=0.6.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
-"semver@2 || 3 || 4 || 5", semver@^5.4.1:
+"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
@@ -6828,6 +7179,10 @@ source-map@~0.1.x:
dependencies:
amdefine ">=0.0.4"
+source-map@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+
sourcemap-validator@^1.0.5:
version "1.0.7"
resolved "https://registry.yarnpkg.com/sourcemap-validator/-/sourcemap-validator-1.0.7.tgz#d76aaadbe2c6ec269293b5f212100fad91eef260"
@@ -7107,6 +7462,13 @@ temp@0.8.3:
os-tmpdir "^1.0.0"
rimraf "~2.2.6"
+terser@^3.7.5:
+ version "3.7.6"
+ resolved "https://registry.npmjs.org/terser/-/terser-3.7.6.tgz#0b3c609f22278c089780ac1cdc63627071e3b96a"
+ dependencies:
+ commander "~2.14.1"
+ source-map "~0.6.1"
+
testdouble@^3.2.6:
version "3.5.2"
resolved "https://registry.yarnpkg.com/testdouble/-/testdouble-3.5.2.tgz#7ac91d08be05bac3b2acba57c430f6c62d0ad8af"
@@ -7243,6 +7605,10 @@ to-fast-properties@^1.0.0, to-fast-properties@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+
to-iso-string@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1"
@@ -7260,7 +7626,7 @@ to-regex-range@^2.1.0:
is-number "^3.0.0"
repeat-string "^1.6.1"
-to-regex@^3.0.1:
+to-regex@^3.0.1, to-regex@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
dependencies:
@@ -7518,7 +7884,7 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
-walk-sync@0.3.2, walk-sync@^0.3.0, walk-sync@^0.3.1:
+walk-sync@0.3.2, walk-sync@^0.3.0, walk-sync@^0.3.1, walk-sync@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.3.2.tgz#4827280afc42d0e035367c4a4e31eeac0d136f75"
dependencies:
@@ -7542,6 +7908,16 @@ walker@~1.0.5:
dependencies:
makeerror "1.0.x"
+watch-detector@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.npmjs.org/watch-detector/-/watch-detector-0.1.0.tgz#e37b410d149e2a8bf263a4f8b71e2f667633dbf8"
+ dependencies:
+ heimdalljs-logger "^0.1.9"
+ quick-temp "^0.1.8"
+ rsvp "^4.7.0"
+ semver "^5.4.1"
+ silent-error "^1.1.0"
+
watch@~0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/watch/-/watch-0.10.0.tgz#77798b2da0f9910d595f1ace5b0c2258521f21dc"
@@ -7688,12 +8064,12 @@ yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
-yam@0.0.22:
- version "0.0.22"
- resolved "https://registry.yarnpkg.com/yam/-/yam-0.0.22.tgz#38a76cb79a19284d9206ed49031e359a1340bd06"
+yam@^0.0.24:
+ version "0.0.24"
+ resolved "https://registry.npmjs.org/yam/-/yam-0.0.24.tgz#11e9630444735f66a561d29221407de6d037cd95"
dependencies:
- fs-extra "^0.30.0"
- lodash.merge "^4.4.0"
+ fs-extra "^4.0.2"
+ lodash.merge "^4.6.0"
yargs@~3.10.0:
version "3.10.0"