From be0c2a91ea77eaae086fe0d98fcdb6e5c503d71d Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Tue, 1 Dec 2015 14:05:33 -0800 Subject: [PATCH] Fix RPC client error after deleting objects Specifically for objects with lists, since the mutation listener would fire on a list that no longer is attached. If during the mutation listener that error is thrown, then the listener will be removed and the error will not be propagated. --- lib/rpc.js | 9 ++++++++- lib/util.js | 22 ++++++++++++++++++++-- tests/lib/ArrayTests.js | 13 +++++++++++-- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/lib/rpc.js b/lib/rpc.js index 5d8380c3..e69275dc 100644 --- a/lib/rpc.js +++ b/lib/rpc.js @@ -167,7 +167,14 @@ function sendRequest(command, data) { let response = JSON.parse(request.responseText); if (!response || response.error) { - throw new Error((response && response.error) || 'Invalid response for "' + command + '"'); + let error = response && response.error; + + // Remove the type prefix from the error message (e.g. "Error: "). + if (error) { + error = error.replace(/^[a-z]+: /i, ''); + } + + throw new Error(error || `Invalid response for "${command}"`); } return response.result; diff --git a/lib/util.js b/lib/util.js index ded21bcd..6ea4f95c 100644 --- a/lib/util.js +++ b/lib/util.js @@ -11,7 +11,6 @@ const {keys} = constants; const mutationListeners = {}; module.exports = { - addMutationListener, fireMutationListeners, createList, createMethods, @@ -25,6 +24,13 @@ function addMutationListener(realmId, callback) { listeners.add(callback); } +function removeMutationListener(realmId, callback) { + let listeners = mutationListeners[realmId]; + if (listeners) { + listeners.delete(callback); + } +} + function fireMutationListeners(realmId) { let listeners = mutationListeners[realmId]; if (listeners) { @@ -87,7 +93,19 @@ function createList(prototype, realmId, info, mutable) { list[keys.type] = info.type; resize(info.size); - addMutationListener(realmId, resize); + + addMutationListener(realmId, function listener() { + try { + resize(); + } catch (e) { + // If the error indicates the list was deleted, then remove this listener. + if (e.message == 'Tableview is not attached') { + removeMutationListener(realmId, listener); + } else { + throw e; + } + } + }); return list; } diff --git a/tests/lib/ArrayTests.js b/tests/lib/ArrayTests.js index 25950511..f5110179 100644 --- a/tests/lib/ArrayTests.js +++ b/tests/lib/ArrayTests.js @@ -276,11 +276,12 @@ module.exports = BaseTest.extend({ testDeletions: function() { var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); + var object; var array; realm.write(function() { - var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); - array = obj.arrayCol; + object = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); + array = object.arrayCol; }); try { @@ -296,6 +297,14 @@ module.exports = BaseTest.extend({ TestCase.assertEqual(array.length, 2); TestCase.assertEqual(array[0].doubleCol, 3); + + realm.write(function() { + realm.delete(object); + }); + + TestCase.assertThrows(function() { + array[0]; + }); }, testLiveUpdatingResults: function() {