Compare commits

...

1 Commits

Author SHA1 Message Date
Meghan Denny
5ff6db0912 js: add inherits builtin for generic cross-realm instanceof 2025-01-10 18:19:45 -08:00
9 changed files with 54 additions and 5 deletions

View File

@@ -3609,6 +3609,7 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm)
GlobalPropertyInfo(builtinNames.TextEncoderStreamEncoderPrivateName(), JSTextEncoderStreamEncoderConstructor(), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | 0),
GlobalPropertyInfo(builtinNames.makeErrorWithCodePrivateName(), JSFunction::create(vm, this, 2, String(), jsFunctionMakeErrorWithCode, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(builtinNames.toClassPrivateName(), JSFunction::create(vm, this, 1, String(), jsFunctionToClass, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(builtinNames.inheritsPrivateName(), JSFunction::create(vm, this, 1, String(), jsFunctionInherits, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
};
addStaticGlobals(staticGlobals, std::size(staticGlobals));

View File

@@ -0,0 +1,4 @@
export default [
//
"Blob",
];

View File

@@ -19,6 +19,7 @@ import { getJS2NativeCPP, getJS2NativeZig } from "./generate-js2native";
import { cap, declareASCIILiteral, writeIfNotChanged } from "./helpers";
import { createInternalModuleRegistry } from "./internal-module-registry-scanner";
import { define } from "./replacements";
import jsclasses from "./../bun.js/bindings/js_classes";
const BASE = path.join(import.meta.dir, "../js");
const debug = process.argv[2] === "--debug=ON";
@@ -464,6 +465,10 @@ declare function $${code}(msg: string, ...args: any[]): ${name};
`;
}
for (const name of jsclasses) {
dts += `\ndeclare function $inherits${name}(value: any): boolean;`;
}
return dts;
})(),
);

View File

@@ -910,6 +910,7 @@ function renderStaticDecls(symbolName, typeName, fields, supportsObjectCreate =
return rows.join("\n");
}
function writeBarrier(symbolName, typeName, name, cacheName) {
return `
@@ -928,6 +929,7 @@ extern JSC_CALLCONV JSC::EncodedJSValue ${symbolName(typeName, name)}GetCachedVa
`.trim();
}
function renderFieldsImpl(
symbolName: (typeName: string, name: string) => string,
typeName: string,
@@ -1176,6 +1178,7 @@ JSC_DEFINE_HOST_FUNCTION(${symbolName(typeName, name)}Callback, (JSGlobalObject
return rows.map(a => a.trim()).join("\n");
}
function allCachedValues(obj: ClassDefinition) {
let values = (obj.values ?? []).slice().map(name => [name, `m_${name}`]);
for (const name in obj.proto) {
@@ -1193,6 +1196,7 @@ function allCachedValues(obj: ClassDefinition) {
return values;
}
var extraIncludes = [];
function generateClassHeader(typeName, obj: ClassDefinition) {
var { klass, proto, JSType = "ObjectType", values = [], callbacks = {}, zigOnly = false } = obj;
@@ -2101,6 +2105,9 @@ const GENERATED_CLASSES_HEADER = [
#include "root.h"
namespace Zig {
JSC_DEFINE_HOST_FUNCTION(jsFunctionInherits, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame));
}
#include "JSDOMWrapper.h"
@@ -2168,6 +2175,25 @@ const GENERATED_CLASSES_IMPL_FOOTER = `
`;
function jsInheritsCppImpl() {
return `
JSC_DEFINE_HOST_FUNCTION(Zig::jsFunctionInherits, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
auto id = callFrame->argument(0).toInt32(globalObject);
auto value = callFrame->argument(1);
auto cell = value.asCell();
switch (id) {
${classes
.map(v => v.name)
.toSorted()
.map((v, i) => ` case ${i}: return JSValue::encode(jsBoolean(cell->inherits<WebCore::JS${v}>()));`)
.join("\n")}
}
return JSValue::encode(jsBoolean(false));
}`;
}
function initLazyClasses(initLaterFunctions) {
return `
@@ -2342,6 +2368,7 @@ comptime {
`,
]);
if (!process.env.ONLY_ZIG) {
const allHeaders = classes.map(a => generateHeader(a.name, a));
await writeIfNotChanged(`${outBase}/ZigGeneratedClasses.h`, [
@@ -2360,7 +2387,9 @@ if (!process.env.ONLY_ZIG) {
allImpls.join("\n"),
writeCppSerializers(classes),
GENERATED_CLASSES_IMPL_FOOTER,
jsInheritsCppImpl(),
]);
await writeIfNotChanged(
`${outBase}/ZigGeneratedClasses+lazyStructureHeader.h`,
classes.map(a => generateLazyClassStructureHeader(a.name, a)).join("\n"),

View File

@@ -2,6 +2,7 @@ import { LoaderKeys } from "../api/schema";
import NodeErrors from "../bun.js/bindings/ErrorCode.ts";
import { sliceSourceCode } from "./builtin-parser";
import { registerNativeCall } from "./generate-js2native";
import jsclasses from "./../bun.js/bindings/js_classes";
// This is a list of extra syntax replacements to do. Kind of like macros
// These are only run on code itself, not string contents or comments.
@@ -21,6 +22,14 @@ for (let i = 0; i < NodeErrors.length; i++) {
});
}
for (let id = 0; id < jsclasses.length; id++) {
const name = jsclasses[id];
replacements.push({
from: new RegExp(`\\b\\__intrinsic__inherits${name}\\(`, "g"),
to: `$inherits(${id}, `,
});
}
// These rules are run on the entire file, including within strings.
export const globalReplacements: ReplacementRule[] = [
{

View File

@@ -115,6 +115,7 @@ using namespace JSC;
macro(inFlightCloseRequest) \
macro(inFlightWriteRequest) \
macro(initializeWith) \
macro(inherits) \
macro(internalModuleRegistry) \
macro(internalRequire) \
macro(internalStream) \

View File

@@ -433,7 +433,7 @@ function normalizePath(path) {
// This is mostly for import.meta.resolve()
// https://github.com/oven-sh/bun/issues/10304
path = Bun.fileURLToPath(path as URL);
} else if (path instanceof Blob) {
} else if ($inheritsBlob(path)) {
// must be a Bun.file() blob
// https://discord.com/channels/876711213126520882/1230114905898614794/1230114905898614794
path = path.name;

View File

@@ -112,11 +112,11 @@ const kfakeSocket = Symbol("kfakeSocket");
const kEmptyBuffer = Buffer.alloc(0);
function isValidTLSArray(obj) {
if (typeof obj === "string" || isTypedArray(obj) || obj instanceof ArrayBuffer || obj instanceof Blob) return true;
if (typeof obj === "string" || isTypedArray(obj) || obj instanceof ArrayBuffer || $inheritsBlob(obj)) return true;
if (Array.isArray(obj)) {
for (var i = 0; i < obj.length; i++) {
const item = obj[i];
if (typeof item !== "string" && !isTypedArray(item) && !(item instanceof ArrayBuffer) && !(item instanceof Blob))
if (typeof item !== "string" && !isTypedArray(item) && !(item instanceof ArrayBuffer) && !$inheritsBlob(item))
return false;
}
return true;

View File

@@ -38,11 +38,11 @@ function parseCertString() {
const rejectUnauthorizedDefault =
process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0" && process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "false";
function isValidTLSArray(obj) {
if (typeof obj === "string" || isTypedArray(obj) || obj instanceof ArrayBuffer || obj instanceof Blob) return true;
if (typeof obj === "string" || isTypedArray(obj) || obj instanceof ArrayBuffer || $inheritsBlob(obj)) return true;
if (Array.isArray(obj)) {
for (var i = 0; i < obj.length; i++) {
const item = obj[i];
if (typeof item !== "string" && !isTypedArray(item) && !(item instanceof ArrayBuffer) && !(item instanceof Blob))
if (typeof item !== "string" && !isTypedArray(item) && !(item instanceof ArrayBuffer) && !$inheritsBlob(item))
return false;
}
return true;