2
function EventListener() {
5
this.addEventListener = function(event, func) {
6
if (!this.listeners[event]) this.listeners[event] = [];
7
this.listeners[event].push(func);
10
this.fireEvent = function(event) {
11
event.preventDefault = function(){};
13
if (event.type in this.listeners) {
14
this.listeners[event.type].forEach(function(listener) {
22
var windowExtra = new EventListener();
23
for (var x in windowExtra) window[x] = windowExtra[x];
25
window.close = function() {
26
postMessage({ target: 'window', method: 'close' });
29
var document = new EventListener();
31
document.createElement = function(what) {
34
var canvas = new EventListener();
35
canvas.ensureData = function() {
36
if (!canvas.data || canvas.data.width !== canvas.width || canvas.data.height !== canvas.height) {
39
height: canvas.height,
40
data: new Uint8Array(canvas.width*canvas.height*4)
42
postMessage({ target: 'canvas', op: 'resize', width: canvas.width, height: canvas.height });
45
canvas.getContext = function(type) {
48
getImageData: function(x, y, w, h) {
49
assert(x == 0 && y == 0 && w == canvas.width && h == canvas.height);
52
width: canvas.data.width,
53
height: canvas.data.height,
54
data: new Uint8Array(canvas.data.data) // TODO: can we avoid this copy?
57
putImageData: function(image, x, y) {
59
assert(x == 0 && y == 0 && image.width == canvas.width && image.height == canvas.height);
60
canvas.data.data.set(image.data); // TODO: can we avoid this copy?
61
postMessage({ target: 'canvas', op: 'render', image: canvas.data });
65
canvas.boundingClientRect = {};
66
canvas.getBoundingClientRect = function() {
68
width: canvas.boundingClientRect.width,
69
height: canvas.boundingClientRect.height,
70
top: canvas.boundingClientRect.top,
71
left: canvas.boundingClientRect.left,
72
bottom: canvas.boundingClientRect.bottom,
73
right: canvas.boundingClientRect.right
78
default: throw 'document.createElement ' + what;
88
Module.canvas = document.createElement('canvas');
90
Module.setStatus = function(){};
92
Module.print = function(x) {
93
postMessage({ target: 'stdout', content: x });
95
Module.printErr = function(x) {
96
postMessage({ target: 'stderr', content: x });
99
// buffer messages until the program starts to run
101
var messageBuffer = null;
103
function messageResender() {
105
assert(messageBuffer && messageBuffer.length > 0);
106
messageBuffer.forEach(function(message) {
109
messageBuffer = null;
111
setTimeout(messageResender, 100);
115
onmessage = function(message) {
117
if (!messageBuffer) {
119
setTimeout(messageResender, 100);
121
messageBuffer.push(message);
123
switch (message.data.target) {
125
document.fireEvent(message.data.event);
129
window.fireEvent(message.data.event);
133
if (message.data.event) {
134
Module.canvas.fireEvent(message.data.event);
135
} else if (message.data.boundingClientRect) {
136
Module.canvas.boundingClientRect = message.data.boundingClientRect;
140
default: throw 'wha? ' + message.data.target;