├── .gitignore ├── src ├── .npmignore ├── package.json ├── LICENSE ├── README.md ├── webworkers.android.js └── webworkers.ios.js └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.tgz 2 | *.tar 3 | .idea/ 4 | support/ 5 | -------------------------------------------------------------------------------- /src/.npmignore: -------------------------------------------------------------------------------- 1 | demo/ 2 | .idea/ 3 | support/ 4 | *.tar 5 | *.tgz 6 | .npmignore 7 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Archived 2 | See: https://fluentreports.com/blog/?p=1434 3 | 4 | # NativeScript-WebWorkers 5 | 6 | 7 | ## Developed by 8 | [](https://plugins.nativescript.rocks/mastertech-nstudio) 9 | 10 | 11 | 12 | ## Documentation 13 | The [documentation](src/README.md) for the plugin is located in the [src folder](src). 14 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nativescript-webworkers", 3 | "version": "2.0.0", 4 | "description": "A WebWorker (thread) NativeScript module for Android and iOS", 5 | "main": "webworkers.js", 6 | "nativescript": { 7 | "platforms": { 8 | "android": "1.0.0", 9 | "ios": "1.0.0" 10 | } 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/nathanaela/nativescript-webworkers.git" 15 | }, 16 | "keywords": [ 17 | "NativeScript", "webworkers", "worker", "thread", "threads", "iOS", "Android", "JavaScript", "WebView" 18 | ], 19 | "author": { 20 | "name": "Nathanael Anderson", 21 | "email": "nathan@master-technology.com" 22 | }, 23 | "license": { 24 | "type": "MIT", 25 | "url": "https://github.com/nathanaela/nativescript-webworkers/blob/master/LICENSE" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/nathanaela/nativescript-webworkers/issues" 29 | }, 30 | "homepage": "https://github.com/nathanaela/nativescript-webworkers", 31 | "readmeFilename": "README.md" 32 | } 33 | -------------------------------------------------------------------------------- /src/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2019, Nathanael Anderson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | [](https://www.npmjs.com/package/nativescript-webworkers) 2 | [](https://www.npmjs.com/package/nativescript-webworkers) 3 | [](https://www.npmjs.com/package/nativescript-webworkers) 4 | 5 | 6 | # nativescript-webworkers 7 | NativeScript WebWorkers (threads) for Android and iOS 8 | This is really only useful if you need to access a hidden WebView now; NativeScript has internal support for WebWorkers for a long time now. 9 | 10 | ## License 11 | 12 | This is released under the MIT License, meaning you are free to include this in any type of program -- However for entities that need a support contract, changes, enhancements and/or a commercial license please contact me at [http://nativescript.tools](http://nativescript.tools). 13 | 14 | I also do contract work; so if you have a module you want built for NativeScript (or any other software projects) feel free to contact me [nathan@master-technology.com](mailto://nathan@master-technology.com). 15 | 16 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=HN8DDMWVGBNQL&lc=US&item_name=Nathanael%20Anderson&item_number=nativescript%2dwebworkers&no_note=1&no_shipping=1¤cy_code=USD&bn=PP%2dDonationsBF%3ax%3aNonHosted) 17 | [](https://www.patreon.com/NathanaelA) 18 | 19 | ## Breaking Changes 20 | v2.00 No longer attempts to assign the global Worker object; NativeScript has Native WebWorker support for a long time now. 21 | 22 | 23 | ## Notes 24 | 25 | Please note The WebWorker environment is a LIMITED JavaScript shell. It does have AJAX/HTTP(s) ability; but it does NOT have any access to any of the NativeScript api. It also does not have any access to the Native iOS or Android api's. It is strictly a JS thread. In addition at this moment "ImportScripts" has not been implemented. It should be fairly easy to implement; and if anyone wants to do a pull request to implement this; I'd be happy to add it to the code that gets injected into the environment. 26 | 27 | If the device has more than one CPU; the Worker threads should not impact the main NativeScript thread. However, if the device only has one CPU; and depending on how busy you make the worker, it will impact the primary NativeScript thread. 28 | 29 | ## Installation 30 | 31 | Run `tns plugin add nativescript-webworkers` in your ROOT directory of your project. 32 | 33 | ## Usage 34 | 35 | To use the module you must first `require()` it: 36 | 37 | ```js 38 | const WebWorker = require( 'nativescript-webworkers' ); 39 | 40 | const myWorker = new WebWorker('~/web.worker.js'); // i.e. using the WebWorker variable returned by the require statement. 41 | ``` 42 | 43 | 44 | ## new WebWorker(data) 45 | ### data can be: 46 | - File path to a JS file (either relative `~/.../somescript.js` or full path `/..../somescript.js`) 47 | - Object with a `.HTML` - which allows you to pass in your own HTML file 48 | - please make sure the HTML is proper and not malformed. 49 | - Object with a `.script` - which allows you to pass in your own javascript code 50 | - Object can have its own custom `.baseURL`, otherwise defaults to the proper baseURL. 51 | 52 | ## NativeScript environment 53 | ### Events 54 | ####.onmessage(data) 55 | This will have the JSON object that was sent from the worker 56 | 57 | ####.onerror 58 | This will have any errors that occurred (this may be unreliable; as not all errors can be tracked properly) 59 | 60 | ####.onready 61 | This is fired when the webworker environment is ready to go. 62 | **This is NOT a standard webworker function** 63 | 64 | #### .executeJS 65 | This allows you to send some JS into the environment. 66 | **This is NOT a standard webworker function** 67 | 68 | ### Methods 69 | ####.postMessage(data) 70 | This posts the message into the webworker environment 71 | ####.terminate() 72 | This terminates the webworker environment; after this is ran; DO NOT attempt to continue doing anything on this webworker. 73 | 74 | 75 | ## WebWorker Environment 76 | ### Events 77 | 78 | ####onmessage(data) 79 | The function that gets any messages from the NativeScript environment 80 | 81 | ####onready() 82 | This function will get called if it exists once the webworker is able to communicate with the NativeScript host. 83 | **This is NOT a standard webworker function** 84 | 85 | ### Methods 86 | ####postMessage(data) 87 | The function you use to send message back to the NativeScript environment 88 | 89 | ####close() 90 | Terminates this environment 91 | 92 | 93 | ##Example: 94 | ### NativeScript code: 95 | ```js 96 | const WebWorker = require( 'nativescript-webworkers' ); 97 | var myWorker = new WebWorker('~/test.worker.js'); 98 | myWorker.onmessage = function(m) { console.log("Webworker said:", m); }; 99 | myWorker.postMessage("Hello"); 100 | ``` 101 | 102 | ### test.worker.js 103 | ```js 104 | onmessage = function(m) { 105 | console.log("NativeScript said" + m); 106 | }; 107 | onready = function() { 108 | postMessage("Hi"); 109 | }; 110 | ``` 111 | -------------------------------------------------------------------------------- /src/webworkers.android.js: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * (c) 2016-2019, Master Technology 3 | * Licensed under the MIT license or contact me for a Support or Commercial License 4 | * 5 | * I do contract work in most languages, so let me solve your problems! 6 | * 7 | * Any questions please feel free to email me or put a issue up on the github repo 8 | * Version 0.0.3 Nathan@master-technology.com 9 | *********************************************************************************/ 10 | "use strict"; 11 | /* global require */ 12 | 13 | const application = require('tns-core-modules/application'); 14 | const fs = require('tns-core-modules/file-system'); 15 | 16 | /* jshint node: true, browser: true, unused: false, undef: true */ 17 | /* global android, com, java, javax, unescape, global, NSObject, NSString, NSLocale */ 18 | 19 | //noinspection JSUnresolvedVariable,JSUnusedLocalSymbols 20 | const _WebChromeClient = android.webkit.WebChromeClient.extend({ 21 | wrapper: null, 22 | onJsConfirm: function(webView, url, message, result) { 23 | const self = this; 24 | setTimeout(function() { 25 | self.wrapper._clientMessage(message); 26 | },0); 27 | return false; 28 | } 29 | }); 30 | 31 | //noinspection JSUnresolvedVariable,JSUnusedLocalSymbols 32 | const _WebViewClient = android.webkit.WebViewClient.extend({ 33 | wrapper: null, 34 | onPageFinished: function(webView, url) { 35 | const self = this; 36 | setTimeout(function() { 37 | self.wrapper._finishedLoading(null); 38 | },0); 39 | }, 40 | onReceivedError: function(webView, request, error) { 41 | this.wrapper._finishedLoading(error); 42 | } 43 | }); 44 | 45 | 46 | // TODO: Determine if we need to pause these threads in the future using something like what is documented 47 | // here: http://stackoverflow.com/questions/2040963/webview-threads-never-stop-webviewcorethread-cookiesyncmanager-http0-3 48 | 49 | function WebWorker(js) { 50 | this._running = true; 51 | this._initialized = false; 52 | this._messages = []; 53 | this._executes = []; 54 | 55 | 56 | //noinspection JSUnresolvedVariable 57 | this.android = new android.webkit.WebView(application.android.context); 58 | 59 | // TODO: Setup DB Storage setDatabaseEnabled 60 | 61 | //noinspection JSUnresolvedFunction 62 | this.android.getSettings().setJavaScriptEnabled(true); 63 | //noinspection JSUnresolvedFunction 64 | this.android.getSettings().setDomStorageEnabled(true); 65 | //noinspection JSUnresolvedFunction 66 | this.android.getSettings().setDatabaseEnabled(true); 67 | //noinspection JSUnresolvedFunction 68 | this.android.getSettings().setUserAgentString("NativeScript-WebWorker"); 69 | 70 | const WCC = new _WebChromeClient(); 71 | WCC.wrapper = this; 72 | const WVC = new _WebViewClient(); 73 | WVC.wrapper = this; 74 | 75 | //noinspection JSUnresolvedFunction 76 | this.android.setWebChromeClient(WCC); 77 | //noinspection JSUnresolvedFunction 78 | this.android.setWebViewClient(WVC); 79 | 80 | if (js == null || js === '') { 81 | console.error("WebWorkers: can not find JavaScript file: ", js); 82 | //noinspection JSUnresolvedFunction 83 | this.android.loadUrl("about:blank"); 84 | return; 85 | } else if (js.HTML != null) { 86 | const baseDataUrl = "file:///" + fs.knownFolders.currentApp().path + "/"; 87 | this.android.loadDataWithBaseURL(js.baseURL || baseDataUrl, js.HTML, "text/html", "utf-8", null); 88 | } else if (js.script != null) { 89 | const baseDataUrl = "file:///" + fs.knownFolders.currentApp().path + "/"; 90 | this.android.loadDataWithBaseURL(js.baseURL || baseDataUrl, "", "text/html", "utf-8", null); 91 | } else { 92 | if (js[0] === '/' || (js[1] === '/' && (js[0] === '.' || js[0] === '~'))) { 93 | if (js[0] === '~' || js[0] === '.') { 94 | // TODO: Check to see if ./ is working properly 95 | js = fs.path.join(fs.knownFolders.currentApp().path, js.substr(2)); 96 | } 97 | if (fs.File.exists(js)) { 98 | const baseJSUrl = "file://" + js.substring(0, js.lastIndexOf('/') + 1); 99 | const fileName = js.substring(baseJSUrl.length - 7); 100 | 101 | //noinspection JSUnresolvedFunction 102 | this.android.loadDataWithBaseURL(baseJSUrl, "", "text/html", "utf-8", null); 103 | } else { 104 | console.error("WebWorkers: can not find JavaScript file: ", js); 105 | //noinspection JSUnresolvedFunction 106 | this.android.loadUrl("about:blank"); 107 | } 108 | } else { 109 | // Check for http(s):// 110 | if ((js[0] === 'h' || js[0] === 'H') && (js[6] === '/' && (js[5] === '/' || js[7] === '/'))) { 111 | //noinspection JSUnresolvedFunction 112 | this.android.loadUrl(js); 113 | } else { 114 | const baseDataUrl = "file:///" + fs.knownFolders.currentApp().path + "/"; 115 | //noinspection JSUnresolvedFunction 116 | this.android.loadDataWithBaseURL(baseDataUrl, "", "text/html", "utf-8", null); 117 | } 118 | } 119 | } 120 | //this._setupBridge(); 121 | } 122 | 123 | WebWorker.prototype.executeJS = function(script) { 124 | if (!this._running) { return false; } 125 | if (!this._initialized) { 126 | this._executes.push(script); 127 | return true; 128 | } 129 | this.android.evaluateJavascript(script, null); 130 | return true; 131 | }; 132 | 133 | WebWorker.prototype._setupBridge = function() { 134 | this._initialized = true; 135 | // TODO: Add "ImportScripts(script[, script...]) 136 | const script = "window.postMessage = function(data) { try { confirm(JSON.stringify(data)); } catch (e) { console.error(e); } }; " + 137 | "window._WW_receiveMessage = function(d) { setTimeout(function() { _WW_timedMessage(d); },0); }; " + 138 | "window._WW_timedMessage = function(d) { try { window.onmessage(d); } catch (e) { console.error(e); postMessage({_BRM: 'error', error: e}); } }; " + 139 | "window.close = function() { postMessage({_BRM: 'close'}); }; " + 140 | "if (typeof onready === 'function') { onready(); } "; 141 | 142 | //noinspection JSUnresolvedFunction 143 | this.android.evaluateJavascript(script, null); 144 | }; 145 | 146 | WebWorker.prototype._clientMessage = function(m) { 147 | let data; 148 | if (m[0] === '{') { 149 | try { 150 | data = JSON.parse(m); 151 | } 152 | catch (e) { 153 | data = m; 154 | } 155 | } else { 156 | data = m; 157 | } 158 | //noinspection JSUnresolvedVariable 159 | if (data._BRM) { 160 | //noinspection JSUnresolvedVariable 161 | if (data._BRM === "close") { 162 | this.terminate(); 163 | } else { 164 | //noinspection JSUnresolvedVariable 165 | if (data._BRM === "error") { 166 | this.onerror(data.error); 167 | } 168 | } 169 | return; 170 | } 171 | this.onmessage(data); 172 | }; 173 | 174 | WebWorker.prototype._finishedLoading = function(err) { 175 | this._setupBridge(); 176 | if (this._messages.length) { 177 | while (this._messages.length) { 178 | let m = this._messages.pop(); 179 | this.postMessage(m); 180 | } 181 | } 182 | if (this._executes.length) { 183 | while (this._executes.length) { 184 | const m = this._executes.pop(); 185 | this.executeJS(m); 186 | } 187 | } 188 | 189 | if (err) { 190 | onerror(err); 191 | } 192 | this.onready(); 193 | }; 194 | 195 | WebWorker.prototype.postMessage = function(data) { 196 | if (!this._running) { return; } 197 | if (!this._initialized) { 198 | this._messages.push(data); 199 | } else { 200 | // TODO: Send errors to actual onerror system? 201 | //noinspection JSUnresolvedFunction 202 | this.android.evaluateJavascript("try { _WW_receiveMessage(" + JSON.stringify(data) + "); } catch (e) { console.error(e); }", null); 203 | } 204 | }; 205 | 206 | WebWorker.prototype.terminate = function() { 207 | this._running = false; 208 | //noinspection JSUnresolvedFunction 209 | this.android.destroy(); 210 | this.android = null; 211 | }; 212 | 213 | WebWorker.prototype.onerror = function(e) { 214 | console.log("NativeScript-WebWorker error:", e); 215 | // Do Nothing. 216 | }; 217 | 218 | WebWorker.prototype.onmessage = function() { 219 | console.log("NativeScript-WebWorker message"); 220 | // Do Nothing. 221 | }; 222 | 223 | WebWorker.prototype.onready = function() { 224 | // Do nothing; this allows the end user to override this 225 | }; 226 | 227 | /* if (!global.Worker) { 228 | global.Worker = WebWorker; 229 | } */ 230 | 231 | // Make TS Compatible; 232 | WebWorker.WebWorker = WebWorker; 233 | 234 | module.exports = WebWorker; -------------------------------------------------------------------------------- /src/webworkers.ios.js: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * (c) 2016-2019, Master Technology 3 | * Licensed under the MIT license or contact me for a Support or Commercial License 4 | * 5 | * I do contract work in most languages, so let me solve your problems! 6 | * 7 | * Any questions please feel free to email me or put a issue up on the github repo 8 | * Version 0.0.2 Nathan@master-technology.com 9 | *********************************************************************************/ 10 | "use strict"; 11 | 12 | const fs = require('tns-core-modules/file-system'); 13 | 14 | /* jshint node: true, browser: true, unused: false, undef: true */ 15 | /* global android, com, java, javax, unescape, exports, global, NSObject, NSString, NSLocale, WKScriptMessageHandler, WKNavigationDelegate */ 16 | 17 | 18 | const _WKScriptMessageHandler = NSObject.extend({ 19 | _worker: null, 20 | userContentControllerDidReceiveScriptMessage: function(userContentController, message) { 21 | this._worker._clientMessage(message.body); 22 | }, 23 | webViewDidFinishNavigation: function(webKit, navigation) { 24 | this._worker._finishedLoading(); 25 | } 26 | },{name: 'WKScriptMHandler', protocols: [WKScriptMessageHandler,WKNavigationDelegate]}); 27 | 28 | function WebWorker(js) { 29 | this._running = true; 30 | this._initialized = false; 31 | this._messages = []; 32 | this._executes = []; 33 | this._config = new WKWebViewConfiguration(); 34 | this._controller = new WKUserContentController(); 35 | 36 | /* 37 | this._uiWindow = UIWindow.alloc().initWithFrame(CGRectMake(0,0,100,100)); 38 | this._uiWindow.userInteractionEnabled = false; 39 | var uiViewController = UIViewController.alloc().init(); 40 | var uiView = UIView.alloc().initWithFrame(CGRectMake(0,0,100,100)); 41 | uiView.backgroundColor = UIColor.alloc().initWithRedGreenBlueAlpha(0 / 255, 0 / 255, 255 / 255, 128 / 255); 42 | uiViewController.view.addSubview(uiView); 43 | this._uiWindow.rootViewController = uiViewController; 44 | this._uiWindow.windowLevel = UIWindowLevelStatusBar; 45 | this._uiWindow.makeKeyAndVisible(); 46 | this._uiWindow.hidden=false; 47 | */ 48 | 49 | const script1 = "if (typeof console === 'undefined') { console = {}; } console.log = function() { postMessage({'_BRM': 'log', 'data': Array.prototype.slice.call(arguments) }); }; " + 50 | "window.postMessage = function(data) { try { window.webkit.messageHandlers.channel.postMessage(JSON.stringify(data)); } catch (e) { console.error(e); } }; " + 51 | "window._WW_receiveMessage = function(d) { setTimeout(function() { _WW_timedMessage(d); },0); }; " + 52 | "window._WW_timedMessage = function(d) { try { window.onmessage(d); } catch (e) { console.log(e); postMessage({_BRM: 'error', error: e}); } }; " + 53 | "window.close = function() { postMessage({_BRM: 'close'}); }; "; 54 | const script2 = "if (typeof onready === 'function') { onready(); } "; 55 | 56 | const s1 = WKUserScript.alloc().initWithSourceInjectionTimeForMainFrameOnly(script1, WKUserScriptInjectionTimeAtDocumentStart, false); 57 | const s2 = WKUserScript.alloc().initWithSourceInjectionTimeForMainFrameOnly(script2, WKUserScriptInjectionTimeAtDocumentEnd, false); 58 | this._scriptHandler = _WKScriptMessageHandler.alloc().init(); 59 | this._scriptHandler._worker = this; 60 | 61 | this._controller.addScriptMessageHandlerName(this._scriptHandler, "channel"); 62 | 63 | this._controller.addUserScript(s1); 64 | this._controller.addUserScript(s2); 65 | 66 | this._config.userContentController = this._controller; 67 | 68 | this.ios = WKWebView.alloc().initWithFrameConfiguration(CGRectMake(0,0,50,50), this._config); 69 | this.ios.customUserAgent = "nativescript-websockets"; 70 | this.ios.navigationDelegate = this._scriptHandler; 71 | 72 | // var d = UIApplication.sharedApplication().keyWindow; 73 | // d.addSubview(this.ios); 74 | //uiView.addSubview(this.ios); 75 | 76 | 77 | if (js == null || js === '') { 78 | console.error("WebWorkers: can not find JavaScript file: ", js); 79 | //noinspection JSUnresolvedFunction 80 | this.ios.loadRequest(NSURLRequest.requestWithURL(NSURL.URLWithString("about:blank"))); 81 | return; 82 | } else if (js.script != null) { 83 | const baseDataUrl = NSURL.URLWithString("file:///" + fs.knownFolders.currentApp().path + "/"); 84 | //noinspection JSUnresolvedFunction 85 | this.ios.loadHTMLStringBaseURL("
", baseDataUrl); 86 | } else if (js.HTML != null) { 87 | const baseDataUrl = NSURL.URLWithString("file:///" + fs.knownFolders.currentApp().path + "/"); 88 | //noinspection JSUnresolvedFunction 89 | this.ios.loadHTMLStringBaseURL(js.HTML, js.baseURL || baseDataUrl); 90 | 91 | } else { 92 | if (js[0] === '/' || (js[1] === '/' && (js[0] === '.' || js[0] === '~'))) { 93 | if (js[0] === '~' || js[0] === '.') { 94 | // TODO: Check to see if ./ is working properly 95 | js = fs.path.join(fs.knownFolders.currentApp().path, js.substr(2)); 96 | } 97 | if (fs.File.exists(js)) { 98 | const baseURL = "file://" + js.substring(0, js.lastIndexOf('/') + 1); 99 | const baseJSUrl = NSURL.URLWithString(baseURL); 100 | const fileName = js.substring(baseURL.length - 7); 101 | 102 | //noinspection JSUnresolvedFunction 103 | this.ios.loadHTMLStringBaseURL("", baseJSUrl); 104 | } else { 105 | console.error("WebWorkers: can not find JavaScript file: ", js); 106 | //noinspection JSUnresolvedFunction 107 | this.ios.loadRequest(NSURLRequest.requestWithURL(NSURL.URLWithString("about:blank"))); 108 | } 109 | } else { 110 | // Check for http(s):// 111 | if ((js[0] === 'h' || js[0] === 'H') && (js[6] === '/' && (js[5] === '/' || js[7] === '/'))) { 112 | //noinspection JSUnresolvedFunction 113 | this.ios.loadRequest(NSURLRequest.requestWithURL(NSURL.URLWithString(js))); 114 | } else { 115 | const baseDataUrl = NSURL.URLWithString("file:///" + fs.knownFolders.currentApp().path + "/"); 116 | //noinspection JSUnresolvedFunction 117 | this.ios.loadHTMLStringBaseURL("", baseDataUrl); 118 | } 119 | } 120 | } 121 | } 122 | 123 | WebWorker.prototype._clientMessage = function(m) { 124 | let data; 125 | if (m[0] === '{') { 126 | try { 127 | data = JSON.parse(m); 128 | } 129 | catch (e) { 130 | data = m; 131 | } 132 | } else { 133 | data = m; 134 | } 135 | //noinspection JSUnresolvedVariable 136 | if (data._BRM) { 137 | switch (data._BRM) { 138 | case 'close': 139 | this.terminate(); break; 140 | case 'error': 141 | this.onerror(data.error); break; 142 | case 'log': 143 | console.log.apply(console, data.data); break; 144 | default: 145 | console.log("Unknown _BRM", data._BRM) 146 | } 147 | 148 | return; 149 | } 150 | this.onmessage(data); 151 | }; 152 | 153 | WebWorker.prototype._finishedLoading = function() { 154 | this._initialized = true; 155 | if (this._messages.length) { 156 | while (this._messages.length) { 157 | const m = this._messages.pop(); 158 | this.postMessage(m); 159 | } 160 | } 161 | if (this._executes.length) { 162 | while (this._executes.length) { 163 | const m = this._executes.pop(); 164 | this.executeJS(m); 165 | } 166 | } 167 | this.onready(); 168 | }; 169 | 170 | WebWorker.prototype.executeJS = function(script) { 171 | if (!this._running) { return false; } 172 | if (!this._initialized) { 173 | this._executes.push(script); 174 | return true; 175 | } 176 | const self = this; 177 | this.ios.evaluateJavaScriptCompletionHandler(script, function(c,err) { if (err) self.onerror(err); }); 178 | return true; 179 | }; 180 | 181 | WebWorker.prototype.postMessage = function(data) { 182 | if (!this._running) { return; } 183 | if (!this._initialized) { 184 | this._messages.push(data); 185 | } else { 186 | let self = this; 187 | this.ios.evaluateJavaScriptCompletionHandler("_WW_receiveMessage(" + JSON.stringify(data) + "); ", function(c,err) { if (err) self.onerror(err); }); 188 | } 189 | }; 190 | 191 | WebWorker.prototype.terminate = function() { 192 | this._running = false; 193 | //this.ios.navigationDelegate = null; 194 | 195 | //noinspection JSUnresolvedFunction 196 | this.ios = null; 197 | this._config = null; 198 | this._controller = null; 199 | }; 200 | 201 | WebWorker.prototype.onerror = function(e) { 202 | console.log("NativeScript-WebWorker error:", e); 203 | // Do Nothing. 204 | }; 205 | 206 | WebWorker.prototype.onmessage = function() { 207 | console.log("NativeScript-WebWorker message"); 208 | // Do Nothing. 209 | }; 210 | 211 | WebWorker.prototype.onready = function() { 212 | // Do nothing; this allows the end user to override this 213 | }; 214 | 215 | // Make TS Compatible; 216 | WebWorker.WebWorker = WebWorker; 217 | 218 | module.exports = WebWorker; --------------------------------------------------------------------------------