diff --git a/.vscode/launch.json b/.vscode/launch.json index 09612ab2..347e625d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,24 +4,6 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { - "type": "lldb", - "request": "launch", - "name": "Debug LLDB", - "program": "node", - "cwd": "${workspaceRoot}/tests", - "args": ["--debug-brk=5858", "${workspaceRoot}/tests/node_modules/jasmine/bin/jasmine.js", "spec/unit_tests.js"], - "stopOnEntry": true - }, - { - "type": "lldb", - "request": "launch", - "name": "Debug LLDB only", - "program": "node", - "cwd": "${workspaceRoot}/tests", - "args": ["${workspaceRoot}/tests/node_modules/jasmine/bin/jasmine.js", "spec/unit_tests.js"], - "stopOnEntry": false - }, { "type": "node", "request": "launch", @@ -42,30 +24,6 @@ "args": [ "spec/unit_tests.js" ] - }, - { - "type": "node", - "request": "launch", - "name": "Download & Start Server", - "cwd": "${workspaceRoot}/scripts" - - }, - { - "type": "node", - "request": "attach", - "name": "Attach to Port", - "address": "localhost", - "port": 5858 - } - ], - "compounds": [ - { - "name": "Rebuild + Start Server + Debug", - "configurations": ["Download & Start Server", "Debug Node Unit Tests (rebuild)"] - }, - { - "name": "Debug LLDB + NodeJS", - "configurations": ["Debug LLDB", "Attach to Port"] } ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index adb49f34..a8a937e6 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,33 +2,15 @@ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "0.1.0", + "command": "npm", + "isShellCommand": true, + "showOutput": "always", + "suppressTaskName": true, "tasks": [ { - "taskName": "Rebuild Node Tests", - "command": "npm", - "isShellCommand": true, - "showOutput": "always", - "suppressTaskName": true, - "args": ["run", "rebuild-changes"], - "isBuildCommand": false - }, - { - "taskName": "Build Node Tests", - "command": "npm", - "isShellCommand": true, - "showOutput": "always", - "suppressTaskName": true, - "args": ["run", "build-changes"], - "isBuildCommand": true - }, - { - "taskName": "Download and Start Server", - "command": "${workspaceRoot}/scripts/download_and_start_server.sh", - "isShellCommand": true, - "showOutput": "always", - "echoCommand": true, - "isBackground": true, - "suppressTaskName": true + "taskName": "rebuild-node-tests", + + "args": ["run", "prenode-tests"] } ] } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e8018f01..97e7727d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ Old files can still be opened and files open in read-only mode will not be modif * The SyncConfig now gets two more optional parameters, `validate_ssl` and `ssl_trust_certificate_path`. ### Enhancements -* Add Realm open async API support. +* None ### Bug fixes * None diff --git a/lib/extensions.js b/lib/extensions.js index 3bcdb051..727b910a 100644 --- a/lib/extensions.js +++ b/lib/extensions.js @@ -40,35 +40,6 @@ module.exports = function(realmConstructor) { setConstructorOnPrototype(realmConstructor.Results); setConstructorOnPrototype(realmConstructor.Object); - //Add async open API - Object.defineProperties(realmConstructor, getOwnPropertyDescriptors({ - open(config) { - return new Promise((resolve, reject) => { - realmConstructor._waitForDownload(config, (error) => { - if (error) { - reject(error); - } - - let syncedRealm = new realmConstructor(config); - //FIXME: RN hangs here. Remove when node's makeCallback alternative is implemented - setTimeout(() => { resolve(syncedRealm); }, 1); - }); - }); - }, - - openAsync(config, callback) { - realmConstructor._waitForDownload(config, (error) => { - if (error) { - callback(error); - } - - let syncedRealm = new realmConstructor(config); - //FIXME: RN hangs here. Remove when node's makeCallback alternative is implemented - setTimeout(() => { callback(null, syncedRealm); }, 1); - }); - }, - })); - // Add sync methods if (realmConstructor.Sync) { let userMethods = require('./user-methods'); diff --git a/package.json b/package.json index 90c1571a..6e9ece16 100644 --- a/package.json +++ b/package.json @@ -48,12 +48,10 @@ "set-version": "scripts/set-version.sh", "get-core-version": "env-cmd ./dependencies.list node -p process.env.REALM_CORE_VERSION", "get-sync-version": "env-cmd ./dependencies.list node -p process.env.REALM_SYNC_VERSION", - "lint": "eslint", + "lint": "eslint", "test": "scripts/test.sh", "install": "node-pre-gyp install --fallback-to-build", - "build-changes": "node-pre-gyp build --fallback-to-build --debug --build-from-source", - "rebuild-changes": "node-pre-gyp install --fallback-to-build --debug --build-from-source && cd tests && npm install", - "prepublish": "echo prepublishing && node scripts/prepublish.js", + "prepublish": "node scripts/prepublish.js", "eslint": "npm install && npm run lint .", "license-check": "npm install && license-checker --exclude \"MIT,ISC,BSD,Apache-2.0,BSD-2-Clause,BSD-3-Clause,WTFPL,Unlicense,(MIT AND CC-BY-3.0)\" | node scripts/handle-license-check.js", "jsdoc:clean": "rimraf ./docs/output", diff --git a/scripts/download_and_start_server.sh b/scripts/download_and_start_server.sh deleted file mode 100755 index 40e3842c..00000000 --- a/scripts/download_and_start_server.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -set -o pipefail -set -e -echo $(pwd) -sh scripts/download-object-server.sh && sh object-server-for-testing/start-object-server.command -f && echo \"Server PID: $!\" \ No newline at end of file diff --git a/src/event_loop_dispatcher.hpp b/src/event_loop_dispatcher.hpp index df454fd6..1d08e036 100644 --- a/src/event_loop_dispatcher.hpp +++ b/src/event_loop_dispatcher.hpp @@ -45,21 +45,13 @@ template class EventLoopDispatcher { using Tuple = std::tuple::type...>; private: - - struct Callback; - struct State { public: - State(std::function func) : - m_func(func), - m_signal(nullptr) - { - } + State(std::function func) : m_func(func) { } const std::function m_func; std::queue m_invocations; std::mutex m_mutex; - std::shared_ptr> m_signal; }; const std::shared_ptr m_state; @@ -75,7 +67,6 @@ private: ::_apply_polyfill::apply(tuple, m_state->m_func); m_state->m_invocations.pop(); } - m_state->m_signal.reset(); } }; const std::shared_ptr> m_signal; @@ -101,7 +92,6 @@ public: { std::unique_lock lock(m_state->m_mutex); - m_state->m_signal = m_signal; m_state->m_invocations.push(std::make_tuple(args...)); } m_signal->notify(); diff --git a/src/js_realm.hpp b/src/js_realm.hpp index 01d7899a..b96e1eec 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -164,8 +164,6 @@ class RealmClass : public ClassDefinition> { public: using ObjectDefaultsMap = typename Schema::ObjectDefaultsMap; using ConstructorMap = typename Schema::ConstructorMap; - - using WaitHandler = void(std::error_code); static FunctionType create_constructor(ContextType); @@ -177,7 +175,6 @@ public: static void delete_all(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); static void write(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); static void add_listener(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); - static void wait_for_download_completion(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); static void remove_listener(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); static void remove_all_listeners(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); static void close(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); @@ -209,7 +206,6 @@ public: {"schemaVersion", wrap}, {"clearTestState", wrap}, {"copyBundledRealmFiles", wrap}, - {"_waitForDownload", wrap}, }; PropertyMap const static_properties = { @@ -541,78 +537,6 @@ void RealmClass::get_sync_session(ContextType ctx, ObjectType object, ReturnV } } - -template -void RealmClass::wait_for_download_completion(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { - validate_argument_count(argc, 2); - auto config_object = Value::validated_to_object(ctx, arguments[0]); - auto callback_function = Value::validated_to_function(ctx, arguments[1]); - - ValueType sync_config_value = Object::get_property(ctx, config_object, "sync"); - if (!Value::is_undefined(ctx, sync_config_value)) { - realm::Realm::Config config; - static const String encryption_key_string = "encryptionKey"; - ValueType encryption_key_value = Object::get_property(ctx, config_object, encryption_key_string); - if (!Value::is_undefined(ctx, encryption_key_value)) { - std::string encryption_key = NativeAccessor::to_binary(ctx, encryption_key_value); - config.encryption_key = std::vector(encryption_key.begin(), encryption_key.end()); - } - - Protected thiz(ctx, this_object); - SyncClass::populate_sync_config(ctx, thiz, config_object, config); - - Protected protected_callback(ctx, callback_function); - Protected protected_this(ctx, this_object); - Protected protected_ctx(Context::get_global_context(ctx)); - - EventLoopDispatcher wait_handler([=](std::error_code error_code) { - HANDLESCOPE - if (!error_code) { - //success - Function::callback(protected_ctx, protected_callback, protected_this, 0, nullptr); - } - else { - //fail - ObjectType object = Object::create_empty(protected_ctx); - Object::set_property(protected_ctx, object, "message", Value::from_string(protected_ctx, error_code.message())); - Object::set_property(protected_ctx, object, "errorCode", Value::from_number(protected_ctx, error_code.value())); - - ValueType callback_arguments[1]; - callback_arguments[0] = object; - Function::callback(protected_ctx, protected_callback, protected_this, 1, callback_arguments); - } - }); - std::function waitFunc = std::move(wait_handler); - - auto realm = realm::Realm::get_shared_realm(config); - if (auto sync_config = config.sync_config) { - std::shared_ptr user = sync_config->user; - if (user && user->state() != SyncUser::State::Error) { - if (auto session = user->session_for_on_disk_path(config.path)) { - session->wait_for_download_completion([=](std::error_code error_code) { - realm->config(); //capture and keep realm instance for till here - waitFunc(error_code); - }); - return; - } - } - - ObjectType object = Object::create_empty(protected_ctx); - Object::set_property(protected_ctx, object, "message", Value::from_string(protected_ctx, "Cannot asynchronously open synced Realm, because the associated session previously experienced a fatal error")); - Object::set_property(protected_ctx, object, "errorCode", Value::from_number(protected_ctx, 1)); - - ValueType callback_arguments[1]; - callback_arguments[0] = object; - Function::call(protected_ctx, protected_callback, protected_this, 1, callback_arguments); - return; - } - } - - ValueType callback_arguments[1]; - callback_arguments[0] = Value::from_null(ctx); - Function::call(ctx, callback_function, this_object, 1, callback_arguments); -} - #endif template @@ -798,4 +722,4 @@ void RealmClass::close(ContextType ctx, FunctionType, ObjectType this_object, } } // js -} // realm \ No newline at end of file +} // realm diff --git a/src/js_types.hpp b/src/js_types.hpp index 1c6a3aec..8a5a10be 100644 --- a/src/js_types.hpp +++ b/src/js_types.hpp @@ -151,7 +151,6 @@ struct Function { using ObjectType = typename T::Object; using ValueType = typename T::Value; - static ValueType callback(ContextType, const FunctionType &, const ObjectType &, size_t, const ValueType[]); static ValueType call(ContextType, const FunctionType &, const ObjectType &, size_t, const ValueType[]); template static ValueType call(ContextType ctx, const FunctionType &function, const ObjectType &this_object, const ValueType (&arguments)[N]) diff --git a/src/jsc/jsc_function.hpp b/src/jsc/jsc_function.hpp index da3f2a3d..866c973f 100644 --- a/src/jsc/jsc_function.hpp +++ b/src/jsc/jsc_function.hpp @@ -33,11 +33,6 @@ inline JSValueRef jsc::Function::call(JSContextRef ctx, const JSObjectRef &funct return result; } -template<> -inline JSValueRef jsc::Function::callback(JSContextRef ctx, const JSObjectRef &function, const JSObjectRef &this_object, size_t argc, const JSValueRef arguments[]) { - return jsc::Function::call(ctx, function, this_object, argc, arguments); -} - template<> inline JSObjectRef jsc::Function::construct(JSContextRef ctx, const JSObjectRef &function, size_t argc, const JSValueRef arguments[]) { JSValueRef exception = nullptr; diff --git a/src/node/node_function.hpp b/src/node/node_function.hpp index cb07959a..39e90720 100644 --- a/src/node/node_function.hpp +++ b/src/node/node_function.hpp @@ -36,19 +36,6 @@ inline v8::Local node::Function::call(v8::Isolate* isolate, const v8: return result.ToLocalChecked(); } -template<> -inline v8::Local node::Function::callback(v8::Isolate* isolate, const v8::Local &function, const v8::Local &this_object, size_t argc, const v8::Local arguments[]) { - Nan::TryCatch trycatch; - - auto recv = this_object.IsEmpty() ? isolate->GetCurrentContext()->Global() : this_object; - auto result = Nan::MakeCallback(recv, function, (int)argc, const_cast*>(arguments)); - - if (trycatch.HasCaught()) { - throw node::Exception(isolate, trycatch.Exception()); - } - return result; -} - template<> inline v8::Local node::Function::construct(v8::Isolate* isolate, const v8::Local &function, size_t argc, const v8::Local arguments[]) { Nan::TryCatch trycatch; diff --git a/tests/js/download-api-helper.js b/tests/js/download-api-helper.js deleted file mode 100644 index 674e468b..00000000 --- a/tests/js/download-api-helper.js +++ /dev/null @@ -1,34 +0,0 @@ -/* -This script creates 3 new objects into a new realm. These are objects are validated to exists by the download api tests. -*/ -'use strict'; - -const username = process.argv[2]; -const realmName = process.argv[3]; -const realmModule = process.argv[4]; - -var Realm = require(realmModule); -Realm.Sync.User.register('http://localhost:9080', username, 'password', (error, user) => { - if (error) { - console.log(error); - process.exit(-2); - } else { - const config = { - sync: { user, url: `realm://localhost:9080/~/${realmName}`, error: err => console.log(err) }, - schema: [{ name: 'Dog', properties: { name: 'string' } }] - }; - - var realm = new Realm(config); - - realm.write(() => { - for (let i = 1; i <= 3; i++) { - realm.create('Dog', { name: `Lassy ${i}` }); - } - }); - - console.log("Dogs count " + realm.objects('Dog').length); - setTimeout(_ => process.exit(0), 3000); - } -}); - - diff --git a/tests/js/index.js b/tests/js/index.js index 5b6580f8..5ad9b114 100644 --- a/tests/js/index.js +++ b/tests/js/index.js @@ -35,16 +35,11 @@ if (!(typeof process === 'object' && process.platform === 'win32')) { } // If sync is enabled, run the user tests -let hasSync = false; try { Realm.Sync; // This will throw if Sync is disabled. - hasSync = true; -} catch (e) { } - -if (hasSync) { TESTS.UserTests = require('./user-tests'); TESTS.SessionTests = require('./session-tests'); -} +} catch (e) {} function node_require(module) { return require(module); } diff --git a/tests/js/session-tests.js b/tests/js/session-tests.js index 08a5fbd7..c0f88575 100644 --- a/tests/js/session-tests.js +++ b/tests/js/session-tests.js @@ -23,49 +23,17 @@ const Realm = require('realm'); const TestCase = require('./asserts'); -const isNodeProccess = (typeof process === 'object' && process + '' === '[object process]'); -console.log("isnode " + isNodeProccess + " typeof " + typeof process === 'object'); -function node_require(module) { - return require(module); -} - -let tmp; -let fs; -let execFile; - -if (isNodeProccess) { - tmp = node_require('tmp'); - fs = node_require('fs'); - execFile = node_require('child_process').execFile; - tmp.setGracefulCleanup(); -} - - function uuid() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); } function promisifiedRegister(server, username, password) { return new Promise((resolve, reject) => { Realm.Sync.User.register(server, username, password, (error, user) => { if (error) { - console.log(`promisifiedRegister ${error}`); - reject(error); - } else { - resolve(user); - } - }); - }); -} - -function promisifiedLogin(server, username, password) { - return new Promise((resolve, reject) => { - Realm.Sync.User.login(server, username, password, (error, user) => { - if (error) { - console.log(`promisifiedLogin ${error}`); reject(error); } else { resolve(user); @@ -75,7 +43,6 @@ function promisifiedLogin(server, username, password) { } module.exports = { - testLocalRealmHasNoSession() { let realm = new Realm(); TestCase.assertNull(realm.syncSession); @@ -83,25 +50,17 @@ module.exports = { testProperties() { return promisifiedRegister('http://localhost:9080', uuid(), 'password').then(user => { - return new Promise((resolve, reject) => { - + return new Promise((resolve, _reject) => { const accessTokenRefreshed = this; - let successCounter = 0; - function checkSuccess() { - successCounter++; - if (successCounter == 2) { - resolve(); - } - } function postTokenRefreshChecks(sender, error) { try { TestCase.assertEqual(error, accessTokenRefreshed); TestCase.assertEqual(sender.url, `realm://localhost:9080/${user.identity}/myrealm`); - checkSuccess(); + resolve(); } catch (e) { - reject(e) + _reject(e) } }; @@ -111,129 +70,18 @@ module.exports = { const config = { sync: { user, url: 'realm://localhost:9080/~/myrealm', error: postTokenRefreshChecks } }; const realm = new Realm(config); const session = realm.syncSession; + + TestCase.assertInstanceOf(session, Realm.Sync.Session); TestCase.assertEqual(session.user.identity, user.identity); TestCase.assertEqual(session.config.url, config.sync.url); TestCase.assertEqual(session.config.user.identity, config.sync.user.identity); TestCase.assertUndefined(session.url); TestCase.assertEqual(session.state, 'active'); - checkSuccess(); }); }); }, - testRealmOpen() { - if (!isNodeProccess) { - return Promise.resolve(); - } - - const username = uuid(); - const realmName = uuid(); - const expectedObjectsCount = 3; - - let tmpDir = tmp.dirSync(); - let content = fs.readFileSync(__dirname + '/download-api-helper.js', 'utf8'); - let tmpFile = tmp.fileSync({ dir: tmpDir.name }); - fs.appendFileSync(tmpFile.fd, content, { encoding: 'utf8' }); - - return new Promise((resolve, reject) => { - //execute download-api-helper which inserts predefined number of objects into the synced realm. - const child = execFile('node', [tmpFile.name, username, realmName, REALM_MODULE_PATH], { cwd: tmpDir.name }, (error, stdout, stderr) => { - if (error) { - reject(new Error('Error executing download api helper' + error)); - } - resolve(); - }); - }) - .then(() => { - return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { - return new Promise((resolve, reject) => { - const accessTokenRefreshed = this; - let successCounter = 0; - - let config = { - sync: { user, url: `realm://localhost:9080/~/${realmName}` }, - schema: [{ name: 'Dog', properties: { name: 'string' } }], - }; - - Realm.open(config) - .then(realm => { - let actualObjectsCount = realm.objects('Dog').length; - TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Synced realm does not contain the expected objects count"); - - const session = realm.syncSession; - TestCase.assertInstanceOf(session, Realm.Sync.Session); - TestCase.assertEqual(session.user.identity, user.identity); - TestCase.assertEqual(session.config.url, config.sync.url); - TestCase.assertEqual(session.config.user.identity, config.sync.user.identity); - TestCase.assertEqual(session.state, 'active'); - resolve(); - }).catch(e => { reject(e) }); - }); - }); - }); - }, - - testRealmOpenAsync() { - if (!isNodeProccess) { - return Promise.resolve(); - } - - const username = uuid(); - const realmName = uuid(); - const expectedObjectsCount = 3; - - let tmpDir = tmp.dirSync(); - let content = fs.readFileSync(__dirname + '/download-api-helper.js', 'utf8'); - let tmpFile = tmp.fileSync({ dir: tmpDir.name }); - fs.appendFileSync(tmpFile.fd, content, { encoding: 'utf8' }); - - return new Promise((resolve, reject) => { - //execute download-api-helper which inserts predefined number of objects into the synced realm. - const child = execFile('node', [tmpFile.name, username, realmName, REALM_MODULE_PATH], { cwd: tmpDir.name }, (error, stdout, stderr) => { - if (error) { - reject(new Error('Error executing download api helper' + error)); - } - resolve(); - }); - }) - .then(() => { - return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { - return new Promise((resolve, reject) => { - const accessTokenRefreshed = this; - let successCounter = 0; - - let config = { - sync: { user, url: `realm://localhost:9080/~/${realmName}` }, - schema: [{ name: 'Dog', properties: { name: 'string' } }], - }; - - Realm.openAsync(config, (error, realm) => { - try { - if (error) { - reject(error); - } - - let actualObjectsCount = realm.objects('Dog').length; - TestCase.assertEqual(actualObjectsCount, expectedObjectsCount, "Synced realm does not contain the expected objects count"); - - const session = realm.syncSession; - TestCase.assertInstanceOf(session, Realm.Sync.Session); - TestCase.assertEqual(session.user.identity, user.identity); - TestCase.assertEqual(session.config.url, config.sync.url); - TestCase.assertEqual(session.config.user.identity, config.sync.user.identity); - TestCase.assertEqual(session.state, 'active'); - resolve(); - } - catch (e) { - reject(e); - } - }); - }); - }); - }); - }, - testErrorHandling() { return promisifiedRegister('http://localhost:9080', uuid(), 'password').then(user => { return new Promise((resolve, _reject) => { @@ -256,4 +104,4 @@ module.exports = { }); }); } -} \ No newline at end of file +} diff --git a/tests/spec/unit_tests.js b/tests/spec/unit_tests.js index 2826381b..d84d349c 100644 --- a/tests/spec/unit_tests.js +++ b/tests/spec/unit_tests.js @@ -28,10 +28,6 @@ const Realm = require('realm'); const RealmTests = require('../js'); jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; -const isDebuggerAttached = typeof v8debug === 'object'; -if (isDebuggerAttached) { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 3000000; -} // Create this method with appropriate implementation for Node testing. Realm.copyBundledRealmFiles = function() {