From 478a089e521de81ca47fc54518bc6a241823d9ae Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sat, 27 May 2017 22:55:52 +0200 Subject: fix module loading for node under fake web workers --- node_modules/tiny-worker/.npmignore | 9 --- node_modules/tiny-worker/LICENSE | 28 ------- node_modules/tiny-worker/README.md | 115 --------------------------- node_modules/tiny-worker/lib/index.js | 137 --------------------------------- node_modules/tiny-worker/lib/noop.js | 5 -- node_modules/tiny-worker/lib/worker.js | 83 -------------------- node_modules/tiny-worker/package.json | 35 --------- package.json | 1 - src/crypto/cryptoApi.ts | 27 +++++-- src/crypto/emscLoader.js | 24 ++++-- src/types-test.ts | 3 + src/types.ts | 4 +- tsconfig.json | 4 + 13 files changed, 45 insertions(+), 430 deletions(-) delete mode 100644 node_modules/tiny-worker/.npmignore delete mode 100644 node_modules/tiny-worker/LICENSE delete mode 100644 node_modules/tiny-worker/README.md delete mode 100644 node_modules/tiny-worker/lib/index.js delete mode 100644 node_modules/tiny-worker/lib/noop.js delete mode 100644 node_modules/tiny-worker/lib/worker.js delete mode 100644 node_modules/tiny-worker/package.json diff --git a/node_modules/tiny-worker/.npmignore b/node_modules/tiny-worker/.npmignore deleted file mode 100644 index b422e464d..000000000 --- a/node_modules/tiny-worker/.npmignore +++ /dev/null @@ -1,9 +0,0 @@ -/.idea/ -/node_modules/ -/src/ -/test/ -.eslintrc -.git -.gitignore -.travis.yml -Gruntfile.js diff --git a/node_modules/tiny-worker/LICENSE b/node_modules/tiny-worker/LICENSE deleted file mode 100644 index f45e28374..000000000 --- a/node_modules/tiny-worker/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2017, Jason Mulligan -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of tiny-worker nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/node_modules/tiny-worker/README.md b/node_modules/tiny-worker/README.md deleted file mode 100644 index b73787334..000000000 --- a/node_modules/tiny-worker/README.md +++ /dev/null @@ -1,115 +0,0 @@ -# tiny-worker -Tiny WebWorker for Server - -`require()` is available for flexible inline Worker scripts. Optional parameters `args` Array & `options` Object; see `child_process.fork()` documentation. - -[![build status](https://secure.travis-ci.org/avoidwork/tiny-worker.svg)](http://travis-ci.org/avoidwork/tiny-worker) - -## Example -#### Creating a Worker from a file -The worker script: -```javascript -onmessage = function (ev) { - postMessage(ev.data); -}; -``` - -The core script: -```javascript -var Worker = require("tiny-worker"); -var worker = new Worker("repeat.js"); - -worker.onmessage = function (ev) { - console.log(ev.data); - worker.terminate(); -}; - -worker.postMessage("Hello World!"); -``` - -#### Creating a Worker from a Function -```javascript -var Worker = require("tiny-worker"); -var worker = new Worker(function () { - self.onmessage = function (ev) { - postMessage(ev.data); - }; -}); - -worker.onmessage = function (ev) { - console.log(ev.data); - worker.terminate(); -}; - -worker.postMessage("Hello World!"); -``` - -# Debugging -To be able to debug a child process, it must have a differnt debug port than the parent. -Tiny worker does this by adding a random port within a range to the parents debug port. -The default Range is `[1, 300]`, it can be changed with the `setRange(min, max)` method. -To disable any automatic port redirection set `options.noDebugRedirection = true`. - -### automatic redirection -```javascript -//parent is started with '--debug=1234' -var Worker = require("tiny-worker"); -Worker.setRange(2, 20); - -var worker = new Worker(function () { - postMessage(process.debugPort); -}); - -worker.onmessage = function (ev) { - console.log(ev.data); //prints any number between 1236 and 1254 - worker.terminate(); -} -``` - -### manual redirection -```javascript -//parent is started with '--debug=1234' -var Worker = require("tiny-worker"); - -var worker = new Worker(function () { - postMessage(process.debugPort); -}, [], {noDebugRedirection: true, execArgv: ["--debug=1235"]}); - -worker.onmessage = function (ev) { - console.log(ev.data); //prints 1235 - worker.terminate(); -} -``` - -## Properties -#### onmessage -Message handler, accepts an `Event` - -#### onerror -Error handler, accepts an `Event` - -## API -#### addEventListener(event, fn) -Adds an event listener - -#### postMessage() -Broadcasts a message to the `Worker` - -#### terminate() -Terminates the `Worker` - -#### static setRange(min, max) -Sets range for debug ports, only affects current process. -Returns true if successful. - -## FAQ -1. I have an orphaned child process that lives on past the parent process' lifespan - * Most likely a `SIGTERM` or `SIGINT` is not reaching the child process -2. How do I insure all process are terminated? - * In your core script register a listener for `SIGTERM` or `SIGINT` via `process.on()` which terminates (all) worker process(es) and then gracefully shutdowns via `process.exit(0);` -3. Why `SIGTERM` or `SIGINT`? - * Unix/BSD will work with `SIGTERM`, but if you also need to support Windows use `SIGINT` - -## License -Copyright (c) 2017 Jason Mulligan -Licensed under the BSD-3 license diff --git a/node_modules/tiny-worker/lib/index.js b/node_modules/tiny-worker/lib/index.js deleted file mode 100644 index 1cce88cfe..000000000 --- a/node_modules/tiny-worker/lib/index.js +++ /dev/null @@ -1,137 +0,0 @@ -"use strict"; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var path = require("path"), - fork = require("child_process").fork, - worker = path.join(__dirname, "worker.js"), - events = /^(error|message)$/, - defaultPorts = { inspect: 9229, debug: 5858 }; -var range = { min: 1, max: 300 }; - -var Worker = function () { - function Worker(arg) { - var _this = this; - - var args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; - var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { cwd: process.cwd() }; - - _classCallCheck(this, Worker); - - var isfn = typeof arg === "function", - input = isfn ? arg.toString() : arg; - - if (!options.cwd) { - options.cwd = process.cwd(); - } - - //get all debug related parameters - var debugVars = process.execArgv.filter(function (execArg) { - return (/(debug|inspect)/.test(execArg) - ); - }); - if (debugVars.length > 0 && !options.noDebugRedirection) { - if (!options.execArgv) { - //if no execArgs are given copy all arguments - debugVars = Array.from(process.execArgv); - options.execArgv = []; - } - - var inspectIndex = debugVars.findIndex(function (debugArg) { - //get index of inspect parameter - return (/^--inspect(-brk)?(=\d+)?$/.test(debugArg) - ); - }); - - var debugIndex = debugVars.findIndex(function (debugArg) { - //get index of debug parameter - return (/^--debug(-brk)?(=\d+)?$/.test(debugArg) - ); - }); - - var portIndex = inspectIndex >= 0 ? inspectIndex : debugIndex; //get index of port, inspect has higher priority - - if (portIndex >= 0) { - var match = /^--(debug|inspect)(?:-brk)?(?:=(\d+))?$/.exec(debugVars[portIndex]); //get port - var port = defaultPorts[match[1]]; - if (match[2]) { - port = parseInt(match[2]); - } - debugVars[portIndex] = "--" + match[1] + "=" + (port + range.min + Math.floor(Math.random() * (range.max - range.min))); //new parameter - - if (debugIndex >= 0 && debugIndex !== portIndex) { - //remove "-brk" from debug if there - match = /^(--debug)(?:-brk)?(.*)/.exec(debugVars[debugIndex]); - debugVars[debugIndex] = match[1] + (match[2] ? match[2] : ""); - } - } - options.execArgv = options.execArgv.concat(debugVars); - } - - delete options.noDebugRedirection; - - this.child = fork(worker, args, options); - this.onerror = undefined; - this.onmessage = undefined; - - this.child.on("error", function (e) { - if (_this.onerror) { - _this.onerror.call(_this, e); - } - }); - - this.child.on("message", function (msg) { - var message = JSON.parse(msg); - var error = void 0; - - if (!message.error && _this.onmessage) { - _this.onmessage.call(_this, message); - } - - if (message.error && _this.onerror) { - error = new Error(message.error); - error.stack = message.stack; - - _this.onerror.call(_this, error); - } - }); - - this.child.send({ input: input, isfn: isfn, cwd: options.cwd }); - } - - _createClass(Worker, [{ - key: "addEventListener", - value: function addEventListener(event, fn) { - if (events.test(event)) { - this["on" + event] = fn; - } - } - }, { - key: "postMessage", - value: function postMessage(msg) { - this.child.send(JSON.stringify({ data: msg }, null, 0)); - } - }, { - key: "terminate", - value: function terminate() { - this.child.kill("SIGINT"); - } - }], [{ - key: "setRange", - value: function setRange(min, max) { - if (min >= max) { - return false; - } - range.min = min; - range.max = max; - - return true; - } - }]); - - return Worker; -}(); - -module.exports = Worker; diff --git a/node_modules/tiny-worker/lib/noop.js b/node_modules/tiny-worker/lib/noop.js deleted file mode 100644 index 312fce83b..000000000 --- a/node_modules/tiny-worker/lib/noop.js +++ /dev/null @@ -1,5 +0,0 @@ -"use strict"; - -module.exports = function () { - return void 0; -}; diff --git a/node_modules/tiny-worker/lib/worker.js b/node_modules/tiny-worker/lib/worker.js deleted file mode 100644 index c8e5d6885..000000000 --- a/node_modules/tiny-worker/lib/worker.js +++ /dev/null @@ -1,83 +0,0 @@ -"use strict"; - -var fs = require("fs"), - path = require("path"), - vm = require("vm"), - noop = require(path.join(__dirname, "noop.js")), - events = /^(error|message)$/; - -function trim(arg) { - return arg.replace(/^(\s+|\t+|\n+)|(\s+|\t+|\n+)$/g, ""); -} - -function explode(arg) { - return trim(arg).split(new RegExp("\\s*,\\s*")); -} - -function toFunction(arg) { - var args = trim(arg.replace(/^.*\(/, "").replace(/[\t|\r|\n|\"|\']+/g, "").replace(/\).*/, "")), - body = trim(arg.replace(/^.*\{/, "").replace(/\}$/, "")); - - return Function.apply(Function, explode(args).concat([body])); -} - -// Bootstraps the Worker -process.once("message", function (obj) { - var exp = obj.isfn ? toFunction(obj.input) : fs.readFileSync(obj.input, "utf8"); - - global.self = { - close: function close() { - process.exit(0); - }, - postMessage: function postMessage(msg) { - process.send(JSON.stringify({ data: msg }, null, 0)); - }, - onmessage: void 0, - onerror: function onerror(err) { - process.send(JSON.stringify({ error: err.message, stack: err.stack }, null, 0)); - }, - addEventListener: function addEventListener(event, fn) { - if (events.test(event)) { - global["on" + event] = global.self["on" + event] = fn; - } - } - }; - - global.__dirname = obj.cwd; - global.__filename = __filename; - global.require = require; - - global.importScripts = function () { - for (var _len = arguments.length, files = Array(_len), _key = 0; _key < _len; _key++) { - files[_key] = arguments[_key]; - } - - if (files.length > 0) { - vm.createScript(files.map(function (file) { - return fs.readFileSync(file, "utf8"); - }).join("\n")).runInThisContext(); - } - }; - - Object.keys(global.self).forEach(function (key) { - global[key] = global.self[key]; - }); - - process.on("message", function (msg) { - try { - (global.onmessage || global.self.onmessage || noop)(JSON.parse(msg)); - } catch (err) { - (global.onerror || global.self.onerror || noop)(err); - } - }); - - process.on("error", function (err) { - (global.onerror || global.self.onerror || noop)(err); - }); - - if (typeof exp === "function") { - exp(); - } else { - vm.createScript(exp).runInThisContext(); - } -}); diff --git a/node_modules/tiny-worker/package.json b/node_modules/tiny-worker/package.json deleted file mode 100644 index 1176ef946..000000000 --- a/node_modules/tiny-worker/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "tiny-worker", - "version": "2.1.1", - "description": "Tiny WebWorker for Server", - "main": "lib/index.js", - "scripts": { - "test": "grunt test" - }, - "repository": { - "type": "git", - "url": "https://github.com/avoidwork/tiny-worker.git" - }, - "keywords": [ - "web", - "worker", - "ps", - "webworker" - ], - "author": "Jason Mulligan ", - "license": "BSD-3-Clause", - "bugs": { - "url": "https://github.com/avoidwork/tiny-worker/issues" - }, - "homepage": "https://github.com/avoidwork/tiny-worker", - "devDependencies": { - "babel-preset-es2015": "~6.22.0", - "grunt": "~1.0.1", - "grunt-babel": "~6.0.0", - "grunt-cli": "~1.2.0", - "grunt-contrib-nodeunit": "~1.0.0", - "grunt-contrib-watch": "~1.0.0", - "grunt-eslint": "~19.0.0" - }, - "dependencies": {} -} diff --git a/package.json b/package.json index cd6033dae..fc7dfb13a 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "react": "^15.5.4", "react-dom": "^15.5.4", "through2": "^2.0.1", - "tiny-worker": "^2.1.1", "ts-loader": "^2.0.3", "typedoc": "^0.7.1", "typescript": "next", diff --git a/src/crypto/cryptoApi.ts b/src/crypto/cryptoApi.ts index a386eab42..b291cd17d 100644 --- a/src/crypto/cryptoApi.ts +++ b/src/crypto/cryptoApi.ts @@ -38,6 +38,9 @@ import { OfferRecord, CoinWithDenom, } from "../wallet"; +import * as timer from "../timer"; + +import { startWorker } from "./startWorker"; /** @@ -57,7 +60,7 @@ interface WorkerState { /** * Timer to terminate the worker if it's not busy enough. */ - terminationTimerHandle: number|null; + terminationTimerHandle: timer.TimerHandle|null; } interface WorkItem { @@ -73,6 +76,8 @@ interface WorkItem { } + + /** * Number of different priorities. Each priority p * must be 0 <= p < NUM_PRIO. @@ -98,7 +103,7 @@ export class CryptoApi { ws.currentWorkItem = work; this.numBusy++; if (!ws.w) { - let w = new Worker("/dist/cryptoWorker-bundle.js"); + let w = startWorker(); w.onmessage = (m: MessageEvent) => this.handleWorkerMessage(ws, m); w.onerror = (e: ErrorEvent) => this.handleWorkerError(ws, e); ws.w = w; @@ -114,7 +119,8 @@ export class CryptoApi { resetWorkerTimeout(ws: WorkerState) { if (ws.terminationTimerHandle != null) { - clearTimeout(ws.terminationTimerHandle); + ws.terminationTimerHandle.clear(); + ws.terminationTimerHandle = null; } let destroy = () => { // terminate worker if it's idle @@ -123,7 +129,7 @@ export class CryptoApi { ws.w = null; } }; - ws.terminationTimerHandle = window.setTimeout(destroy, 20 * 1000); + ws.terminationTimerHandle = timer.after(20 * 1000, destroy); } handleWorkerError(ws: WorkerState, e: ErrorEvent) { @@ -182,7 +188,14 @@ export class CryptoApi { } constructor() { - this.workers = new Array((navigator as any)["hardwareConcurrency"] || 2); + let concurrency = 2; + try { + // only works in the browser + concurrency = (navigator as any)["hardwareConcurrency"]; + } catch (e) { + // ignore + } + this.workers = new Array(concurrency); for (let i = 0; i < this.workers.length; i++) { this.workers[i] = { @@ -199,7 +212,7 @@ export class CryptoApi { private doRpc(operation: string, priority: number, ...args: any[]): Promise { - let start = performance.now(); + let start = timer.performanceNow(); let p = new Promise((resolve, reject) => { let rpcId = this.nextRpcId++; @@ -228,7 +241,7 @@ export class CryptoApi { }); return p.then((r: T) => { - console.log(`rpc ${operation} took ${performance.now() - start}ms`); + console.log(`rpc ${operation} took ${timer.performanceNow() - start}ms`); return r; }); } diff --git a/src/crypto/emscLoader.js b/src/crypto/emscLoader.js index eebe20c02..190f007f1 100644 --- a/src/crypto/emscLoader.js +++ b/src/crypto/emscLoader.js @@ -31,6 +31,22 @@ * be globally available. Inside node, require is used. */ export function getLib() { + if (typeof require !== "undefined") { + // Make sure that TypeScript doesn't try + // to check the taler-emscripten-lib. + const indirectRequire = require; + const g = global as any; + // unavoidable hack, so that emscripten detects + // the environment as node even though importScripts + // is present. + const savedImportScripts = g.importScripts; + delete g.importScripts; + // Assume that the code is run from the build/ directory. + const lib = indirectRequire("../../../emscripten/taler-emscripten-lib.js"); + g.importScripts = savedImportScripts; + return lib; + } + if (typeof importScripts !== "undefined") { importScripts('/src/emscripten/taler-emscripten-lib.js') if (TalerEmscriptenLib) { @@ -39,14 +55,6 @@ export function getLib() { return TalerEmscriptenLib } - if (typeof require !== "undefined") { - // Make sure that TypeScript doesn't try - // to check the taler-emscripten-lib. - const fn = require; - // Assume that the code is run from the build/ directory. - return fn("../../../emscripten/taler-emscripten-lib.js"); - } - if (typeof window !== "undefined") { if (window.TalerEmscriptenLib) { return TalerEmscriptenLib; diff --git a/src/types-test.ts b/src/types-test.ts index bc053b40b..780d49e45 100644 --- a/src/types-test.ts +++ b/src/types-test.ts @@ -53,6 +53,9 @@ test("contract validation", t => { timestamp: "Date(12345)", transaction_id: 1234, fulfillment_url: "foo", + wire_method: "test", + order_id: "test_order", + pay_url: "https://example.com/pay", }; types.Contract.checked(c); diff --git a/src/types.ts b/src/types.ts index 26280874c..240275975 100644 --- a/src/types.ts +++ b/src/types.ts @@ -587,10 +587,10 @@ export class Contract { @Checkable.String fulfillment_url: string; - @Checkable.Number + @Checkable.Optional(Checkable.Number) wire_fee_amortization?: number; - @Checkable.Value(AmountJson) + @Checkable.Optional(Checkable.Value(AmountJson)) max_wire_fee?: AmountJson; @Checkable.Any diff --git a/tsconfig.json b/tsconfig.json index 0c684214e..412616d69 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -34,6 +34,9 @@ "src/crypto/emscInterface.ts", "src/crypto/emscLoader.d.ts", "src/crypto/emscLoader.js", + "src/crypto/nodeWorker.ts", + "src/crypto/nodeWorkerEntry.ts", + "src/crypto/startWorker.js", "src/helpers-test.ts", "src/helpers.ts", "src/http.ts", @@ -52,6 +55,7 @@ "src/pages/tree.tsx", "src/query.ts", "src/renderHtml.tsx", + "src/timer.ts", "src/types-test.ts", "src/types.ts", "src/wallet-test.ts", -- cgit v1.2.3