node-fetch polyfill shouldn't break when web globals are overriden (#12634)

This commit is contained in:
Jarred Sumner
2024-07-17 18:57:03 -07:00
committed by GitHub
parent ecf5aea071
commit cc42052039
6 changed files with 88 additions and 8 deletions

View File

@@ -0,0 +1,50 @@
#include "root.h"
#include "JSDOMGlobalObjectInlines.h"
#include "ZigGlobalObject.h"
#include "JSFetchHeaders.h"
#include "JSDOMFormData.h"
#include "JavaScriptCore/ObjectConstructor.h"
#include "helpers.h"
#include "BunClientData.h"
#include "JavaScriptCore/AggregateError.h"
#include "JavaScriptCore/JSFunction.h"
#include "JSDOMFile.h"
namespace Bun {
using namespace JSC;
using namespace WebCore;
// Ensure overriding globals doesn't impact usages.
JSC::JSValue createNodeFetchInternalBinding(Zig::GlobalObject* globalObject)
{
auto& vm = globalObject->vm();
auto* obj = constructEmptyObject(globalObject);
obj->putDirectIndex(
globalObject, 0,
globalObject->JSResponseConstructor());
obj->putDirectIndex(
globalObject, 1,
globalObject->JSRequestConstructor());
obj->putDirectIndex(
globalObject, 2,
globalObject->JSBlobConstructor());
obj->putDirectIndex(
globalObject, 3,
WebCore::JSFetchHeaders::getConstructor(vm, globalObject));
obj->putDirectIndex(
globalObject, 4,
WebCore::JSDOMFormData::getConstructor(vm, globalObject));
obj->putDirectIndex(
globalObject, 5,
globalObject->JSDOMFileConstructor());
return obj;
}
}

View File

@@ -0,0 +1,7 @@
#include "config.h"
namespace Bun {
JSC::JSValue createNodeFetchInternalBinding(Zig::GlobalObject*);
}

View File

@@ -1,13 +1,13 @@
import type * as s from "stream";
const {
Headers: WebHeaders,
Request: WebRequest,
Response: WebResponse,
Blob,
File = Blob,
FormData,
} = globalThis as any;
// Users may override the global fetch implementation, so we need to ensure these are the originals.
const bindings = $cpp("NodeFetch.cpp", "createNodeFetchInternalBinding");
const WebResponse: typeof globalThis.Response = bindings[0];
const WebRequest: typeof globalThis.Request = bindings[1];
const Blob: typeof globalThis.Blob = bindings[2];
const WebHeaders: typeof globalThis.Headers = bindings[3];
const FormData: typeof globalThis.FormData = bindings[4];
const File: typeof globalThis.File = bindings[5];
const nativeFetch = Bun.fetch;
// node-fetch extends from URLSearchParams in their implementation...

Binary file not shown.

View File

@@ -0,0 +1,20 @@
import { test, expect } from "bun:test";
test("fetch, Response, Request can be overriden", async () => {
const { Response, Request } = globalThis;
globalThis.Response = class BadResponse {};
globalThis.Request = class BadRequest {};
globalThis.fetch = function badFetch() {};
const fetch = require("node-fetch").fetch;
using server = Bun.serve({
port: 0,
async fetch(req) {
return new Response("Hello, World!");
},
});
const response = await fetch(server.url);
expect(response).toBeInstanceOf(Response);
});

View File

@@ -61,5 +61,8 @@
"private": true,
"scripts": {
"typecheck": "tsc --noEmit"
},
"resolutions": {
"react": "../node_modules/react"
}
}