diff --git a/lib/internal/bootstrap/web/exposed-window-or-worker.js b/lib/internal/bootstrap/web/exposed-window-or-worker.js index db5d449dd79be4..7733f711bc6daf 100644 --- a/lib/internal/bootstrap/web/exposed-window-or-worker.js +++ b/lib/internal/bootstrap/web/exposed-window-or-worker.js @@ -57,32 +57,21 @@ defineReplaceableLazyAttribute(globalThis, 'perf_hooks', ['performance']); const { installObjectURLMethods } = require('internal/url'); installObjectURLMethods(); -{ - // https://fetch.spec.whatwg.org/#fetch-method - function set(value) { - ObjectDefineProperty(globalThis, 'fetch', { - __proto__: null, - writable: true, - value, - }); - } - ObjectDefineProperty(globalThis, 'fetch', { - __proto__: null, - configurable: true, - enumerable: true, - set, - get() { - function fetch(input, init = undefined) { - // Loading undici alone lead to promises which breaks lots of tests so we - // have to load it really lazily for now. - const { fetch: impl } = require('internal/deps/undici/undici'); - return impl(input, init); - } - set(fetch); - return fetch; - }, - }); -} +let fetchImpl; +// https://fetch.spec.whatwg.org/#fetch-method +ObjectDefineProperty(globalThis, 'fetch', { + __proto__: null, + configurable: true, + enumerable: true, + writable: true, + value: function value(input, init = undefined) { + if (!fetchImpl) { // Implement lazy loading of undici module for fetch function + const undiciModule = require('internal/deps/undici/undici'); + fetchImpl = undiciModule.fetch; + } + return fetchImpl(input, init); + }, +}); // https://xhr.spec.whatwg.org/#interface-formdata // https://fetch.spec.whatwg.org/#headers-class diff --git a/test/parallel/test-fetch-mock.js b/test/parallel/test-fetch-mock.js new file mode 100644 index 00000000000000..b457745f1c4c90 --- /dev/null +++ b/test/parallel/test-fetch-mock.js @@ -0,0 +1,20 @@ +'use strict'; +require('../common'); +const { mock, test } = require('node:test'); +const assert = require('node:assert'); + +test('should correctly stub globalThis.fetch', async () => { + const customFetch = async (url) => { + return { + text: async () => 'foo', + }; + }; + + mock.method(globalThis, 'fetch', customFetch); + + const response = await globalThis.fetch('some-url'); + const text = await response.text(); + + assert.strictEqual(text, 'foo'); + mock.restoreAll(); +});