diff --git a/lib/lists.js b/lib/lists.js index 92cdafa6..c74593cc 100644 --- a/lib/lists.js +++ b/lib/lists.js @@ -1,10 +1,11 @@ 'use strict'; let rpc = require('./rpc'); +let util = require('./util'); let idKey = Symbol(); let realmKey = Symbol(); -let prototype = {}; +let prototype = util.createListPrototype(getterForLength, getterForIndex, setterForIndex); exports.create = create; @@ -30,7 +31,7 @@ exports.create = create; // Since this method might have grown the list, ensure index properties are defined. if (growthMethod) { - defineIndexProperties(this.length); + prototype[util.growListPrototypeKey](this.length); } return result; @@ -38,12 +39,6 @@ exports.create = create; }); }); -Object.defineProperty(prototype, 'length', { - get() { - return rpc.getListSize(this[realmKey], this[idKey]); - } -}); - function create(realmId, info) { let list = Object.create(prototype); let size = info.size; @@ -51,27 +46,13 @@ function create(realmId, info) { list[realmKey] = realmId; list[idKey] = info.id; - defineIndexProperties(size); + list[util.growListPrototypeKey](size); + + return list; } -let maxSize = 0; -function defineIndexProperties(size) { - if (size < maxSize) { - return; - } - - let props = {}; - for (let i = maxSize; i <= size; i++) { - props[i] = { - get: getterForIndex(i), - set: setterForIndex(i), - }; - } - - // TODO: Use ES6 Proxy once it's supported on Chrome! - Object.defineProperties(prototype, props); - - maxSize = size + 1; +function getterForLength() { + return rpc.getListSize(this[realmKey], this[idKey]); } function getterForIndex(index) { diff --git a/lib/realm.js b/lib/realm.js index 832b8623..3e067cec 100644 --- a/lib/realm.js +++ b/lib/realm.js @@ -2,6 +2,7 @@ let lists = require('./lists'); let objects = require('./objects'); +let results = require('./results'); let rpc = require('./rpc'); let types = require('./types'); @@ -51,8 +52,11 @@ class Realm { // TODO } - objects(type) { - // TODO + objects(type, predicate) { + let realmId = this[realmKey]; + let info = rpc.getObjects(realmId, type, predicate); + + return results.create(realmId, info); } write(callback) { diff --git a/lib/results.js b/lib/results.js new file mode 100644 index 00000000..a7abb187 --- /dev/null +++ b/lib/results.js @@ -0,0 +1,33 @@ +'use strict'; + +let rpc = require('./rpc'); +let util = require('./util'); + +let idKey = Symbol(); +let realmKey = Symbol(); +let prototype = util.createListPrototype(getterForLength, getterForIndex); + +exports.create = create; + +function create(realmId, info) { + let results = Object.create(prototype); + let size = info.size; + + results[realmKey] = realmId; + results[idKey] = info.resultsId; + + results[util.growListPrototypeKey](size); + + return results; +} + +function getterForLength() { + return rpc.getResultsSize(this[realmKey], this[idKey]); +} + +function getterForIndex(index) { + return function() { + let realmId = this[realmKey]; + return rpc.getResultsItem(realmId, this[idKey], index); + }; +} diff --git a/lib/rpc.js b/lib/rpc.js index e68b37c9..1fd0aba7 100644 --- a/lib/rpc.js +++ b/lib/rpc.js @@ -17,6 +17,7 @@ exports.registerTypeConverter = registerTypeConverter; exports.createRealm = createRealm; exports.createObject = createObject; +exports.getObjects = getObjects; exports.getObjectProperty = getObjectProperty; exports.setObjectProperty = setObjectProperty; @@ -26,6 +27,9 @@ exports.setListItem = setListItem; exports.getListSize = getListSize; exports.callListMethod = callListMethod; +exports.getResultsItem = getResultsItem; +exports.getResultsSize = getResultsSize; + exports.beginTransaction = beginTransaction; exports.cancelTransaction = cancelTransaction; exports.commitTransaction = commitTransaction; @@ -42,6 +46,10 @@ function createObject(realmId, type, values) { return sendRequest('create_object', {realmId, type, values}); } +function getObjects(realmId, type, predicate) { + return sendRequest('get_objects', {realmId, type, predicate}); +} + function getObjectProperty(realmId, objectId, name) { let result = sendRequest('get_property', {realmId, objectId, name}); return convert(result); @@ -69,6 +77,15 @@ function callListMethod(realmId, listId, name, args) { return convert(result); } +function getResultsItem(realmId, resultsId, index) { + let result = sendRequest('get_results_item', {realmId, resultsId, index}); + return convert(result); +} + +function getResultsSize(realmId, resultsId) { + return sendRequest('get_results_size', {realmId, resultsId}); +} + function beginTransaction(realmId) { sendRequest('begin_transaction', {realmId}); } diff --git a/lib/util.js b/lib/util.js new file mode 100644 index 00000000..a01c641b --- /dev/null +++ b/lib/util.js @@ -0,0 +1,35 @@ +'use strict'; + +let growListPrototypeKey = exports.growListPrototypeKey = Symbol(); + +exports.createListPrototype = createListPrototype; + +function createListPrototype(getterForLength, getterForIndex, setterForIndex) { + let prototype = {}; + let maxSize = 0; + + Object.defineProperty(prototype, 'length', { + get: getterForLength + }); + + prototype[growListPrototypeKey] = function(size) { + if (size < maxSize) { + return; + } + + let props = {}; + for (let i = maxSize; i <= size; i++) { + props[i] = { + get: getterForIndex(i), + set: setterForIndex && setterForIndex(i), + }; + } + + // TODO: Use ES6 Proxy once it's supported on Chrome! + Object.defineProperties(prototype, props); + + maxSize = size + 1; + } + + return prototype; +}