From 9399cf001112996f40682a4b85557cc631378779 Mon Sep 17 00:00:00 2001 From: Paul Shapiro Date: Fri, 18 Jan 2019 12:53:41 -0600 Subject: [PATCH] moved core bridge ctor fn back to CoreBridge b/c it's too specific to CoreBridge --- monero_utils/MyMoneroBridge_utils.js | 139 +-------------------------- monero_utils/MyMoneroCoreBridge.js | 133 +++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 145 deletions(-) diff --git a/monero_utils/MyMoneroBridge_utils.js b/monero_utils/MyMoneroBridge_utils.js index 22b86a9..4b77f9c 100644 --- a/monero_utils/MyMoneroBridge_utils.js +++ b/monero_utils/MyMoneroBridge_utils.js @@ -100,141 +100,4 @@ function update_options_for_fallback_to_asmjs(options) options.asmjs = use_asmjs; } } -// -function bridgeModulePromiseCtorFnCtor(ctor_options) -{ - ctor_options = ctor_options || {}; - // - const BridgeClass = ctor_options.BridgeClass; // e.g. MyMoneroCoreBridge or MyMoneroLibAppBridge - const coreBridge_rootContainerDirectory = ctor_options.coreBridge_rootContainerDirectory; // e.g. "monero_utils" - const coreBridge_browserBuildContainerDirName = ctor_options.coreBridge_browserBuildContainerDirName; // e.g. "mymonero_core_js" - const coreBridge_compiledFileNameRootKey = ctor_options.coreBridge_compiledFileNameRootKey; // e.g. "MyMoneroCoreCpp" - // - update_options_for_fallback_to_asmjs(ctor_options) - // - return function(options) - { - const platform_info = detect_platform(); - const ENVIRONMENT_IS_WEB = platform_info.ENVIRONMENT_IS_WEB; - const ENVIRONMENT_IS_WORKER = platform_info.ENVIRONMENT_IS_WORKER; - const ENVIRONMENT_IS_NODE = platform_info.ENVIRONMENT_IS_NODE; - const ENVIRONMENT_IS_SHELL = platform_info.ENVIRONMENT_IS_SHELL; - // - function locateFile(filename, scriptDirectory) - { - // if (options["locateFile"]) { - // return options["locateFile"](filename, scriptDirectory) - // } - var this_scriptDirectory = scriptDirectory - const lastChar = this_scriptDirectory.charAt(this_scriptDirectory.length - 1) - if (lastChar == "/" || lastChar == "\\") { - // ^-- this is not a '\\' on Windows because emscripten actually appends a '/' - this_scriptDirectory = this_scriptDirectory.substring(0, this_scriptDirectory.length - 1) // remove trailing "/" - } - var fullPath = null; // add trailing slash to this - if (ENVIRONMENT_IS_NODE) { - const path = require('path') - const lastPathComponent = path.basename(this_scriptDirectory) - if (lastPathComponent == coreBridge_rootContainerDirectory) { // typical node or electron-main process - fullPath = path.format({ - dir: this_scriptDirectory, - base: filename - }) - } else { - console.warn(`MyMoneroBridge_utils/locateFile() on node.js didn't find "${coreBridge_rootContainerDirectory}" (or possibly MyMoneroCoreBridge.js) itself in the expected location in the following path. The function may need to be expanded but it might in normal situations be likely to be another bug. ${pathTo_cryptonoteUtilsDir}`) - } - } else if (ENVIRONMENT_IS_WEB) { - var pathTo_cryptonoteUtilsDir; - if (typeof __dirname !== undefined && __dirname !== "/") { // looks like node running in browser.. (but not going to assume it's electron-renderer since that should be taken care of by monero_utils.js itself) - // but just in case it is... here's an attempt to support it - // have to check != "/" b/c webpack (I think) replaces __dirname - pathTo_cryptonoteUtilsDir = "file://" + __dirname + "/" // prepending "file://" because it's going to try to stream it - } else { // actual web browser - pathTo_cryptonoteUtilsDir = this_scriptDirectory + `/${coreBridge_browserBuildContainerDirName}/${coreBridge_rootContainerDirectory}/` // this works for the MyMonero browser build, and is quite general, at least - } - fullPath = pathTo_cryptonoteUtilsDir + filename - } - if (fullPath == null) { - throw "Unable to derive fullPath. Please pass locateFile() to bridge obj init." - } - // - return fullPath - } - return new Promise(function(resolve, reject) { - var Module_template = {} - if (options.asmjs != true || options.wasm == true) { // wasm - console.log("Using wasm: ", true) - // - Module_template["locateFile"] = locateFile - // - // NOTE: This requires src/module-post.js to be included as post-js in CMakeLists.txt under a wasm build - const WASM_coreBridge_compiledFileNameRootKey = `${coreBridge_compiledFileNameRootKey}_WASM` - require(`./${WASM_coreBridge_compiledFileNameRootKey}`)(Module_template).ready.then(function(thisModule) - { - const instance = new BridgeClass(thisModule); - resolve(instance); - }).catch(function(e) { - console.error("Error loading ", WASM_coreBridge_compiledFileNameRootKey, ":", e); - reject(e); - }); - } else { // this is synchronous so we can resolve immediately - console.log("Using wasm: ", false) - // - var scriptDirectory=""; // this was extracted from emscripten - it could get factored if anything else would ever need it - if (ENVIRONMENT_IS_NODE) { - scriptDirectory=__dirname+"/"; - } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { - if (ENVIRONMENT_IS_WORKER) { - scriptDirectory = self.location.href - } else if (document.currentScript) { - scriptDirectory = document.currentScript.src - } - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if(_scriptDir){ - scriptDirectory = _scriptDir - } - if (scriptDirectory.indexOf("blob:") !== 0) { - scriptDirectory = scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1) - } else { - scriptDirectory = "" - } - } - var read_fn; - if (ENVIRONMENT_IS_NODE) { - read_fn = function(filepath) - { - return require("fs").readFileSync(require("path").normalize(filepath)).toString() - }; - } else if (ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER) { - read_fn = function(url) - { // it's an option to move this over to fetch, but, fetch requires a polyfill for these older browsers anyway - making fetch an automatic dep just for asmjs fallback - and the github/fetch polyfill does not appear to actually support mode (for 'same-origin' policy) anyway - probably not worth it yet - var xhr = new XMLHttpRequest() - xhr.open("GET", url, false) - xhr.send(null) - // - return xhr.responseText - }; - } else { - throw "Unsupported environment - please implement file reading for asmjs fallback case" - } - const filepath = locateFile(`${coreBridge_compiledFileNameRootKey}_ASMJS.asm.js`, scriptDirectory) - const content = read_fn(filepath) - // TODO: verify content - for now, relying on same-origin and tls/ssl - var Module = {} - try { - eval(content) // I do not believe this is a safety concern, because content is server-controlled; https://humanwhocodes.com/blog/2013/06/25/eval-isnt-evil-just-misunderstood/ - } catch (e) { - reject(e) - return - } - setTimeout(function() - { // "delaying even 1ms is enough to allow compilation memory to be reclaimed" - Module_template['asm'] = Module['asm'] - Module = null - resolve(new BridgeClass(require(`./${coreBridge_compiledFileNameRootKey}_ASMJS`)(Module_template))) - }, 1) - } - }); - } -} -exports.bridgeModulePromiseCtorFnCtor = bridgeModulePromiseCtorFnCtor \ No newline at end of file +exports.update_options_for_fallback_to_asmjs = update_options_for_fallback_to_asmjs; \ No newline at end of file diff --git a/monero_utils/MyMoneroCoreBridge.js b/monero_utils/MyMoneroCoreBridge.js index 7173b42..ce3408f 100644 --- a/monero_utils/MyMoneroCoreBridge.js +++ b/monero_utils/MyMoneroCoreBridge.js @@ -29,11 +29,130 @@ const MyMoneroCoreBridgeClass = require('./MyMoneroCoreBridgeClass') const MyMoneroBridge_utils = require('./MyMoneroBridge_utils') // -const ctor_options = +module.exports = function(options) { - BridgeClass: MyMoneroCoreBridgeClass, - coreBridge_rootContainerDirectory: "monero_utils", - coreBridge_browserBuildContainerDirName: "mymonero_core_js", // not actually used for libapp - coreBridge_compiledFileNameRootKey: "MyMoneroCoreCpp" -}; -module.exports = MyMoneroBridge_utils.bridgeModulePromiseCtorFnCtor(ctor_options); \ No newline at end of file + options = options || {} + + MyMoneroBridge_utils.update_options_for_fallback_to_asmjs(options) + + const platform_info = MyMoneroBridge_utils.detect_platform(); + const ENVIRONMENT_IS_WEB = platform_info.ENVIRONMENT_IS_WEB; + const ENVIRONMENT_IS_WORKER = platform_info.ENVIRONMENT_IS_WORKER; + const ENVIRONMENT_IS_NODE = platform_info.ENVIRONMENT_IS_NODE; + const ENVIRONMENT_IS_SHELL = platform_info.ENVIRONMENT_IS_SHELL; + // + function locateFile(filename, scriptDirectory) + { + // if (options["locateFile"]) { + // return options["locateFile"](filename, scriptDirectory) + // } + var this_scriptDirectory = scriptDirectory + const lastChar = this_scriptDirectory.charAt(this_scriptDirectory.length - 1) + if (lastChar == "/" || lastChar == "\\") { + // ^-- this is not a '\\' on Windows because emscripten actually appends a '/' + this_scriptDirectory = this_scriptDirectory.substring(0, this_scriptDirectory.length - 1) // remove trailing "/" + } + var fullPath = null; // add trailing slash to this + if (ENVIRONMENT_IS_NODE) { + const path = require('path') + const lastPathComponent = path.basename(this_scriptDirectory) + if (lastPathComponent == "monero_utils") { // typical node or electron-main process + fullPath = path.format({ + dir: this_scriptDirectory, + base: filename + }) + } else { + console.warn(`MyMoneroCoreBridge/locateFile() on node.js didn't find "monero_utils" (or possibly MyMoneroCoreBridge.js) itself in the expected location in the following path. The function may need to be expanded but it might in normal situations be likely to be another bug. ${pathTo_cryptonoteUtilsDir}`) + } + } else if (ENVIRONMENT_IS_WEB) { + var pathTo_cryptonoteUtilsDir; + if (typeof __dirname !== undefined && __dirname !== "/") { // looks like node running in browser.. (but not going to assume it's electron-renderer since that should be taken care of by monero_utils.js itself) + // but just in case it is... here's an attempt to support it + // have to check != "/" b/c webpack (I think) replaces __dirname + pathTo_cryptonoteUtilsDir = "file://" + __dirname + "/" // prepending "file://" because it's going to try to stream it + } else { // actual web browser + pathTo_cryptonoteUtilsDir = this_scriptDirectory + `/mymonero_core_js/monero_utils/` // this works for the MyMonero browser build, and is quite general, at least + } + fullPath = pathTo_cryptonoteUtilsDir + filename + } + if (fullPath == null) { + throw "Unable to derive fullPath. Please pass locateFile() to bridge obj init." + } + // + return fullPath + } + return new Promise(function(resolve, reject) { + var Module_template = {} + if (options.asmjs != true || options.wasm == true) { // wasm + console.log("Using wasm: ", true) + // + Module_template["locateFile"] = locateFile + // + // NOTE: This requires src/module-post.js to be included as post-js in CMakeLists.txt under a wasm build + require(`./MyMoneroCoreCpp_WASM`)(Module_template).ready.then(function(thisModule) + { + const instance = new MyMoneroCoreBridgeClass(thisModule); + resolve(instance); + }).catch(function(e) { + console.error("Error loading WASM_MyMoneroCoreCpp:", e); + reject(e); + }); + } else { // this is synchronous so we can resolve immediately + console.log("Using wasm: ", false) + // + var scriptDirectory=""; // this was extracted from emscripten - it could get factored if anything else would ever need it + if (ENVIRONMENT_IS_NODE) { + scriptDirectory=__dirname+"/"; + } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + if (ENVIRONMENT_IS_WORKER) { + scriptDirectory = self.location.href + } else if (document.currentScript) { + scriptDirectory = document.currentScript.src + } + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if(_scriptDir){ + scriptDirectory = _scriptDir + } + if (scriptDirectory.indexOf("blob:") !== 0) { + scriptDirectory = scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1) + } else { + scriptDirectory = "" + } + } + var read_fn; + if (ENVIRONMENT_IS_NODE) { + read_fn = function(filepath) + { + return require("fs").readFileSync(require("path").normalize(filepath)).toString() + }; + } else if (ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER) { + read_fn = function(url) + { // it's an option to move this over to fetch, but, fetch requires a polyfill for these older browsers anyway - making fetch an automatic dep just for asmjs fallback - and the github/fetch polyfill does not appear to actually support mode (for 'same-origin' policy) anyway - probably not worth it yet + var xhr = new XMLHttpRequest() + xhr.open("GET", url, false) + xhr.send(null) + // + return xhr.responseText + }; + } else { + throw "Unsupported environment - please implement file reading for asmjs fallback case" + } + const filepath = locateFile("MyMoneroCoreCpp_ASMJS.asm.js", scriptDirectory) + const content = read_fn(filepath) + // TODO: verify content - for now, relying on same-origin and tls/ssl + var Module = {} + try { + eval(content) // I do not believe this is a safety concern, because content is server-controlled; https://humanwhocodes.com/blog/2013/06/25/eval-isnt-evil-just-misunderstood/ + } catch (e) { + reject(e) + return + } + setTimeout(function() + { // "delaying even 1ms is enough to allow compilation memory to be reclaimed" + Module_template['asm'] = Module['asm'] + Module = null + resolve(new MyMoneroCoreBridgeClass(require("./MyMoneroCoreCpp_ASMJS")(Module_template))) + }, 1) + } + }); +}; \ No newline at end of file