// META: global=window,worker // META: script=../resources/utils.js promise_test(async () => { // t.add_cleanup doesn't work when Object.prototype.then is overwritten, so // these tests use add_completion_callback for cleanup instead. add_completion_callback(() => delete Object.prototype.then); const hello = new TextEncoder().encode('hello'); const bye = new TextEncoder().encode('bye'); const rs = new ReadableStream({ start(controller) { controller.enqueue(hello); controller.close(); } }); const resp = new Response(rs); Object.prototype.then = (onFulfilled) => { delete Object.prototype.then; onFulfilled({done: false, value: bye}); }; const text = await resp.text(); delete Object.prototype.then; assert_equals(text, 'hello', 'The value should be "hello".'); }, 'Attempt to inject {done: false, value: bye} via Object.prototype.then.'); promise_test(async (t) => { add_completion_callback(() => delete Object.prototype.then); const hello = new TextEncoder().encode('hello'); const rs = new ReadableStream({ start(controller) { controller.enqueue(hello); controller.close(); } }); const resp = new Response(rs); Object.prototype.then = (onFulfilled) => { delete Object.prototype.then; onFulfilled({done: false, value: undefined}); }; const text = await resp.text(); delete Object.prototype.then; assert_equals(text, 'hello', 'The value should be "hello".'); }, 'Attempt to inject value: undefined via Object.prototype.then.'); promise_test(async (t) => { add_completion_callback(() => delete Object.prototype.then); const hello = new TextEncoder().encode('hello'); const rs = new ReadableStream({ start(controller) { controller.enqueue(hello); controller.close(); } }); const resp = new Response(rs); Object.prototype.then = (onFulfilled) => { delete Object.prototype.then; onFulfilled(undefined); }; const text = await resp.text(); delete Object.prototype.then; assert_equals(text, 'hello', 'The value should be "hello".'); }, 'Attempt to inject undefined via Object.prototype.then.'); promise_test(async (t) => { add_completion_callback(() => delete Object.prototype.then); const hello = new TextEncoder().encode('hello'); const rs = new ReadableStream({ start(controller) { controller.enqueue(hello); controller.close(); } }); const resp = new Response(rs); Object.prototype.then = (onFulfilled) => { delete Object.prototype.then; onFulfilled(8.2); }; const text = await resp.text(); delete Object.prototype.then; assert_equals(text, 'hello', 'The value should be "hello".'); }, 'Attempt to inject 8.2 via Object.prototype.then.'); promise_test(async () => { add_completion_callback(() => delete Object.prototype.then); const hello = new TextEncoder().encode('hello'); const bye = new TextEncoder().encode('bye'); const resp = new Response(hello); Object.prototype.then = (onFulfilled) => { delete Object.prototype.then; onFulfilled({done: false, value: bye}); }; const text = await resp.text(); delete Object.prototype.then; assert_equals(text, 'hello', 'The value should be "hello".'); }, 'intercepting arraybuffer to text conversion via Object.prototype.then ' + 'should not be possible'); promise_test(async () => { add_completion_callback(() => delete Object.prototype.then); const u8a123 = new Uint8Array([1, 2, 3]); const u8a456 = new Uint8Array([4, 5, 6]); const resp = new Response(u8a123); const writtenBytes = []; const ws = new WritableStream({ write(chunk) { writtenBytes.push(...Array.from(chunk)); } }); Object.prototype.then = (onFulfilled) => { delete Object.prototype.then; onFulfilled({done: false, value: u8a456}); }; await resp.body.pipeTo(ws); delete Object.prototype.then; assert_array_equals(writtenBytes, u8a123, 'The value should be [1, 2, 3]'); }, 'intercepting arraybuffer to body readable stream conversion via ' + 'Object.prototype.then should not be possible');