From a9cac20f7975eac442e0c586dfb5079bd30c0d2d Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Wed, 7 Oct 2015 21:20:14 -0700 Subject: [PATCH] Rework lists to each have their own getters This was necessary for them to each have their own enumerable properties. The React Native ListViewDataSource uses Object.keys() to the indexes. --- ReactNative/RealmRPC.mm | 1 + lib/lists.js | 16 ++++-------- lib/results.js | 5 ++-- lib/util.js | 54 ++++++++++++++++++++++++----------------- 4 files changed, 40 insertions(+), 36 deletions(-) diff --git a/ReactNative/RealmRPC.mm b/ReactNative/RealmRPC.mm index c2290a09..ea60f0c7 100644 --- a/ReactNative/RealmRPC.mm +++ b/ReactNative/RealmRPC.mm @@ -272,6 +272,7 @@ static JSGlobalContextRef s_context; return @{ @"type": @(RJSTypeGet(realm::PropertyTypeArray).c_str()), @"id": @(oid), + @"size": @(array->link_view->size()), @"schema": [self objectSchemaToJSONObject:array->object_schema] }; } diff --git a/lib/lists.js b/lib/lists.js index c74593cc..d127e815 100644 --- a/lib/lists.js +++ b/lib/lists.js @@ -5,7 +5,7 @@ let util = require('./util'); let idKey = Symbol(); let realmKey = Symbol(); -let prototype = util.createListPrototype(getterForLength, getterForIndex, setterForIndex); +let prototype = {}; exports.create = create; @@ -15,9 +15,7 @@ exports.create = create; 'push', 'unshift', 'splice', -].forEach(function(name, i) { - let growthMethod = (i >= 2); - +].forEach(function(name) { Object.defineProperty(prototype, name, { value: function() { let listId = this[idKey]; @@ -28,11 +26,7 @@ exports.create = create; } let result = rpc.callListMethod(realmId, listId, name, Array.from(arguments)); - - // Since this method might have grown the list, ensure index properties are defined. - if (growthMethod) { - prototype[util.growListPrototypeKey](this.length); - } + this[util.resizeListKey](); return result; } @@ -40,13 +34,13 @@ exports.create = create; }); function create(realmId, info) { - let list = Object.create(prototype); + let list = util.createList(prototype, getterForLength, getterForIndex, setterForIndex); let size = info.size; list[realmKey] = realmId; list[idKey] = info.id; - list[util.growListPrototypeKey](size); + list[util.resizeListKey](size); return list; } diff --git a/lib/results.js b/lib/results.js index a7abb187..d71ec514 100644 --- a/lib/results.js +++ b/lib/results.js @@ -5,18 +5,17 @@ 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 results = util.createList(null, getterForLength, getterForIndex); let size = info.size; results[realmKey] = realmId; results[idKey] = info.resultsId; - results[util.growListPrototypeKey](size); + results[util.resizeListKey](size); return results; } diff --git a/lib/util.js b/lib/util.js index a01c641b..116ffdb0 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,35 +1,45 @@ 'use strict'; -let growListPrototypeKey = exports.growListPrototypeKey = Symbol(); +let resizeListKey = exports.resizeListKey = Symbol(); -exports.createListPrototype = createListPrototype; +exports.createList = createList; -function createListPrototype(getterForLength, getterForIndex, setterForIndex) { - let prototype = {}; - let maxSize = 0; +function createList(prototype, getterForLength, getterForIndex, setterForIndex) { + var list = prototype ? Object.create(prototype) : {}; + var size = 0; - Object.defineProperty(prototype, 'length', { - get: getterForLength - }); + Object.defineProperty(list, 'length', {get: getterForLength}); - prototype[growListPrototypeKey] = function(size) { - if (size < maxSize) { + list[resizeListKey] = function(length) { + if (length == null) { + length = this.length; + } + if (length == size) { return; } - let props = {}; - for (let i = maxSize; i <= size; i++) { - props[i] = { - get: getterForIndex(i), - set: setterForIndex && setterForIndex(i), - }; + if (length > size) { + let props = {}; + + for (let i = size; i < length; i++) { + props[i] = { + get: getterForIndex(i), + set: setterForIndex && setterForIndex(i), + enumerable: true, + configurable: true, + }; + } + + Object.defineProperties(this, props); + } + else if (length < size) { + for (let i = size - 1; i >= length; i--) { + delete this[i]; + } } - // TODO: Use ES6 Proxy once it's supported on Chrome! - Object.defineProperties(prototype, props); + size = length; + }; - maxSize = size + 1; - } - - return prototype; + return list; }