emberjs / data

WarpDrive is a lightweight data library for web apps — universal, typed, reactive, and ready to scale.
https://api.emberjs.com/ember-data/release
MIT License
3.04k stars 1.33k forks source link

store `willDestroy` triggers BelongsToRelationship getData #5669

Closed makepanic closed 6 years ago

makepanic commented 6 years ago

Hi,

When upgrading:

We're seeing failing acceptance tests as store teardown somehow triggers relationship fetches.

20181005-171039

simplified call stack:

Store.willDestroy()
Store.unloadAll()
...
unloadRecord()
destroyRelationships()
..
Relationship.internalModelDidDematerialize()
...
BelongsToRelationship.inverseDidDematerialize()
BelongsToRelationship.notifyBelongsToChange()
...
Metal.notifyPropertyChange()
...
lazyGet()
...
BelongsToRelationship.getData()
...
findBelongsTo()
adapterFor()

actual error stack:

vendor.js:56040 Uncaught TypeError: Cannot read property 'state' of null
    at Class.adapterFor (vendor.js:175022)
    at Class.findBelongsTo (vendor.js:173755)
    at BelongsToRelationship._fetchLink (vendor.js:167365)
    at BelongsToRelationship.getData (vendor.js:167393)
    at State.get (vendor.js:175639)
    at ComputedProperty.get (vendor.js:48892)
    at _get (vendor.js:47733)
    at Proxy.unknownProperty (vendor.js:56216)
    at _get (vendor.js:47766)
    at lazyGet (vendor.js:48299)

Where adapterFor throws an error as the _adapterCache is already null and it tries to lookup the normalizedModelName of null.

20181005-151021

I'm trying to get create a dummy project that reproduces the error but it's kinda hard to do. I'll update this issue once I got it to throw in a minimal project.

Here's the full stacktrace:

