Files

163 lines
4.2 KiB
JavaScript

export function immediateCancelIterable() {
return {
[Symbol.iterator]() {
return {
next() {
console.log("source iterator started");
return { value: 1, done: false };
},
return(reason) {
console.log("source iterator returned:", reason);
return { value: undefined, done: true };
},
};
},
};
}
export async function streamFromProtocolProbe() {
const promiseChunk = Promise.resolve(8);
const asyncSource = {
[Symbol.asyncIterator]() {
return {
next() {
return Promise.resolve({ value: promiseChunk, done: false });
},
};
},
};
const asyncReader = ReadableStream.from(asyncSource).getReader();
const asyncPart = await asyncReader.read();
console.log("async promise chunk preserved:", asyncPart.value === promiseChunk);
await asyncReader.cancel();
try {
ReadableStream.from({
[Symbol.iterator]() {
return null;
},
});
console.log("invalid iterator unexpectedly accepted");
} catch (error) {
console.log("invalid iterator:", error.name);
}
try {
ReadableStream.from({
[Symbol.asyncIterator]: false,
*[Symbol.iterator]() {
yield 1;
},
});
console.log("noncallable async iterator unexpectedly accepted");
} catch (error) {
console.log("noncallable async iterator:", error.name);
}
let nextReads = 0;
let nextCalls = 0;
const stableNextSource = {
[Symbol.asyncIterator]() {
return {
get next() {
nextReads++;
return function () {
nextCalls++;
return Promise.resolve(
nextCalls === 1
? { value: 9, done: false }
: { value: undefined, done: true },
);
};
},
};
},
};
const stableNextReader = ReadableStream.from(stableNextSource).getReader();
console.log("async next reads at setup:", nextReads);
await stableNextReader.read();
await stableNextReader.read();
console.log("async next method reused:", nextReads, nextCalls);
try {
const invalidNextStream = ReadableStream.from({
[Symbol.asyncIterator]() {
return { next: 1 };
},
});
await invalidNextStream.getReader().read();
console.log("noncallable next unexpectedly accepted");
} catch (error) {
console.log("noncallable next:", error.name);
}
}
export async function requestInitReadOrder(url) {
const names = [
"body", "cache", "credentials", "dispatcher", "duplex", "headers",
"integrity", "keepalive", "method", "mode", "priority", "redirect",
"referrer", "referrerPolicy", "signal", "window",
];
const reads = [];
const init = {};
for (const name of names) {
Object.defineProperty(init, name, {
get() {
reads.push(name);
return undefined;
},
});
}
await fetch(url, init);
console.log("request init reads:", reads.join(","));
}
export async function requestInitConversionOrder(url) {
const events = [];
const init = {
get method() {
events.push("get method");
return {
toString() {
events.push("convert method");
return "GET";
},
};
},
get redirect() {
events.push("get redirect");
return {
toString() {
events.push("convert redirect");
return "follow";
},
};
},
};
await fetch(url, init);
console.log("request init conversions:", events.join(","));
}
export async function inheritedRequestBodyMethodOverrides(url) {
for (const method of ["GET", "HEAD"]) {
const constructorInput = new Request(url, {
method: "POST",
body: "constructor body",
});
try {
new Request(constructorInput, { method });
console.log("request inherited body unexpectedly accepted:", method);
} catch (error) {
console.log("request inherited body:", method, error.name, error.message);
}
const fetchInput = new Request(url, { method: "POST", body: "fetch body" });
try {
await fetch(fetchInput, { method });
console.log("fetch inherited body unexpectedly accepted:", method);
} catch (error) {
console.log("fetch inherited body:", method, error.name, error.message);
}
}
}