summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/bench/spawn.js11
-rw-r--r--ext/web/06_streams.js30
-rw-r--r--runtime/js/40_spawn.js20
3 files changed, 40 insertions, 21 deletions
diff --git a/cli/bench/spawn.js b/cli/bench/spawn.js
new file mode 100644
index 000000000..f5a658f3f
--- /dev/null
+++ b/cli/bench/spawn.js
@@ -0,0 +1,11 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+
+Deno.bench("echo deno", async () => {
+ await Deno.spawn("echo", { args: ["deno"] });
+});
+
+Deno.bench("cat 128kb", async () => {
+ await Deno.spawn("cat", {
+ args: ["./cli/bench/testdata/128k.bin"],
+ });
+});
diff --git a/ext/web/06_streams.js b/ext/web/06_streams.js
index 0b9e00483..d51556a37 100644
--- a/ext/web/06_streams.js
+++ b/ext/web/06_streams.js
@@ -730,6 +730,7 @@
const stream = webidl.createBranded(ReadableStream);
stream[promiseIdSymbol] = undefined;
stream[_isUnref] = false;
+ stream[_resourceBackingUnrefable] = { rid, autoClose: true };
const underlyingSource = {
type: "bytes",
async pull(controller) {
@@ -767,8 +768,14 @@
return stream;
}
+ function readableStreamIsUnrefable(stream) {
+ return _isUnref in stream;
+ }
+
function readableStreamForRidUnrefableRef(stream) {
- if (!(_isUnref in stream)) throw new TypeError("Not an unrefable stream");
+ if (!readableStreamIsUnrefable(stream)) {
+ throw new TypeError("Not an unrefable stream");
+ }
stream[_isUnref] = false;
if (stream[promiseIdSymbol] !== undefined) {
core.refOp(stream[promiseIdSymbol]);
@@ -776,7 +783,9 @@
}
function readableStreamForRidUnrefableUnref(stream) {
- if (!(_isUnref in stream)) throw new TypeError("Not an unrefable stream");
+ if (!readableStreamIsUnrefable(stream)) {
+ throw new TypeError("Not an unrefable stream");
+ }
stream[_isUnref] = true;
if (stream[promiseIdSymbol] !== undefined) {
core.unrefOp(stream[promiseIdSymbol]);
@@ -787,15 +796,25 @@
return stream[_resourceBacking];
}
+ function getReadableStreamResourceBackingUnrefable(stream) {
+ return stream[_resourceBackingUnrefable];
+ }
+
async function readableStreamCollectIntoUint8Array(stream) {
- const resourceBacking = getReadableStreamResourceBacking(stream);
+ const resourceBacking = getReadableStreamResourceBacking(stream) ||
+ getReadableStreamResourceBackingUnrefable(stream);
const reader = acquireReadableStreamDefaultReader(stream);
if (resourceBacking) {
// fast path, read whole body in a single op call
try {
readableStreamDisturb(stream);
- const buf = await core.opAsync("op_read_all", resourceBacking.rid);
+ const promise = core.opAsync("op_read_all", resourceBacking.rid);
+ if (readableStreamIsUnrefable(stream)) {
+ const promiseId = stream[promiseIdSymbol] = promise[promiseIdSymbol];
+ if (stream[_isUnref]) core.unrefOp(promiseId);
+ }
+ const buf = await promise;
readableStreamThrowIfErrored(stream);
readableStreamClose(stream);
return buf;
@@ -4585,6 +4604,9 @@
}
const _resourceBacking = Symbol("[[resourceBacking]]");
+ // This distinction exists to prevent unrefable streams being used in
+ // regular fast streams that are unaware of refability
+ const _resourceBackingUnrefable = Symbol("[[resourceBackingUnrefable]]");
/** @template R */
class ReadableStream {
/** @type {ReadableStreamDefaultController | ReadableByteStreamController} */
diff --git a/runtime/js/40_spawn.js b/runtime/js/40_spawn.js
index e262a1325..8f44c8929 100644
--- a/runtime/js/40_spawn.js
+++ b/runtime/js/40_spawn.js
@@ -12,12 +12,12 @@
ObjectEntries,
String,
TypeError,
- Uint8Array,
PromisePrototypeThen,
SafePromiseAll,
SymbolFor,
} = window.__bootstrap.primordials;
const {
+ readableStreamCollectIntoUint8Array,
readableStreamForRidUnrefable,
readableStreamForRidUnrefableRef,
readableStreamForRidUnrefableUnref,
@@ -64,26 +64,12 @@
};
}
- async function collectOutput(readableStream) {
+ function collectOutput(readableStream) {
if (!(readableStream instanceof ReadableStream)) {
return null;
}
- const bufs = [];
- let size = 0;
- for await (const chunk of readableStream) {
- bufs.push(chunk);
- size += chunk.byteLength;
- }
-
- const buffer = new Uint8Array(size);
- let offset = 0;
- for (const chunk of bufs) {
- buffer.set(chunk, offset);
- offset += chunk.byteLength;
- }
-
- return buffer;
+ return readableStreamCollectIntoUint8Array(readableStream);
}
class Child {