_fetchLink (-private.js:5595)
getData (-private.js:5623)
get (-private.js:13869)
get (ember-metal.js:2515)
_get (ember-metal.js:1356)
unknownProperty (-proxy.js:73)
_get (ember-metal.js:1389)
lazyGet (ember-metal.js:1922)
value (ember-metal.js:1789)
notify (ember-metal.js:1867)
notify (ember-metal.js:1886)
notify (ember-metal.js:1694)
chainsDidChange (ember-metal.js:652)
notifyPropertyChange (ember-metal.js:597)
contentPropertyDidChange (-proxy.js:12)
sendEvent (ember-metal.js:188)
notifyObservers (ember-metal.js:710)
notifyPropertyChange (ember-metal.js:598)
notify (ember-metal.js:1703)
chainsDidChange (ember-metal.js:652)
notifyPropertyChange (ember-metal.js:597)
notifyPropertyChange (observable.js:193)
notifyBelongsToChange (-private.js:2594)
notifyBelongsToChange (-private.js:7978)
notifyBelongsToChange (-private.js:5543)
inverseDidDematerialize (-private.js:5455)
(anonymous) (-private.js:4016)
forAllMembers (-private.js:4250)
internalModelDidDematerialize (-private.js:4014)
destroyRelationship (-private.js:7309)
(anonymous) (-private.js:8166)
destroyRelationships (-private.js:8164)
dematerializeRecord (-private.js:7521)
unloadRecord (-private.js:7638)
clear (-private.js:8719)
clear (-private.js:8814)
unloadAll (-private.js:12449)
willDestroy (-private.js:13381)
superWrapper (ember-utils.js:308)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
end (backburner.js:558)
_run (backburner.js:853)
run (backburner.js:601)
run (index.js:113)
(anonymous) (teardown-context.js:30)
tryCatcher (rsvp.js:200)
invokeCallback (rsvp.js:372)
publish (rsvp.js:358)
(anonymous) (rsvp.js:10)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_ensureInstance (backburner.js:965)
schedule (backburner.js:638)
(anonymous) (rsvp.js:8)
fulfill (rsvp.js:309)
resolve$1 (rsvp.js:284)
(anonymous) (rsvp.js:402)
setTimeout (async)
(anonymous) (-utils.js:19)
initializePromise (rsvp.js:397)
Promise (rsvp.js:877)
nextTickPromise (-utils.js:18)
teardownContext (teardown-context.js:24)
(anonymous) (index.js:159)
callHook (qunit.js:1793)
runHook (qunit.js:1814)
advanceTaskQueue (qunit.js:1373)
advance (qunit.js:1354)
begin (qunit.js:3126)
(anonymous) (qunit.js:2368)
setTimeout (async)
internalStart (qunit.js:2359)
resume (qunit.js:2320)
(anonymous) (qunit.js:2090)
tryCatcher (rsvp.js:200)
invokeCallback (rsvp.js:372)
publish (rsvp.js:358)
(anonymous) (rsvp.js:10)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_ensureInstance (backburner.js:965)
schedule (backburner.js:638)
(anonymous) (rsvp.js:8)
fulfill (rsvp.js:309)
resolve$1 (rsvp.js:284)
(anonymous) (rsvp.js:402)
(anonymous) (wait-until.js:56)
setTimeout (async)
scheduleCheck (wait-until.js:45)
(anonymous) (wait-until.js:65)
initializePromise (rsvp.js:397)
Promise (rsvp.js:877)
waitUntil (wait-until.js:35)
settled (settled.js:251)
exports.default (teardown-application-context.js:9)
(anonymous) (index.js:183)
callHook (qunit.js:1793)
runHook (qunit.js:1814)
advanceTaskQueue (qunit.js:1373)
advance (qunit.js:1354)
begin (qunit.js:3126)
(anonymous) (qunit.js:2368)
setTimeout (async)
internalStart (qunit.js:2359)
resume (qunit.js:2320)
(anonymous) (qunit.js:2090)
tryCatcher (rsvp.js:200)
invokeCallback (rsvp.js:372)
publish (rsvp.js:358)
(anonymous) (rsvp.js:14)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_ensureInstance (backburner.js:965)
schedule (backburner.js:638)
(anonymous) (rsvp.js:8)
fulfill (rsvp.js:309)
resolve$1 (rsvp.js:284)
(anonymous) (rsvp.js:402)
(anonymous) (wait-until.js:56)
setTimeout (async)
scheduleCheck (wait-until.js:45)
(anonymous) (wait-until.js:58)
setTimeout (async)
scheduleCheck (wait-until.js:45)
(anonymous) (wait-until.js:65)
initializePromise (rsvp.js:397)
Promise (rsvp.js:877)
waitUntil (wait-until.js:35)
settled (settled.js:251)
tryCatcher (rsvp.js:200)
invokeCallback (rsvp.js:372)
publish (rsvp.js:358)
(anonymous) (rsvp.js:14)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
end (backburner.js:558)
_run (backburner.js:853)
_join (backburner.js:829)
join (backburner.js:612)
resolveRenderPromise (ember-glimmer.js:4171)
loopEnd (ember-glimmer.js:4189)
_trigger (backburner.js:901)
_end (backburner.js:820)
end (backburner.js:558)
_run (backburner.js:853)
_join (backburner.js:829)
join (backburner.js:612)
join (index.js:164)
(anonymous) (ajax-request.js:232)
(anonymous) (fake_xml_http_request.js:137)
dispatchEvent (fake_xml_http_request.js:181)
_readyStateChange (fake_xml_http_request.js:389)
_setResponseBody (fake_xml_http_request.js:453)
respond (fake_xml_http_request.js:474)
(anonymous) (pretender.js:378)
resolve (pretender.js:429)
(anonymous) (pretender.js:420)
setTimeout (async)
handleResponse (pretender.js:419)
_handleRequest (pretender.js:377)
(anonymous) (pretender.js:388)
tryCatcher (rsvp.js:200)
invokeCallback (rsvp.js:372)
publish (rsvp.js:358)
(anonymous) (rsvp.js:14)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
end (backburner.js:558)
_run (backburner.js:853)
_join (backburner.js:829)
join (backburner.js:612)
join (index.js:164)
(anonymous) (ajax-request.js:232)
(anonymous) (fake_xml_http_request.js:137)
dispatchEvent (fake_xml_http_request.js:181)
_readyStateChange (fake_xml_http_request.js:389)
_setResponseBody (fake_xml_http_request.js:453)
respond (fake_xml_http_request.js:474)
(anonymous) (pretender.js:378)
resolve (pretender.js:429)
(anonymous) (pretender.js:420)
setTimeout (async)
handleResponse (pretender.js:419)
_handleRequest (pretender.js:377)
(anonymous) (pretender.js:388)
tryCatcher (rsvp.js:200)
invokeCallback (rsvp.js:372)
publish (rsvp.js:358)
(anonymous) (rsvp.js:14)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
end (backburner.js:558)
_run (backburner.js:853)
_join (backburner.js:829)
join (backburner.js:612)
join (index.js:164)
(anonymous) (ajax-request.js:232)
(anonymous) (fake_xml_http_request.js:137)
dispatchEvent (fake_xml_http_request.js:181)
_readyStateChange (fake_xml_http_request.js:389)
_setResponseBody (fake_xml_http_request.js:453)
respond (fake_xml_http_request.js:474)
(anonymous) (pretender.js:378)
resolve (pretender.js:429)
(anonymous) (pretender.js:420)
setTimeout (async)
handleResponse (pretender.js:419)
_handleRequest (pretender.js:377)
(anonymous) (pretender.js:388)
tryCatcher (rsvp.js:200)
invokeCallback (rsvp.js:372)
publish (rsvp.js:358)
(anonymous) (rsvp.js:14)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
end (backburner.js:558)
_run (backburner.js:853)
_join (backburner.js:829)
join (backburner.js:612)
join (index.js:164)
(anonymous) (ajax-request.js:232)
(anonymous) (fake_xml_http_request.js:137)
dispatchEvent (fake_xml_http_request.js:181)
_readyStateChange (fake_xml_http_request.js:389)
_setResponseBody (fake_xml_http_request.js:453)
respond (fake_xml_http_request.js:474)
(anonymous) (pretender.js:378)
resolve (pretender.js:429)
(anonymous) (pretender.js:420)
setTimeout (async)
handleResponse (pretender.js:419)
_handleRequest (pretender.js:377)
(anonymous) (pretender.js:388)
tryCatcher (rsvp.js:200)
invokeCallback (rsvp.js:372)
publish (rsvp.js:358)
(anonymous) (rsvp.js:14)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
end (backburner.js:558)
_run (backburner.js:853)
_join (backburner.js:829)
join (backburner.js:612)
join (index.js:164)
(anonymous) (ajax-request.js:232)
(anonymous) (fake_xml_http_request.js:137)
dispatchEvent (fake_xml_http_request.js:181)
_readyStateChange (fake_xml_http_request.js:389)
_setResponseBody (fake_xml_http_request.js:453)
respond (fake_xml_http_request.js:474)
(anonymous) (pretender.js:378)
resolve (pretender.js:429)
(anonymous) (pretender.js:420)
setTimeout (async)
handleResponse (pretender.js:419)
_handleRequest (pretender.js:377)
(anonymous) (pretender.js:388)
tryCatcher (rsvp.js:200)
invokeCallback (rsvp.js:372)
publish (rsvp.js:358)
(anonymous) (rsvp.js:14)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
end (backburner.js:558)
_run (backburner.js:853)
_join (backburner.js:829)
join (backburner.js:612)
join (index.js:164)
(anonymous) (ajax-request.js:232)
(anonymous) (fake_xml_http_request.js:137)
dispatchEvent (fake_xml_http_request.js:181)
_readyStateChange (fake_xml_http_request.js:389)
_setResponseBody (fake_xml_http_request.js:453)
respond (fake_xml_http_request.js:474)
(anonymous) (pretender.js:378)
resolve (pretender.js:429)
(anonymous) (pretender.js:420)
setTimeout (async)
handleResponse (pretender.js:419)
_handleRequest (pretender.js:377)
(anonymous) (pretender.js:388)
tryCatcher (rsvp.js:200)
invokeCallback (rsvp.js:372)
publish (rsvp.js:358)
(anonymous) (rsvp.js:14)
invoke (backburner.js:274)
flush (backburner.js:186)
flush (backburner.js:353)
_end (backburner.js:808)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
characterData (async)
next (backburner.js:17)
_scheduleAutorun (backburner.js:973)
_end (backburner.js:813)
Backburner._boundAutorunEnd (backburner.js:528)
makepanic commented 6 years ago

As it turns out, this is most likely caused by me using dependent keys that look like this:

relationshipName.id

Once i've changed the computed keys to relationshipName, it worked without throwing an error during test teardown.

Leooo commented 5 years ago

For those who see the same, on our side (Ember 3.4.4, ember-data 3.5) we had to remove a link for a parent relationship from a mirage response to make it work (couldn't find any computed property with .id cache key that we could try to remove).