Skip to content

Commit 507b962

Browse files
authored
Merge pull request #66 from golemcloud/node-stream
Node stream support
2 parents 5de7ce7 + 6ece8d8 commit 507b962

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+10257
-139
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,3 +1003,18 @@ There are a few important things to keep in mind when working on the project:
10031003
times and huge resulting binaries. Use the `cleanup-skeleton.sh` script to quickly remove the `target` directory from
10041004
the `skeleton` crate.
10051005

1006+
## Acknowledgements
1007+
1008+
The builtin JS modules are based on the work of several other projects:
1009+
1010+
- [base64-js](https://github.com/beatgammit/base64-js)
1011+
- [buffer](https://github.com/feross/buffer)
1012+
- [consoleTable](https://github.com/ronnyKJ/consoleTable)
1013+
- [eventemitter3](https://github.com/primus/eventemitter3)
1014+
- [fetch-blob](https://github.com/node-fetch/fetch-blob)
1015+
- [fetch.js](https://github.com/JakeChampion/fetch/blob/main/fetch.js)
1016+
- [FormData](https://github.com/jimmywarting/FormData)
1017+
- [ieee754](https://github.com/feross/ieee754)
1018+
- [url-search-params-polyfill](https://github.com/jerrybendy/url-search-params-polyfill)
1019+
- [wasmedge-quickjs](https://github.com/second-state/wasmedge-quickjs)
1020+
- [web-streams-polyfill](https://github.com/MattiasBuelens/web-streams-polyfill)

crates/wasm-rquickjs/skeleton/Cargo.toml_

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ logging = ["dep:wasi-logging"]
2020

2121
[dependencies]
2222
# Core dependencies
23+
# rquickjs = { version = "0.10.0", default-features = false, features = ["full-async-wasi"] }
24+
# rquickjs = { git = "https://github.com/DelSkayn/rquickjs", rev="7e921da7637ce6c330ab206f17d9ae5d275d8755", default-features = false, features = ["full-async-wasi"] }
2325
rquickjs = { version = "0.9.0", default-features = false, features = ["futures", "bindgen", "loader", "macro"] }
2426

2527
encoding_rs = "0.8.35"
2628
futures = { version = "0.3.31", features = [] }
2729
futures-concurrency = "7.6.3"
28-
pin-project = "1.1.10"
2930
url = "2.5.7"
3031
uuid = { version = "1.18.1", features = ["v4"] }
3132
rand = "0.9.2"
Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
// From https://github.com/primus/eventemitter3/
2+
3+
'use strict';
4+
5+
var has = Object.prototype.hasOwnProperty
6+
, prefix = '~';
7+
8+
/**
9+
* Constructor to create a storage for our `EE` objects.
10+
* An `Events` instance is a plain object whose properties are event names.
11+
*
12+
* @constructor
13+
* @private
14+
*/
15+
function Events() {}
16+
17+
//
18+
// We try to not inherit from `Object.prototype`. In some engines creating an
19+
// instance in this way is faster than calling `Object.create(null)` directly.
20+
// If `Object.create(null)` is not supported we prefix the event names with a
21+
// character to make sure that the built-in object properties are not
22+
// overridden or used as an attack vector.
23+
//
24+
if (Object.create) {
25+
Events.prototype = Object.create(null);
26+
27+
//
28+
// This hack is needed because the `__proto__` property is still inherited in
29+
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
30+
//
31+
if (!new Events().__proto__) prefix = false;
32+
}
33+
34+
/**
35+
* Representation of a single event listener.
36+
*
37+
* @param {Function} fn The listener function.
38+
* @param {*} context The context to invoke the listener with.
39+
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
40+
* @constructor
41+
* @private
42+
*/
43+
function EE(fn, context, once) {
44+
this.fn = fn;
45+
this.context = context;
46+
this.once = once || false;
47+
}
48+
49+
/**
50+
* Add a listener for a given event.
51+
*
52+
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
53+
* @param {(String|Symbol)} event The event name.
54+
* @param {Function} fn The listener function.
55+
* @param {*} context The context to invoke the listener with.
56+
* @param {Boolean} once Specify if the listener is a one-time listener.
57+
* @returns {EventEmitter}
58+
* @private
59+
*/
60+
function addListener(emitter, event, fn, context, once) {
61+
if (typeof fn !== 'function') {
62+
throw new TypeError('The listener must be a function');
63+
}
64+
65+
var listener = new EE(fn, context || emitter, once)
66+
, evt = prefix ? prefix + event : event;
67+
68+
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
69+
else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
70+
else emitter._events[evt] = [emitter._events[evt], listener];
71+
72+
return emitter;
73+
}
74+
75+
/**
76+
* Clear event by name.
77+
*
78+
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
79+
* @param {(String|Symbol)} evt The Event name.
80+
* @private
81+
*/
82+
function clearEvent(emitter, evt) {
83+
if (--emitter._eventsCount === 0) emitter._events = new Events();
84+
else delete emitter._events[evt];
85+
}
86+
87+
/**
88+
* Minimal `EventEmitter` interface that is molded against the Node.js
89+
* `EventEmitter` interface.
90+
*
91+
* @constructor
92+
* @public
93+
*/
94+
function EventEmitter() {
95+
this._events = new Events();
96+
this._eventsCount = 0;
97+
}
98+
99+
/**
100+
* Return an array listing the events for which the emitter has registered
101+
* listeners.
102+
*
103+
* @returns {Array}
104+
* @public
105+
*/
106+
EventEmitter.prototype.eventNames = function eventNames() {
107+
var names = []
108+
, events
109+
, name;
110+
111+
if (this._eventsCount === 0) return names;
112+
113+
for (name in (events = this._events)) {
114+
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
115+
}
116+
117+
if (Object.getOwnPropertySymbols) {
118+
return names.concat(Object.getOwnPropertySymbols(events));
119+
}
120+
121+
return names;
122+
};
123+
124+
/**
125+
* Return the listeners registered for a given event.
126+
*
127+
* @param {(String|Symbol)} event The event name.
128+
* @returns {Array} The registered listeners.
129+
* @public
130+
*/
131+
EventEmitter.prototype.listeners = function listeners(event) {
132+
var evt = prefix ? prefix + event : event
133+
, handlers = this._events[evt];
134+
135+
if (!handlers) return [];
136+
if (handlers.fn) return [handlers.fn];
137+
138+
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
139+
ee[i] = handlers[i].fn;
140+
}
141+
142+
return ee;
143+
};
144+
145+
/**
146+
* Return the number of listeners listening to a given event.
147+
*
148+
* @param {(String|Symbol)} event The event name.
149+
* @returns {Number} The number of listeners.
150+
* @public
151+
*/
152+
EventEmitter.prototype.listenerCount = function listenerCount(event) {
153+
var evt = prefix ? prefix + event : event
154+
, listeners = this._events[evt];
155+
156+
if (!listeners) return 0;
157+
if (listeners.fn) return 1;
158+
return listeners.length;
159+
};
160+
161+
/**
162+
* Calls each of the listeners registered for a given event.
163+
*
164+
* @param {(String|Symbol)} event The event name.
165+
* @returns {Boolean} `true` if the event had listeners, else `false`.
166+
* @public
167+
*/
168+
EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
169+
var evt = prefix ? prefix + event : event;
170+
171+
if (!this._events[evt]) return false;
172+
173+
var listeners = this._events[evt]
174+
, len = arguments.length
175+
, args
176+
, i;
177+
178+
if (listeners.fn) {
179+
if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
180+
181+
switch (len) {
182+
case 1: return listeners.fn.call(listeners.context), true;
183+
case 2: return listeners.fn.call(listeners.context, a1), true;
184+
case 3: return listeners.fn.call(listeners.context, a1, a2), true;
185+
case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
186+
case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
187+
case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
188+
}
189+
190+
for (i = 1, args = new Array(len -1); i < len; i++) {
191+
args[i - 1] = arguments[i];
192+
}
193+
194+
listeners.fn.apply(listeners.context, args);
195+
} else {
196+
var length = listeners.length
197+
, j;
198+
199+
for (i = 0; i < length; i++) {
200+
if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
201+
202+
switch (len) {
203+
case 1: listeners[i].fn.call(listeners[i].context); break;
204+
case 2: listeners[i].fn.call(listeners[i].context, a1); break;
205+
case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
206+
case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
207+
default:
208+
if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
209+
args[j - 1] = arguments[j];
210+
}
211+
212+
listeners[i].fn.apply(listeners[i].context, args);
213+
}
214+
}
215+
}
216+
217+
return true;
218+
};
219+
220+
/**
221+
* Add a listener for a given event.
222+
*
223+
* @param {(String|Symbol)} event The event name.
224+
* @param {Function} fn The listener function.
225+
* @param {*} [context=this] The context to invoke the listener with.
226+
* @returns {EventEmitter} `this`.
227+
* @public
228+
*/
229+
EventEmitter.prototype.on = function on(event, fn, context) {
230+
return addListener(this, event, fn, context, false);
231+
};
232+
233+
/**
234+
* Add a one-time listener for a given event.
235+
*
236+
* @param {(String|Symbol)} event The event name.
237+
* @param {Function} fn The listener function.
238+
* @param {*} [context=this] The context to invoke the listener with.
239+
* @returns {EventEmitter} `this`.
240+
* @public
241+
*/
242+
EventEmitter.prototype.once = function once(event, fn, context) {
243+
return addListener(this, event, fn, context, true);
244+
};
245+
246+
/**
247+
* Remove the listeners of a given event.
248+
*
249+
* @param {(String|Symbol)} event The event name.
250+
* @param {Function} fn Only remove the listeners that match this function.
251+
* @param {*} context Only remove the listeners that have this context.
252+
* @param {Boolean} once Only remove one-time listeners.
253+
* @returns {EventEmitter} `this`.
254+
* @public
255+
*/
256+
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
257+
var evt = prefix ? prefix + event : event;
258+
259+
if (!this._events[evt]) return this;
260+
if (!fn) {
261+
clearEvent(this, evt);
262+
return this;
263+
}
264+
265+
var listeners = this._events[evt];
266+
267+
if (listeners.fn) {
268+
if (
269+
listeners.fn === fn &&
270+
(!once || listeners.once) &&
271+
(!context || listeners.context === context)
272+
) {
273+
clearEvent(this, evt);
274+
}
275+
} else {
276+
for (var i = 0, events = [], length = listeners.length; i < length; i++) {
277+
if (
278+
listeners[i].fn !== fn ||
279+
(once && !listeners[i].once) ||
280+
(context && listeners[i].context !== context)
281+
) {
282+
events.push(listeners[i]);
283+
}
284+
}
285+
286+
//
287+
// Reset the array, or remove it completely if we have no more listeners.
288+
//
289+
if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
290+
else clearEvent(this, evt);
291+
}
292+
293+
return this;
294+
};
295+
296+
/**
297+
* Remove all listeners, or those of the specified event.
298+
*
299+
* @param {(String|Symbol)} [event] The event name.
300+
* @returns {EventEmitter} `this`.
301+
* @public
302+
*/
303+
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
304+
var evt;
305+
306+
if (event) {
307+
evt = prefix ? prefix + event : event;
308+
if (this._events[evt]) clearEvent(this, evt);
309+
} else {
310+
this._events = new Events();
311+
this._eventsCount = 0;
312+
}
313+
314+
return this;
315+
};
316+
317+
//
318+
// Alias methods names because people roll like that.
319+
//
320+
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
321+
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
322+
323+
//
324+
// Expose the prefix.
325+
//
326+
EventEmitter.prefixed = prefix;
327+
328+
//
329+
// Allow `EventEmitter` to be imported as module namespace.
330+
//
331+
EventEmitter.EventEmitter = EventEmitter;
332+
333+
//
334+
// Expose the module.
335+
//
336+
export { EventEmitter };
337+
338+
export default { EventEmitter };
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// JS functions for the EventEmitter implementation
2+
pub const EVENTEMITTER_JS: &str = include_str!("eventemitter.js");

0 commit comments

Comments
 (0)