Merge pull request #288 from realm/sk-array-methods

Steal Array.prototype methods for List and Results
This commit is contained in:
Scott Kyle 2016-03-01 00:38:27 -08:00
commit 578e6b9742
30 changed files with 297 additions and 166 deletions

View File

@ -40,7 +40,7 @@
02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; };
02EF76861BFFDE37000D5BAD /* test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02EF76851BFFDE37000D5BAD /* test.cpp */; };
02EF76881BFFDE9E000D5BAD /* GrammarTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 02EF76871BFFDE9E000D5BAD /* GrammarTests.mm */; };
F61378791C18EAC5008BFC51 /* lib in Resources */ = {isa = PBXBuildFile; fileRef = F61378781C18EAAC008BFC51 /* lib */; };
F61378791C18EAC5008BFC51 /* js in Resources */ = {isa = PBXBuildFile; fileRef = F61378781C18EAAC008BFC51 /* js */; };
F636F6C81BCDB3570023F35C /* RealmReact.h in Headers */ = {isa = PBXBuildFile; fileRef = 0270BCCF1B7D067300010E03 /* RealmReact.h */; settings = {ATTRIBUTES = (Public, ); }; };
F63FF2C61C12469E00B3B8E0 /* js_init.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 029048011C0428DF00ABDED4 /* js_init.cpp */; };
F63FF2C71C12469E00B3B8E0 /* js_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 029048031C0428DF00ABDED4 /* js_list.cpp */; };
@ -86,6 +86,7 @@
F63FF3311C16434400B3B8E0 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F63FF3301C16434400B3B8E0 /* libz.tbd */; };
F68A278C1BC2722A0063D40A /* RJSModuleLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = F68A278B1BC2722A0063D40A /* RJSModuleLoader.m */; };
F6BB7DF21BF681BC00D0A69E /* base64.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F6BB7DF01BF681BC00D0A69E /* base64.hpp */; };
F6BCCFE21C8380A400FE31AE /* lib in Resources */ = {isa = PBXBuildFile; fileRef = F6BCCFDF1C83809A00FE31AE /* lib */; };
F6C74DF01C732CC500C9DDCD /* RealmAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = F6C74DEE1C732CC500C9DDCD /* RealmAnalytics.h */; };
F6C74DF11C732CC500C9DDCD /* RealmAnalytics.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6C74DEF1C732CC500C9DDCD /* RealmAnalytics.mm */; };
/* End PBXBuildFile section */
@ -207,7 +208,7 @@
02D0F23A1BF6C95200B4FC45 /* binding_context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = binding_context.hpp; sourceTree = "<group>"; };
02EF76851BFFDE37000D5BAD /* test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test.cpp; path = "src/object-store/parser/test.cpp"; sourceTree = SOURCE_ROOT; };
02EF76871BFFDE9E000D5BAD /* GrammarTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = GrammarTests.mm; path = ios/GrammarTests.mm; sourceTree = "<group>"; };
F61378781C18EAAC008BFC51 /* lib */ = {isa = PBXFileReference; lastKnownFileType = folder; path = lib; sourceTree = "<group>"; };
F61378781C18EAAC008BFC51 /* js */ = {isa = PBXFileReference; lastKnownFileType = folder; path = js; sourceTree = "<group>"; };
F63FF2B11C1241E500B3B8E0 /* libRealmJS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRealmJS.a; sourceTree = BUILT_PRODUCTS_DIR; };
F63FF2DC1C15659A00B3B8E0 /* RealmJS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RealmJS.mm; sourceTree = "<group>"; };
F63FF2F01C16405C00B3B8E0 /* libGCDWebServers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libGCDWebServers.a; sourceTree = BUILT_PRODUCTS_DIR; };
@ -248,6 +249,7 @@
F68A278B1BC2722A0063D40A /* RJSModuleLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RJSModuleLoader.m; path = ios/RJSModuleLoader.m; sourceTree = "<group>"; };
F6BB7DEF1BF681BC00D0A69E /* base64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = base64.cpp; sourceTree = "<group>"; };
F6BB7DF01BF681BC00D0A69E /* base64.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = base64.hpp; sourceTree = "<group>"; };
F6BCCFDF1C83809A00FE31AE /* lib */ = {isa = PBXFileReference; lastKnownFileType = folder; path = lib; sourceTree = SOURCE_ROOT; };
F6C3FBBC1BF680EC00E6FFD4 /* json.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = json.hpp; sourceTree = "<group>"; };
F6C74DEE1C732CC500C9DDCD /* RealmAnalytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmAnalytics.h; path = "react-native/RealmAnalytics.h"; sourceTree = "<group>"; };
F6C74DEF1C732CC500C9DDCD /* RealmAnalytics.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmAnalytics.mm; path = "react-native/RealmAnalytics.mm"; sourceTree = "<group>"; };
@ -308,6 +310,7 @@
0270BC3D1B7CFBFD00010E03 /* RealmJS */ = {
isa = PBXGroup;
children = (
F6BCCFDF1C83809A00FE31AE /* lib */,
F62A35131C18E6E2004A917D /* iOS */,
F62A35141C18E783004A917D /* Object Store */,
029048011C0428DF00ABDED4 /* js_init.cpp */,
@ -371,7 +374,7 @@
02B58CC01AE99CEC009B348C /* RealmJSTests */ = {
isa = PBXGroup;
children = (
F61378781C18EAAC008BFC51 /* lib */,
F61378781C18EAAC008BFC51 /* js */,
0270BC781B7D020100010E03 /* Info.plist */,
0270BC7A1B7D020100010E03 /* RealmJSTests.h */,
0270BC7B1B7D020100010E03 /* RealmJSTests.mm */,
@ -735,7 +738,8 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F61378791C18EAC5008BFC51 /* lib in Resources */,
F6BCCFE21C8380A400FE31AE /* lib in Resources */,
F61378791C18EAC5008BFC51 /* js in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -754,7 +758,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "cp src/object-store/parser/queryTests.json \"$TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH/lib/query-tests.json\"";
shellScript = "cp src/object-store/parser/queryTests.json \"$TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH/js/query-tests.json\"";
};
F63FF2C51C12462600B3B8E0 /* Download Core */ = {
isa = PBXShellScriptBuildPhase;

View File

@ -40,7 +40,7 @@ export default class TodoListItem extends React.Component {
get done() {
let items = this.props.item.items;
return items.length > 0 && Array.prototype.every.call(items, (item) => item.done);
return items.length > 0 && items.every((item) => item.done);
}
get text() {

View File

@ -1,13 +1,5 @@
{
"env": {
"commonjs": true,
"browser": true,
"es6": true
},
"ecmaFeatures": {
"forOf": false
},
"globals": {
"global": true
"commonjs": true
}
}

18
lib/browser/.eslintrc Normal file
View File

@ -0,0 +1,18 @@
{
"env": {
"es6": true,
"worker": true
},
"globals": {
"global": true
},
"parserOptions": {
"ecmaFeatures": {
"forOf": false
},
"sourceType": "module"
},
"rules": {
"strict": 0
}
}

View File

@ -23,12 +23,7 @@ const CHAR_MAP = {};
Array.from(CHARS, (char, i) => CHAR_MAP[char] = i);
module.exports = {
decode,
encode,
};
function decode(base64) {
export function decode(base64) {
let length = base64.length;
let byteCount = length * 0.75;
@ -56,7 +51,7 @@ function decode(base64) {
return buffer;
}
function encode(data) {
export function encode(data) {
var byteOffset = 0;
var buffer;

View File

@ -18,9 +18,9 @@
'use strict';
let keys = {};
let objectTypes = {};
let propTypes = {};
export const keys = {};
export const objectTypes = {};
export const propTypes = {};
[
'id',
@ -62,9 +62,3 @@ let propTypes = {};
enumerable: true,
});
});
module.exports = {
keys,
objectTypes,
propTypes
};

View File

@ -18,21 +18,20 @@
'use strict';
const constants = require('./constants');
const lists = require('./lists');
const objects = require('./objects');
const results = require('./results');
const rpc = require('./rpc');
const util = require('./util');
import { keys, propTypes, objectTypes } from './constants';
import * as lists from './lists';
import * as objects from './objects';
import * as results from './results';
import * as rpc from './rpc';
import * as util from './util';
const {keys, propTypes, objectTypes} = constants;
const listenersKey = Symbol();
rpc.registerTypeConverter(objectTypes.LIST, lists.create);
rpc.registerTypeConverter(objectTypes.OBJECT, objects.create);
rpc.registerTypeConverter(objectTypes.RESULTS, results.create);
class Realm {
export default class Realm {
constructor(config) {
let schemas = typeof config == 'object' && config.schema;
let constructors = {};
@ -142,6 +141,12 @@ util.createMethods(Realm.prototype, objectTypes.REALM, [
], true);
Object.defineProperties(Realm, {
List: {
value: lists.List,
},
Results: {
value: results.Results,
},
Types: {
value: Object.freeze(propTypes),
},
@ -159,5 +164,3 @@ Object.defineProperties(Realm, {
// The session ID refers to the Realm constructor object in the RPC server.
Realm[keys.id] = rpc.createSession();
module.exports = Realm;

View File

@ -18,26 +18,24 @@
'use strict';
const constants = require('./constants');
const util = require('./util');
import { objectTypes } from './constants';
import { createCollection, createMethods } from './util';
const {objectTypes} = constants;
module.exports = {
create,
};
class List {}
export class List {
constructor() {
throw new TypeError('Illegal constructor');
}
}
// Non-mutating methods:
util.createMethods(List.prototype, objectTypes.LIST, [
createMethods(List.prototype, objectTypes.LIST, [
'filtered',
'sorted',
'snapshot',
]);
// Mutating methods:
util.createMethods(List.prototype, objectTypes.LIST, [
createMethods(List.prototype, objectTypes.LIST, [
'pop',
'shift',
'push',
@ -45,6 +43,6 @@ util.createMethods(List.prototype, objectTypes.LIST, [
'splice',
], true);
function create(realmId, info) {
return util.createList(List.prototype, realmId, info, true);
export function create(realmId, info) {
return createCollection(List.prototype, realmId, info, true);
}

View File

@ -18,18 +18,12 @@
'use strict';
const constants = require('./constants');
const util = require('./util');
import { keys } from './constants';
import { getterForProperty, setterForProperty } from './util';
const {keys} = constants;
const registeredConstructors = {};
module.exports = {
create,
registerConstructors,
};
function create(realmId, info) {
export function create(realmId, info) {
let schema = info.schema;
let constructor = (registeredConstructors[realmId] || {})[schema.name];
let object = constructor ? Object.create(constructor.prototype) : {};
@ -41,8 +35,8 @@ function create(realmId, info) {
schema.properties.forEach((name) => {
Object.defineProperty(object, name, {
enumerable: true,
get: util.getterForProperty(name),
set: util.setterForProperty(name),
get: getterForProperty(name),
set: setterForProperty(name),
});
});
@ -56,6 +50,6 @@ function create(realmId, info) {
return object;
}
function registerConstructors(realmId, constructors) {
export function registerConstructors(realmId, constructors) {
registeredConstructors[realmId] = constructors;
}

View File

@ -18,21 +18,21 @@
'use strict';
const constants = require('./constants');
const util = require('./util');
import { objectTypes } from './constants';
import { createCollection, createMethods } from './util';
module.exports = {
create,
};
export class Results {
constructor() {
throw new TypeError('Illegal constructor');
}
}
class Results {}
util.createMethods(Results.prototype, constants.objectTypes.RESULTS, [
createMethods(Results.prototype, objectTypes.RESULTS, [
'filtered',
'sorted',
'snapshot',
]);
function create(realmId, info) {
return util.createList(Results.prototype, realmId, info);
export function create(realmId, info) {
return createCollection(Results.prototype, realmId, info);
}

View File

@ -18,12 +18,11 @@
'use strict';
const base64 = require('./base64');
const constants = require('./constants');
import * as base64 from './base64';
import { keys, objectTypes } from './constants';
const DEVICE_HOST = 'localhost:8082';
const {keys, objectTypes} = constants;
const {id: idKey, realm: realmKey} = keys;
const typeConverters = {};
@ -38,35 +37,20 @@ if (XMLHttpRequest.__proto__ != global.XMLHttpRequestEventTarget) {
global.XMLHttpRequest = fakeXMLHttpRequest;
}
module.exports = {
registerTypeConverter,
createSession,
createRealm,
callMethod,
getProperty,
setProperty,
beginTransaction,
cancelTransaction,
commitTransaction,
clearTestState,
};
registerTypeConverter(objectTypes.DATA, (_, {value}) => base64.decode(value));
registerTypeConverter(objectTypes.DATE, (_, {value}) => new Date(value));
registerTypeConverter(objectTypes.DICT, deserializeDict);
function registerTypeConverter(type, handler) {
export function registerTypeConverter(type, handler) {
typeConverters[type] = handler;
}
function createSession() {
export function createSession() {
sessionId = sendRequest('create_session');
return sessionId;
}
function createRealm(args) {
export function createRealm(args) {
if (args) {
args = args.map((arg) => serialize(null, arg));
}
@ -74,7 +58,7 @@ function createRealm(args) {
return sendRequest('create_realm', {arguments: args});
}
function callMethod(realmId, id, name, args) {
export function callMethod(realmId, id, name, args) {
if (args) {
args = args.map((arg) => serialize(realmId, arg));
}
@ -83,29 +67,29 @@ function callMethod(realmId, id, name, args) {
return deserialize(realmId, result);
}
function getProperty(realmId, id, name) {
export function getProperty(realmId, id, name) {
let result = sendRequest('get_property', {realmId, id, name});
return deserialize(realmId, result);
}
function setProperty(realmId, id, name, value) {
export function setProperty(realmId, id, name, value) {
value = serialize(realmId, value);
sendRequest('set_property', {realmId, id, name, value});
}
function beginTransaction(realmId) {
export function beginTransaction(realmId) {
sendRequest('begin_transaction', {realmId});
}
function cancelTransaction(realmId) {
export function cancelTransaction(realmId) {
sendRequest('cancel_transaction', {realmId});
}
function commitTransaction(realmId) {
export function commitTransaction(realmId) {
sendRequest('commit_transaction', {realmId});
}
function clearTestState() {
export function clearTestState() {
sendRequest('clear_test_state');
}

View File

@ -18,22 +18,11 @@
'use strict';
const constants = require('./constants');
const rpc = require('./rpc');
import { keys } from './constants';
import * as rpc from './rpc';
const {keys} = constants;
let mutationListeners = {};
module.exports = {
clearMutationListeners,
fireMutationListeners,
createList,
createMethods,
createMethod,
getterForProperty,
setterForProperty,
};
function addMutationListener(realmId, callback) {
let listeners = mutationListeners[realmId] || (mutationListeners[realmId] = new Set());
listeners.add(callback);
@ -46,18 +35,18 @@ function removeMutationListener(realmId, callback) {
}
}
function clearMutationListeners() {
export function clearMutationListeners() {
mutationListeners = {};
}
function fireMutationListeners(realmId) {
export function fireMutationListeners(realmId) {
let listeners = mutationListeners[realmId];
if (listeners) {
listeners.forEach((cb) => cb());
}
}
function createList(prototype, realmId, info, mutable) {
export function createCollection(prototype, realmId, info, mutable) {
let list = Object.create(prototype);
let size = 0;
@ -129,7 +118,7 @@ function createList(prototype, realmId, info, mutable) {
return list;
}
function createMethods(prototype, type, methodNames, mutates) {
export function createMethods(prototype, type, methodNames, mutates) {
let props = {};
methodNames.forEach((name) => {
@ -141,7 +130,7 @@ function createMethods(prototype, type, methodNames, mutates) {
Object.defineProperties(prototype, props);
}
function createMethod(type, name, mutates) {
export function createMethod(type, name, mutates) {
return function() {
let realmId = this[keys.realm];
let id = this[keys.id];
@ -163,13 +152,13 @@ function createMethod(type, name, mutates) {
};
}
function getterForProperty(name) {
export function getterForProperty(name) {
return function() {
return rpc.getProperty(this[keys.realm], this[keys.id], name);
};
}
function setterForProperty(name) {
export function setterForProperty(name) {
return function(value) {
let realmId = this[keys.realm];

View File

@ -18,12 +18,44 @@
'use strict';
var realmConstructor;
if (typeof Realm != 'undefined') {
// The global Realm constructor should be available on device (using JavaScriptCore).
module.exports = Realm; // eslint-disable-line no-undef
} else if (navigator.userAgent) {
realmConstructor = Realm; // eslint-disable-line no-undef
} else if (typeof navigator != 'undefined' && navigator.userAgent) { // eslint-disable-line no-undef
// The userAgent will be defined when running in a browser (such as Chrome debugging mode).
module.exports = require('./realm');
realmConstructor = require('./browser').default; // (exported as ES6 module)
} else {
throw new Error('Missing Realm constructor - please ensure RealmReact framework is included!');
}
var arrayPrototype = Array.prototype;
var arrayMethods = {};
[
'join',
'slice',
'forEach',
'every',
'some',
'find',
'findIndex',
'map',
'reduce',
'reduceRight',
'entries',
'keys',
'values',
].forEach(function(methodName) {
var method = arrayPrototype[methodName];
if (method) {
arrayMethods[methodName] = {value: method};
}
});
// Add the specified Array methods to the prototype of List and Results.
Object.defineProperties(realmConstructor.List.prototype, arrayMethods);
Object.defineProperties(realmConstructor.Results.prototype, arrayMethods);
module.exports = realmConstructor;

View File

@ -19,6 +19,8 @@
#include "js_init.h"
#include "js_realm.hpp"
#include "js_object.hpp"
#include "js_list.hpp"
#include "js_results.hpp"
#include "js_util.hpp"
#include "js_schema.hpp"
#include "platform.hpp"
@ -54,27 +56,36 @@ JSClassRef RJSRealmTypeClass() {
return JSClassCreate(&realmTypesDefinition);
}
static JSObjectRef UncallableConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
*exception = RJSMakeError(ctx, "Illegal constructor");
return NULL;
}
static JSValueRef ClearTestState(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) {
RJSClearTestState();
return NULL;
}
JSObjectRef RJSConstructorCreate(JSContextRef ctx) {
static JSStringRef clearTestStateString = JSStringCreateWithUTF8CString("clearTestState");
static JSStringRef listString = JSStringCreateWithUTF8CString("List");
static JSStringRef resultsString = JSStringCreateWithUTF8CString("Results");
static JSStringRef typeString = JSStringCreateWithUTF8CString("Types");
JSObjectRef realmObject = JSObjectMake(ctx, RJSRealmConstructorClass(), NULL);
JSObjectRef typesObject = JSObjectMake(ctx, RJSRealmTypeClass(), NULL);
JSValueRef exception = NULL;
JSStringRef typeString = JSStringCreateWithUTF8CString("Types");
JSPropertyAttributes attributes = kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete;
JSObjectSetProperty(ctx, realmObject, typeString, typesObject, attributes, &exception);
JSStringRelease(typeString);
assert(!exception);
JSStringRef clearTestStateString = JSStringCreateWithUTF8CString("clearTestState");
JSObjectRef listConstructor = JSObjectMakeConstructor(ctx, RJSListClass(), UncallableConstructor);
RJSValidatedSetProperty(ctx, realmObject, listString, listConstructor, attributes);
JSObjectRef resultsContructor = JSObjectMakeConstructor(ctx, RJSResultsClass(), UncallableConstructor);
RJSValidatedSetProperty(ctx, realmObject, resultsString, resultsContructor, attributes);
JSObjectRef typesObject = JSObjectMake(ctx, RJSRealmTypeClass(), NULL);
RJSValidatedSetProperty(ctx, realmObject, typeString, typesObject, attributes);
JSObjectRef clearTestStateFunction = JSObjectMakeFunctionWithCallback(ctx, clearTestStateString, ClearTestState);
JSObjectSetProperty(ctx, realmObject, clearTestStateString, clearTestStateFunction, attributes, &exception);
JSStringRelease(clearTestStateString);
assert(!exception);
RJSValidatedSetProperty(ctx, realmObject, clearTestStateString, clearTestStateFunction, attributes);
return realmObject;
}

View File

@ -217,16 +217,22 @@ JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t a
}
}
bool RealmHasInstance(JSContextRef ctx, JSObjectRef constructor, JSValueRef value, JSValueRef* exception) {
return JSValueIsObjectOfClass(ctx, value, RJSRealmClass());
}
static const JSStaticValue RealmStaticProperties[] = {
{"defaultPath", GetDefaultPath, SetDefaultPath, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{NULL, NULL}
};
JSClassRef RJSRealmConstructorClass() {
JSClassDefinition realmConstructorDefinition = kJSClassDefinitionEmpty;
realmConstructorDefinition.className = "Realm";
realmConstructorDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
realmConstructorDefinition.className = "RealmConstructor";
realmConstructorDefinition.callAsConstructor = RealmConstructor;
JSStaticValue realmStaticProperties[] = {
{"defaultPath", GetDefaultPath, SetDefaultPath, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{NULL, NULL}
};
realmConstructorDefinition.staticValues = realmStaticProperties;
realmConstructorDefinition.hasInstance = RealmHasInstance;
realmConstructorDefinition.staticValues = RealmStaticProperties;
return JSClassCreate(&realmConstructorDefinition);
}

View File

@ -201,6 +201,14 @@ static inline size_t RJSValidatedListLength(JSContextRef ctx, JSObjectRef object
return RJSValidatedValueToNumber(ctx, lengthValue);
}
static inline void RJSValidatedSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes = 0) {
JSValueRef exception = NULL;
JSObjectSetProperty(ctx, object, propertyName, value, attributes, &exception);
if (exception) {
throw RJSException(ctx, exception);
}
}
template<typename T>
T stot(const std::string s) {
std::istringstream iss(s);

View File

@ -32,14 +32,21 @@
+ (XCTestSuite *)defaultTestSuite {
XCTestSuite *suite = [super defaultTestSuite];
JSContext *context = [[JSContext alloc] init];
JSValue *realmConstructor = [JSValue valueWithJSValueRef:RJSConstructorCreate(context.JSGlobalContextRef) inContext:context];
RJSModuleLoader *moduleLoader = [[RJSModuleLoader alloc] initWithContext:context];
NSURL *scriptURL = [[NSBundle bundleForClass:self] URLForResource:@"index" withExtension:@"js" subdirectory:@"lib"];
NSURL *realmURL = [[NSBundle bundleForClass:self] URLForResource:@"index" withExtension:@"js" subdirectory:@"lib"];
NSURL *scriptURL = [[NSBundle bundleForClass:self] URLForResource:@"index" withExtension:@"js" subdirectory:@"js"];
NSError *error;
// Create Realm constructor in the JS context.
RJSInitializeInContext(context.JSGlobalContextRef);
// Load the Realm module so additional functionality is exposed on Realm objects.
JSValue *realmConstructor = [moduleLoader loadModuleFromURL:realmURL error:&error];
NSAssert(realmConstructor, @"%@", error);
// Expose the Realm constructor as a global 'realm' CommonJS module.
[moduleLoader addGlobalModuleObject:realmConstructor forName:@"realm"];
NSError *error;
JSValue *testObject = [moduleLoader loadModuleFromURL:scriptURL error:&error];
NSAssert(testObject, @"%@", error);
@ -76,7 +83,7 @@
NSURL *sourceURL = nil;
if (source) {
NSString *path = [NSString pathWithComponents:@[[@(__FILE__) stringByDeletingLastPathComponent], @"..", @"lib", source.lastPathComponent]];
NSString *path = [NSString pathWithComponents:@[[@(__FILE__) stringByDeletingLastPathComponent], @"..", @"js", source.lastPathComponent]];
sourceURL = [NSURL URLWithString:path];
}

View File

@ -24,7 +24,20 @@ var TestCase = require('./asserts');
var schemas = require('./schemas');
module.exports = BaseTest.extend({
testArrayLength: function() {
testListConstructor: function() {
var realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]});
realm.write(function() {
var obj = realm.create('PersonList', {list: []});
TestCase.assertTrue(obj.list instanceof Realm.List);
});
TestCase.assertThrows(function() {
new Realm.List();
});
},
testListLength: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;
@ -52,7 +65,7 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(array.length, 2);
},
testArraySubscriptGetters: function() {
testListSubscriptGetters: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;
@ -72,7 +85,7 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(array[-1], undefined);
},
testArraySubscriptSetters: function() {
testListSubscriptSetters: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;
@ -110,7 +123,7 @@ module.exports = BaseTest.extend({
}, 'cannot set list item outside write transaction');
},
testArrayInvalidProperty: function() {
testListInvalidProperty: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;
@ -127,7 +140,7 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(undefined, array.ablasdf);
},
testArrayEnumerate: function() {
testListEnumerate: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var obj;
@ -160,7 +173,7 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(keys.length, 2);
},
testPush: function() {
testListPush: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;
@ -194,7 +207,7 @@ module.exports = BaseTest.extend({
}, 'can only push in a write transaction');
},
testPop: function() {
testListPop: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;
@ -222,7 +235,7 @@ module.exports = BaseTest.extend({
}, 'can only pop in a write transaction');
},
testUnshift: function() {
testListUnshift: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;
@ -252,7 +265,7 @@ module.exports = BaseTest.extend({
}, 'can only unshift in a write transaction');
},
testShift: function() {
testListShift: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;
@ -280,7 +293,7 @@ module.exports = BaseTest.extend({
}, 'can only shift in a write transaction');
},
testSplice: function() {
testListSplice: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;
@ -345,7 +358,7 @@ module.exports = BaseTest.extend({
}, 'can only splice in a write transaction');
},
testDeletions: function() {
testListDeletions: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var object;
var array;
@ -424,7 +437,7 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(objects.length, 4);
},
testStaticResults: function() {
testListSnapshot: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var objects = realm.objects('TestObject');
var array;
@ -498,7 +511,7 @@ module.exports = BaseTest.extend({
});
var names = function(results, prop) {
return Array.prototype.map.call(results, function(object) {
return results.map(function(object) {
return object.name;
});
};
@ -509,4 +522,61 @@ module.exports = BaseTest.extend({
objects = list.sorted(['age', 'name']);
TestCase.assertArraysEqual(names(objects), ['Ari', 'Tim', 'Alex', 'Bjarne']);
},
testArrayMethods: function() {
var realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]});
var object;
realm.write(function() {
object = realm.create('PersonList', {list: [
{name: 'Ari', age: 10},
{name: 'Tim', age: 11},
{name: 'Bjarne', age: 12},
]});
});
[
object.list,
realm.objects('PersonObject'),
].forEach(function(list) {
TestCase.assertEqual(list.slice().length, 3);
TestCase.assertEqual(list.slice(-1).length, 1);
TestCase.assertEqual(list.slice(-1)[0].age, 12);
TestCase.assertEqual(list.slice(1, 3).length, 2);
TestCase.assertEqual(list.slice(1, 3)[1].age, 12);
TestCase.assertEqual(list.join(' '), 'Ari Tim Bjarne');
var count = 0;
list.forEach(function(p, i) {
TestCase.assertEqual(p.name, list[i].name);
count++;
});
TestCase.assertEqual(count, list.length);
TestCase.assertArraysEqual(list.map(function(p) {return p.age}), [10, 11, 12]);
TestCase.assertTrue(list.some(function(p) {return p.age > 10}));
TestCase.assertTrue(list.every(function(p) {return p.age > 0}));
var person = list.find(function(p) {return p.name == 'Tim'});
TestCase.assertEqual(person.name, 'Tim');
var index = list.findIndex(function(p) {return p.name == 'Tim'});
TestCase.assertEqual(index, 1);
TestCase.assertEqual(list.reduce(function(n, p) {return n + p.age}, 0), 33);
TestCase.assertEqual(list.reduceRight(function(n, p) {return n + p.age}, 0), 33);
// Some of these may not be present in every environment.
if (list.entries) {
TestCase.assertEqual(list.entries().next().value[1].name, 'Ari');
}
if (list.keys) {
TestCase.assertEqual(list.keys().next().value, 0);
}
if (list.values) {
TestCase.assertEqual(list.values().next().value.name, 'Ari');
}
});
},
});

View File

@ -97,8 +97,8 @@ function runQuerySuite(suite) {
throw "Primary key required for object comparison";
}
TestCase.assertArraysEqual(test[1], Array.prototype.map.call(results, function(el) {
return el[primary]
TestCase.assertArraysEqual(test[1], results.map(function(el) {
return el[primary];
}));
}
else if (test[0] == "QueryThrows") {

View File

@ -25,6 +25,11 @@ var schemas = require('./schemas');
var util = require('./util');
module.exports = BaseTest.extend({
testRealmConstructor: function() {
var realm = new Realm({schema: []});
TestCase.assertTrue(realm instanceof Realm);
},
testRealmConstructorPath: function() {
TestCase.assertThrows(function() {
new Realm('/invalidpath');

View File

@ -24,6 +24,17 @@ var TestCase = require('./asserts');
var schemas = require('./schemas');
module.exports = BaseTest.extend({
testResultsConstructor: function() {
var realm = new Realm({schema: [schemas.TestObject]});
var objects = realm.objects('TestObject');
TestCase.assertTrue(objects instanceof Realm.Results);
TestCase.assertThrows(function() {
new Realm.Results();
});
},
testResultsLength: function() {
var realm = new Realm({schema: [schemas.TestObject]});
var objects = realm.objects('TestObject');
@ -35,6 +46,7 @@ module.exports = BaseTest.extend({
});
TestCase.assertEqual(objects.length, 1);
},
testResultsSubscript: function() {
var realm = new Realm({schema: [schemas.PersonObject]});
realm.write(function() {
@ -50,6 +62,7 @@ module.exports = BaseTest.extend({
TestCase.assertTrue(Object.getPrototypeOf(people[0]) === schemas.PersonObject.prototype);
TestCase.assertTrue(people[0] instanceof schemas.PersonObject);
},
testResultsReadonly: function() {
var realm = new Realm({schema: [schemas.TestObject]});
var objects = realm.objects('TestObject');
@ -71,17 +84,20 @@ module.exports = BaseTest.extend({
objects.length = 0;
});
},
testResultsInvalidProperty: function() {
var realm = new Realm({schema: [schemas.TestObject]});
var objects = realm.objects('TestObject');
TestCase.assertEqual(undefined, objects.ablasdf);
},
testResultsInvalidObjectType: function() {
var realm = new Realm({schema: [schemas.TestObject]});
TestCase.assertThrows(function() {
var objects = realm.objects('NotTestObject');
});
},
testResultsEnumerate: function() {
var realm = new Realm({schema: [schemas.TestObject]});
var objects = realm.objects('TestObject');
@ -105,6 +121,7 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(count, 1);
TestCase.assertEqual(keys.length, 1);
},
testResultsFiltered: function() {
var realm = new Realm({schema: [schemas.PersonObject, schemas.DefaultValues, schemas.TestObject]});
realm.write(function() {
@ -149,6 +166,7 @@ module.exports = BaseTest.extend({
realm.objects('PersonObject').filtered("invalidQuery");
});
},
testResultsSorted: function() {
var realm = new Realm({schema: [schemas.IntPrimary]});
var objects = realm.objects('IntPrimaryObject');
@ -162,7 +180,7 @@ module.exports = BaseTest.extend({
});
var primaries = function(results, prop) {
return Array.prototype.map.call(results, function(object) {
return results.map(function(object) {
return object.primaryCol;
});
};

View File

@ -39,6 +39,9 @@ PersonObject.schema = {
PersonObject.prototype.description = function() {
return this.name + ' ' + this.age;
};
PersonObject.prototype.toString = function() {
return this.name;
};
exports.PersonObject = PersonObject;
exports.PersonList = {

View File

@ -10,6 +10,6 @@
"react-native-fs": "^1.1.0",
"xmlbuilder": "^4.2.1",
"realm": "file:../..",
"realm-tests": "file:../lib"
"realm-tests": "file:../js"
}
}