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.
This commit is contained in:
Scott Kyle 2015-10-07 21:20:14 -07:00
parent 0ed5ba2d8e
commit a9cac20f79
4 changed files with 40 additions and 36 deletions

View File

@ -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]
};
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
if (length > size) {
let props = {};
for (let i = maxSize; i <= size; i++) {
for (let i = size; i < length; i++) {
props[i] = {
get: getterForIndex(i),
set: setterForIndex && setterForIndex(i),
enumerable: true,
configurable: true,
};
}
// TODO: Use ES6 Proxy once it's supported on Chrome!
Object.defineProperties(prototype, props);
maxSize = size + 1;
Object.defineProperties(this, props);
}
else if (length < size) {
for (let i = size - 1; i >= length; i--) {
delete this[i];
}
}
return prototype;
size = length;
};
return list;
}