Commit 99f30f21e8fe9b8c89b244e7a67a849481583e11

Authored by Rooftrellen
1 parent b0c846da

add webworkers support for javapoly

Gruntfile.js
... ... @@ -3,8 +3,10 @@ module.exports = function(grunt) {
3 3 pkg: grunt.file.readJSON('package.json'),
4 4 browserify: {
5 5 build: {
6   - src: ['src/**/main.js'],
7   - dest: 'build/javapoly.js',
  6 + files:{
  7 + 'build/javapoly.js':['src/**/main.js'],
  8 + 'build/javapoly_worker.js':['src/**/webworkers/JavaPolyWorker.js']
  9 + },
8 10 options: {
9 11 transform: [
10 12 ["babelify", { "presets": ["es2015"] }]
... ... @@ -12,8 +14,10 @@ module.exports = function(grunt) {
12 14 }
13 15 },
14 16 buildForTest:{
15   - src: ['src/**/main.test.js'],
16   - dest: 'build/javapoly.js',
  17 + files:{
  18 + 'build/javapoly.js':['src/**/main.test.js'],
  19 + 'build/javapoly_worker.js':['src/**/webworkers/JavaPolyWorker.js']
  20 + },
17 21 options: {
18 22 transform: [
19 23 ["babelify", { "presets": ["es2015"] }]
... ... @@ -24,7 +28,7 @@ module.exports = function(grunt) {
24 28 watch: {
25 29 scripts: {
26 30 files: 'src/**/*.js',
27   - tasks: ['build', 'copy:distToTests'],
  31 + tasks: ['build:test'],
28 32 options: {
29 33 interrupt: true,
30 34 },
... ...
README.md
... ... @@ -72,3 +72,16 @@ $ npm install -g mocha
72 72 ```
73 73  
74 74 And type `mocha` in projects directory.
  75 +
  76 +### Using JavaPoly Core(include JVM) in WebWorker
  77 +
  78 +we could use webworkers if possible(the browser support) , to avoid blocking the main thread.
  79 +
  80 +simply add a worker options in javapoly.
  81 +The options value is the url of the javapoly_worker.js.(default value is null for not using webworkers)
  82 +
  83 +eg.
  84 +
  85 +```js
  86 +new JavaPoly(worker : 'build/javapoly_worker.js');
  87 +```
75 88 \ No newline at end of file
... ...
src/JavaClassWrapper.js
... ... @@ -86,7 +86,17 @@ class JavaClassWrapper {
86 86 window.javaPolyMessageTypes[id] = messageType;
87 87 window.javaPolyData[id] = data;
88 88 window.javaPolyCallbacks[id] = callback;
89   - window.postMessage({ javapoly:{ messageId:""+id } }, "*")
  89 +
  90 + if (javapoly.worker && global.Worker)
  91 + JavaClassWrapper.dispatchOnJVMWorker(""+id, messageType, data, callback);
  92 + else
  93 + window.postMessage({ javapoly:{ messageId:""+id } }, "*");
  94 + }
  95 +
  96 + static dispatchOnJVMWorker(id, messageType, data) {
  97 + // NOTES, here we need to pass args and return value via Worker postMessage.
  98 + // The worker and browser don't share data, we need to pass data via message body
  99 + javapoly.worker.postMessage({javapoly:{messageId:id, messageType:messageType, data:data}});
90 100 }
91 101  
92 102 runMethodWithJavaDispatching(methodName, argumentsList) {
... ...
src/JavaPoly.js
1 1 import * as _ from 'underscore';
2   -import JavaClassFile from './JavaClassFile';
3   -import JavaArchiveFile from './JavaArchiveFile';
4   -import JavaSourceFile from './JavaSourceFile';
5 2 import JavaClassWrapper from './JavaClassWrapper';
6 3 import QueueExecutor from './QueueExecutor';
7 4 import ProxyWrapper from './ProxyWrapper';
8   -
9   -const JAVA_MIME = [
10   - { // For compiled Java-class
11   - type: 'class',
12   - mime: ['application/java-vm'],
13   - srcRequired: true
14   - },
15   - { // For Java source files
16   - type: 'java',
17   - mime: ['text/x-java-source'],
18   - srcRequired: false
19   - },
20   - { // For JAR-files
21   - type: 'jar',
22   - mime: ['application/java-archive'],
23   - srcRequired: true
24   - }
25   -];
  5 +import JavaPolyLoader from './JavaPolyLoader.js'
26 6  
27 7 const DEFAULT_JAVAPOLY_OPTIONS = {
28 8 /**
... ... @@ -41,15 +21,24 @@ const DEFAULT_JAVAPOLY_OPTIONS = {
41 21 * 1.'doppio/', download from user owner domain(${your.domain}/doppio), eg. localhost for locally test
42 22 * 2. or a public url, eg. http://www.javapoly.com/doppio/
43 23 */
44   - doppioLibUrl: 'doppio/'
  24 + doppioLibUrl: '/doppio/',
45 25  
46 26 /**
47 27 * Optional: javaPolyBaseUrl
48 28 * When defined, this is used as the base URL for loading JavaPoly data such as system classes and native functions.
49 29 * If empty, JavaPoly will try to automatically figure it out during initialisation.
50 30 */
  31 +
  32 + /**
  33 + * Javapoly worker path. null or a path, eg. build/javapoly_worker.js
  34 + *
  35 + * @type {String} when defined not null, we will try to use the webworkers path to run the core javapoly and jvm. if web
  36 + * worker is not supported by browser, we will just load javapoly and jvm in browser main Thread.
  37 + */
  38 + worker : null // 'build/javapoly_worker.js'
51 39 }
52 40  
  41 +
53 42 /**
54 43 * Main JavaPoly class that do all underliying job for initialization
55 44 * Simple usage:
... ... @@ -114,6 +103,12 @@ class JavaPoly {
114 103 */
115 104 this.classpath = [this.options.storageDir];
116 105  
  106 + /**
  107 + * Web Worker instance which run the javapoly core and JVM
  108 + * @Type {global.Worker}
  109 + */
  110 + this.worker = null;
  111 +
117 112 if (!this.options.javaPolyBaseUrl) {
118 113 this.options.javaPolyBaseUrl = this.getScriptBase();
119 114 }
... ... @@ -136,45 +131,61 @@ class JavaPoly {
136 131 }
137 132  
138 133 beginLoading(resolveJVMReady) {
139   - global.document.addEventListener('DOMContentLoaded', e => {
140   - // Ensure we have loaded the browserfs.js file before handling Java/class file
141   - this.loadExternalJs(this.options.doppioLibUrl+'vendor/browserfs/dist/browserfs.min.js').then(()=> {
142   - this.initBrowserFS();
143   - // Load doppio.js file
144   - this.loadingHub.push(this.loadExternalJs(this.options.doppioLibUrl+'doppio.js'));
  134 + global.document.addEventListener('DOMContentLoaded', e => {
  135 +
  136 + let javaMimeScripts = [];
  137 + _.each(global.document.scripts, script => {
  138 + javaMimeScripts.push({type:script.type, src:script.src});
  139 + });
145 140  
146   - this.loadScripts();
  141 + this.initDispatcher();
147 142  
148   - this.initJVM().then(resolveJVMReady);
  143 + // start JVM and JavaPoly Core in Web Worker
  144 + // only if worker option enable and browser support WebWorkers
  145 + if (this.options.worker && global.Worker){
  146 + return this.startJavaPolyWebWorker(javaMimeScripts,resolveJVMReady);
  147 + }
  148 +
  149 + // Otherwise Start in Browser Main Thread,
  150 + // Ensure we have loaded the browserfs.js file before handling Java/class file
  151 + this.loadExternalJs(this.options.doppioLibUrl+'vendor/browserfs/dist/browserfs.min.js').then(()=> {
  152 +
  153 + new JavaPolyLoader(this, javaMimeScripts,
  154 + () => {this.loadingHub.push(this.loadExternalJs(this.options.doppioLibUrl+'doppio.js'));},
  155 + resolveJVMReady);
  156 +
149 157 });
150 158 }, false);
151 159 }
152 160  
153   - loadScripts() {
154   - // Load java mime files
155   - _.each(global.document.scripts, script => {
156   - let scriptTypes = JAVA_MIME.filter(item => item.mime.some(m => m === script.type));
157   - // Create only when scriptTypes is only 1
158   - if (scriptTypes.length === 1) {
159   - let scriptType = scriptTypes[0].type;
160   - if (scriptTypes[0].srcRequired && !script.src)
161   - throw `An attribute 'src' should be declared for MIME-type '${script.type}'`;
162   -
163   - switch(scriptType) {
164   - case 'class':
165   - this.scripts.push(new JavaClassFile(this, script));
166   - break;
167   - case 'java':
168   - let javaSource = new JavaSourceFile(this, script);
169   - this.scripts.push(javaSource);
170   - this.sources.push(javaSource);
171   - break;
172   - case 'jar':
173   - this.scripts.push(new JavaArchiveFile(this, script));
174   - break;
175   - }
176   - }
177   - });
  161 + startJavaPolyWebWorker(javaMimeScripts,resolveJVMReady) {
  162 + this.worker = new global.Worker(this.options.worker);
  163 + this.worker.addEventListener('message', e => {
  164 + let data = e.data.javapoly;
  165 + //JVM Init response
  166 + if (data.messgeType == 'JVM_INIT'){
  167 + if (data.success == true){ // JVM init success..
  168 + console.log('JVM init success in webWorkers');
  169 + resolveJVMReady();
  170 + }else{
  171 + console.log('JVM init failed in webWorkers');
  172 + // try to load in main thread directly when JVM init failed in WebWorkers ?
  173 + // this.loadExternalJs(this.options.doppioLibUrl+'vendor/browserfs/dist/browserfs.min.js').then(()=> {
  174 + //
  175 + // new JavaPolyLoader(this, javaMimeScripts,
  176 + // () => {this.loadingHub.push(this.loadExternalJs(this.options.doppioLibUrl+'doppio.js'));},
  177 + // resolveJVMReady);
  178 + // });
  179 + }
  180 + } else {
  181 + //JVM command(METHOD_INVOKATION/CLASS_LOADING/...) response
  182 + let cb = window.javaPolyCallbacks[data.messageId];
  183 + cb(data.returnValue);
  184 + }
  185 + }, false);
  186 +
  187 + // send JVM init request to webworker to init the jvm in javapoly workers.
  188 + this.worker.postMessage({javapoly:{ messgeType : 'JVM_INIT', data:{options:this.options, scripts:javaMimeScripts}}});
178 189 }
179 190  
180 191 /* This should be called outside of Promise, or any such async call */
... ... @@ -199,26 +210,6 @@ class JavaPoly {
199 210 }
200 211  
201 212 /**
202   - * Initialization of BrowserFS
203   - */
204   - initBrowserFS(){
205   - let mfs = new BrowserFS.FileSystem.MountableFileSystem();
206   - BrowserFS.initialize(mfs);
207   - mfs.mount('/tmp', new BrowserFS.FileSystem.InMemory());
208   - mfs.mount('/home', new BrowserFS.FileSystem.LocalStorage());
209   - mfs.mount('/sys', new BrowserFS.FileSystem.XmlHttpRequest('listings.json', this.options.doppioLibUrl));
210   - mfs.mount('/polynatives', new BrowserFS.FileSystem.XmlHttpRequest('polylistings.json', "natives/"));
211   - mfs.mount('/javapolySys', new BrowserFS.FileSystem.XmlHttpRequest('libListings.json', this.options.javaPolyBaseUrl + "/sys/"));
212   - mfs.mount('/javapolySysNatives', new BrowserFS.FileSystem.XmlHttpRequest('libListings.json', this.options.javaPolyBaseUrl + "/sysNatives/"));
213   -
214   -
215   - this.fs = BrowserFS.BFSRequire('fs');
216   - this.path = BrowserFS.BFSRequire('path');
217   - this.fsext = require('./tools/fsext')(this.fs, this.path);
218   - this.fsext.rmkdirSync(this.options.storageDir);
219   - }
220   -
221   - /**
222 213 * load js library file.
223 214 * @param fileSrc
224 215 * the uri src of the file
... ... @@ -267,50 +258,6 @@ class JavaPoly {
267 258 window.javaPolyIdCount = 0;
268 259 }
269 260  
270   - /**
271   - * Return a promise that JVM will be initialised for this JavaPoly:
272   - * 1. Ensure that all loading promises are finished
273   - * 2. Create object for JVM
274   - */
275   - initJVM() {
276   - this.initDispatcher();
277   -
278   - return new Promise((resolve) => {
279   -
280   - Promise.all(this.loadingHub).then(()=> {
281   - // Delete loadingHub (if somewhere else it is used so it's gonna be runtime error of that usage)
282   - delete this.loadingHub;
283   - this.loadingHub = [];
284   -
285   - this.jvm = new Doppio.VM.JVM({
286   - bootstrapClasspath: ['/sys/vendor/java_home/classes', "/javapolySys"],
287   - classpath: this.classpath,
288   - javaHomePath: '/sys/vendor/java_home',
289   - extractionPath: '/tmp',
290   - nativeClasspath: ['/sys/natives', '/polynatives', "/javapolySysNatives"],
291   - assertionsEnabled: true
292   - }, (err, jvm) => {
293   - if (err) {
294   - console.log("err loading JVM:", err);
295   - } else {
296   - var self = this
297   - window.javaPolyInitialisedCallback = function() {
298   - // Compilation of Java sorces
299   - const compilationHub = self.sources.map( (src) => src.compile() );
300   - Promise.all(compilationHub).then(resolve);
301   - }
302   -
303   - jvm.runClass('javapoly.Main', [], function(exitCode) {
304   - // Control flow shouldn't reach here under normal circumstances,
305   - // because Main thread keeps polling for messages.
306   - console.log("JVM Exit code: ", exitCode);
307   - });
308   -
309   - }
310   - });
311   - });
312   - });
313   - }
314 261 }
315 262  
316 263 export default JavaPoly;
... ...
src/JavaPolyLoader.js 0 → 100644
... ... @@ -0,0 +1,159 @@
  1 +import JavaClassFile from './JavaClassFile';
  2 +import JavaArchiveFile from './JavaArchiveFile';
  3 +import JavaSourceFile from './JavaSourceFile';
  4 +
  5 +const JAVA_MIME = [
  6 + { // For compiled Java-class
  7 + type: 'class',
  8 + mime: ['application/java-vm'],
  9 + srcRequired: true
  10 + },
  11 + { // For Java source files
  12 + type: 'java',
  13 + mime: ['text/x-java-source'],
  14 + srcRequired: false
  15 + },
  16 + { // For JAR-files
  17 + type: 'jar',
  18 + mime: ['application/java-archive'],
  19 + srcRequired: true
  20 + }
  21 +];
  22 +
  23 +/**
  24 + * The JavaPolyLoader load the jvm and do the basic init of javapoly.
  25 + * can be run both in Browser or WebWorker
  26 + *
  27 + * The JavaPoly loader will do the following step
  28 + * 1. init the browserFS of JavaPoly,
  29 + * 2. run the callback {callbackBeforeStartJVM}
  30 + * 3. load java mime scripts
  31 + * 4. start jvm
  32 + *
  33 + * @param javapoly
  34 + * the javapoly instance to loader
  35 + * @param scripts
  36 + * the scripts {src, type} include the java mime script to load,
  37 + * we will only load the script in JAVA_MIME.
  38 + * @param callbackBeforeStartJVM
  39 + * the callback execute before JVM start
  40 + * @param resolveJVMReady
  41 + * the callback execute when jvm start finished.
  42 + *
  43 + */
  44 +class JavaPolyLoader {
  45 +
  46 + constructor(javapoly, scripts, callbackBeforeStartJVM, resolveJVMReady) {
  47 +
  48 + this.javapoly = javapoly;
  49 +
  50 + this.initBrowserFS();
  51 +
  52 + if (callbackBeforeStartJVM){
  53 + callbackBeforeStartJVM();
  54 + }
  55 +
  56 + this.loadScripts(scripts);
  57 + this.initJVM().then(resolveJVMReady);
  58 + }
  59 +
  60 + loadScripts(scripts) {
  61 + // Load java mime files
  62 + // _.each(scripts, script => {
  63 + for(let script of scripts) {
  64 + let scriptTypes = JAVA_MIME.filter(item => item.mime.some(m => m === script.type));
  65 + // Create only when scriptTypes is only 1
  66 + if (scriptTypes.length === 1) {
  67 + let scriptType = scriptTypes[0].type;
  68 +
  69 + if (scriptTypes[0].srcRequired && !script.src)
  70 + throw `An attribute 'src' should be declared for MIME-type '${script.type}'`;
  71 +
  72 + switch(scriptType) {
  73 + case 'class':
  74 + this.javapoly.scripts.push(new JavaClassFile(this.javapoly, script));
  75 + break;
  76 + case 'java':
  77 + let javaSource = new JavaSourceFile(this.javapoly, script);
  78 + this.javapoly.scripts.push(javaSource);
  79 + this.javapoly.sources.push(javaSource);
  80 + break;
  81 + case 'jar':
  82 + this.javapoly.scripts.push(new JavaArchiveFile(this.javapoly, script));
  83 + break;
  84 + }
  85 + }
  86 + };
  87 + }
  88 +
  89 + /**
  90 + * Initialization of BrowserFS
  91 + */
  92 + initBrowserFS(){
  93 + let mfs = new BrowserFS.FileSystem.MountableFileSystem();
  94 + BrowserFS.initialize(mfs);
  95 + mfs.mount('/tmp', new BrowserFS.FileSystem.InMemory());
  96 +
  97 + // FIXME local storage can't be used in WebWorker, check if it affect anything.
  98 + if (!window.isJavaPolyWorker)
  99 + mfs.mount('/home', new BrowserFS.FileSystem.LocalStorage());
  100 +
  101 + mfs.mount('/sys', new BrowserFS.FileSystem.XmlHttpRequest('listings.json', this.javapoly.options.doppioLibUrl));
  102 + mfs.mount('/polynatives', new BrowserFS.FileSystem.XmlHttpRequest('polylistings.json', "/natives/"));
  103 + mfs.mount('/javapolySys', new BrowserFS.FileSystem.XmlHttpRequest('libListings.json', this.javapoly.options.javaPolyBaseUrl + "/sys/"));
  104 + mfs.mount('/javapolySysNatives', new BrowserFS.FileSystem.XmlHttpRequest('libListings.json', this.javapoly.options.javaPolyBaseUrl + "/sysNatives/"));
  105 +
  106 + this.javapoly.fs = BrowserFS.BFSRequire('fs');
  107 + this.javapoly.path = BrowserFS.BFSRequire('path');
  108 + this.javapoly.fsext = require('./tools/fsext')(this.javapoly.fs, this.javapoly.path);
  109 + this.javapoly.fsext.rmkdirSync(this.javapoly.options.storageDir);
  110 + }
  111 +
  112 +
  113 + /**
  114 + * Return a promise that JVM will be initialised for this JavaPoly:
  115 + * 1. Ensure that all loading promises are finished
  116 + * 2. Create object for JVM
  117 + */
  118 + initJVM() {
  119 + return new Promise( (resolve, reject) => {
  120 +
  121 + Promise.all(this.javapoly.loadingHub).then(()=> {
  122 + // Delete loadingHub (if somewhere else it is used so it's gonna be runtime error of that usage)
  123 + delete this.javapoly.loadingHub;
  124 + this.loadingHub = [];
  125 +
  126 + this.javapoly.jvm = new Doppio.VM.JVM({
  127 + bootstrapClasspath: ['/sys/vendor/java_home/classes', "/javapolySys"],
  128 + classpath: this.javapoly.classpath,
  129 + javaHomePath: '/sys/vendor/java_home',
  130 + extractionPath: '/tmp',
  131 + nativeClasspath: ['/sys/natives', '/polynatives', "/javapolySysNatives"],
  132 + assertionsEnabled: true
  133 + }, (err, jvm) => {
  134 + if (err) {
  135 + console.log('err loading JVM:', err);
  136 + reject();
  137 + } else {
  138 + // var self = this
  139 + self.javapoly = this.javapoly;
  140 + window.javaPolyInitialisedCallback = () => {
  141 + // Compilation of Java sorces
  142 + const compilationHub = this.javapoly.sources.map( (src) => src.compile() );
  143 + Promise.all(compilationHub).then(resolve);
  144 + }
  145 +
  146 + jvm.runClass('javapoly.Main', [], function(exitCode) {
  147 + // Control flow shouldn't reach here under normal circumstances,
  148 + // because Main thread keeps polling for messages.
  149 + console.log("JVM Exit code: ", exitCode);
  150 + });
  151 +
  152 + }
  153 + });
  154 + });
  155 + });
  156 + }
  157 +}
  158 +
  159 +export default JavaPolyLoader;
0 160 \ No newline at end of file
... ...
src/webworkers/JavaPolyWorker.js 0 → 100644
... ... @@ -0,0 +1,141 @@
  1 +import * as _ from 'underscore';
  2 +import JavaPolyLoader from '../JavaPolyLoader';
  3 +
  4 +class JavaPolyWorker {
  5 +
  6 + constructor(options) {
  7 +
  8 + /**
  9 + * Stores referense to the BrowserFS fs-library
  10 + *
  11 + * @type {BrowserFS}
  12 + */
  13 + this.fs = null;
  14 +
  15 + /**
  16 + * Stores referense to the BrowserFS path-library
  17 + *
  18 + * @type {[type]}
  19 + */
  20 + this.path = null;
  21 +
  22 + /**
  23 + * Stores referense to the special extension for fs (for example it contains recursive mkdir)
  24 + *
  25 + * @type {[type]}
  26 + */
  27 + this.fsext = null;
  28 +
  29 + /**
  30 + * Array of all registered Java classes, jars, or sources
  31 + *
  32 + * @type {Array}
  33 + */
  34 + this.scripts = [];
  35 +
  36 + /**
  37 + * Array of all registered Java sources.
  38 + *
  39 + * @type {Array}
  40 + */
  41 + this.sources = [];
  42 +
  43 + /**
  44 + * Array that contains all promises that should be resolved before JVM running. This array should be used for
  45 + * loading script
  46 + *
  47 + * @type {Array<Promise>}
  48 + */
  49 + this.loadingHub = [];
  50 +
  51 + /**
  52 + * Object with options of JavaPoly
  53 + *
  54 + * @type {Object}
  55 + */
  56 + this.options = options;
  57 +
  58 + /**
  59 + * Array that contains classpath, include the root path of class files , jar file path.
  60 + *
  61 + * @type {Array}
  62 + */
  63 + this.classpath = [this.options.storageDir];
  64 +
  65 + // NOTES, hack global window variable used in doppio, javapoly.
  66 + global.window = global.self;
  67 +
  68 + // load browserfs.min.js and doppio.js
  69 + importScripts(this.options.doppioLibUrl+'vendor/browserfs/dist/browserfs.min.js');
  70 + importScripts(this.options.doppioLibUrl+'doppio.js');
  71 + }
  72 +
  73 + /**
  74 + * init the jvm and load library in web workers
  75 + */
  76 + init(javaMimeScripts, cb){
  77 + this.initDispatcher();
  78 + new JavaPolyLoader(this, javaMimeScripts, null, () => cb(true));
  79 + }
  80 +
  81 + initDispatcher() {
  82 + window.javaPolyMessageTypes = {};
  83 + window.javaPolyCallbacks = {};
  84 + window.javaPolyData = {};
  85 + window.javaPolyIdCount = 0;
  86 +
  87 + window.isJavaPolyWorker = true;
  88 + }
  89 +}
  90 +
  91 +self.addEventListener('message', function(e) {
  92 + if (!e.data || !e.data.javapoly)
  93 + //invalid command, ignore
  94 + return;
  95 + let data = e.data.javapoly;
  96 +
  97 + switch (data.messgeType) {
  98 +
  99 + // NOTES, we need some options,Java MIME script path info from browser main thread.
  100 + // so here we add a JVM_INIT command.
  101 + case 'JVM_INIT':
  102 + self.removeEventListener('message', this);
  103 + self.javaPolyWorker = new JavaPolyWorker(data.data.options);
  104 + self.javaPolyWorker.init( data.data.scripts, (result) => {
  105 + global.self.postMessage({javapoly:{messgeType:'JVM_INIT', success:result}});
  106 + } );
  107 + break;
  108 +
  109 + default:
  110 + // FIXME here we pass the args and return value.
  111 + // FIXME how to support self-defined object, stream, file handler...
  112 + if (typeof (data) == "object") {
  113 + let id = data.messageId;
  114 + if (!id)
  115 + //invalid command, ignore
  116 + return;
  117 +
  118 + window.javaPolyMessageTypes[id] = data.messageType;
  119 + window.javaPolyData[id] = data.data;
  120 + window.javaPolyCallbacks[id] = (returnValue) => {
  121 + global.self.postMessage({javapoly:{messageId: id, messageType:data.messageType, returnValue:returnValue}});
  122 + } ;
  123 +
  124 + // we can't use the window.postMesssage here in Webworkers.
  125 + // FIXME Hack the Main.js.installListener() by using the webworker.addEventListener
  126 + // window.postMessage({ javapoly:{ 'messageId':""+id } }, "*");
  127 +
  128 + e.preventDefault();
  129 + if (!window.javaPolyEvents)
  130 + window.javaPolyEvents = [];
  131 + window.javaPolyEvents.push(e);
  132 + if (window.javaPolyCallback) {
  133 + window.javaPolyCallback();
  134 + }
  135 + }
  136 + break;
  137 + }
  138 + ;
  139 +}, false);
  140 +
  141 +
... ...
sysNatives/Main.js
... ... @@ -78,8 +78,10 @@ registerNatives({
78 78 },
79 79  
80 80 'installListener()V': function(thread) {
81   - window.javaPolyEvents = [];
82   - window.addEventListener("message", function(event) {
  81 + if (!window.javaPolyEvents)
  82 + window.javaPolyEvents = [];
  83 + if (!window.isJavaPolyWorker) {
  84 + window.addEventListener("message", function(event) {
83 85 if (event.origin == window.location.origin) {
84 86 if (typeof (event.data.javapoly) == "object") {
85 87 event.preventDefault();
... ... @@ -90,7 +92,8 @@ registerNatives({
90 92 }
91 93 }
92 94 }
93   - });
  95 + });
  96 + }
94 97 if (window.javaPolyInitialisedCallback) {
95 98 var callback = window.javaPolyInitialisedCallback;
96 99 delete window.javaPolyInitialisedCallback;
... ...