|
|
|
|
@@ -8,13 +8,19 @@
|
|
|
|
|
// library, instead of RegExp hacks.
|
|
|
|
|
//
|
|
|
|
|
// For explanation on this, please nag @paperdave to write documentation on how everything works.
|
|
|
|
|
//
|
|
|
|
|
// The output is intended to be similar to what WebCore does internally with a couple differences:
|
|
|
|
|
//
|
|
|
|
|
// - We concatenate all the sources into one big string, which then createsa
|
|
|
|
|
// single JSC::SourceProvider and pass start/end positions to each function's
|
|
|
|
|
// JSC::SourceCode. JSC does this, but WebCore does not seem to.
|
|
|
|
|
import { readdirSync, rmSync } from "fs";
|
|
|
|
|
import path from "path";
|
|
|
|
|
import { sliceSourceCode } from "./builtin-parser";
|
|
|
|
|
import { applyGlobalReplacements, define } from "./replacements";
|
|
|
|
|
import { cap, fmtCPPCharArray, low, writeIfNotChanged } from "./helpers";
|
|
|
|
|
import { createAssertClientJS, createLogClientJS } from "./client-js";
|
|
|
|
|
import { getJS2NativeDTS } from "./generate-js2native";
|
|
|
|
|
import { addCPPCharArray, cap, low, writeIfNotChanged } from "./helpers";
|
|
|
|
|
import { applyGlobalReplacements, define } from "./replacements";
|
|
|
|
|
|
|
|
|
|
const PARALLEL = false;
|
|
|
|
|
const KEEP_TMP = true;
|
|
|
|
|
@@ -52,6 +58,7 @@ interface BundledBuiltin {
|
|
|
|
|
source: string;
|
|
|
|
|
params: string[];
|
|
|
|
|
visibility: string;
|
|
|
|
|
sourceOffset: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -228,6 +235,10 @@ $$capture_start$$(${fn.async ? "async " : ""}${
|
|
|
|
|
constructKind: fn.directives.ConstructKind ?? "None",
|
|
|
|
|
isLinkTimeConstant: !!fn.directives.linkTimeConstant,
|
|
|
|
|
intrinsic: fn.directives.intrinsic ?? "NoIntrinsic",
|
|
|
|
|
|
|
|
|
|
// Not known yet.
|
|
|
|
|
sourceOffset: 0,
|
|
|
|
|
|
|
|
|
|
overriddenName: fn.directives.getter
|
|
|
|
|
? `"get ${fn.name}"_s`
|
|
|
|
|
: fn.directives.overriddenName
|
|
|
|
|
@@ -275,6 +286,34 @@ export async function bundleBuiltinFunctions({ requireTransformer }: BundleBuilt
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let combinedSourceCodeChars = "";
|
|
|
|
|
let combinedSourceCodeLength = 0;
|
|
|
|
|
// Compute source offsets
|
|
|
|
|
{
|
|
|
|
|
for (const { basename, functions } of files) {
|
|
|
|
|
for (const fn of functions) {
|
|
|
|
|
fn.sourceOffset = combinedSourceCodeLength;
|
|
|
|
|
combinedSourceCodeLength += fn.source.length;
|
|
|
|
|
if (combinedSourceCodeChars && !combinedSourceCodeChars.endsWith(",")) {
|
|
|
|
|
combinedSourceCodeChars += ",";
|
|
|
|
|
}
|
|
|
|
|
combinedSourceCodeChars += addCPPCharArray(fn.source, false);
|
|
|
|
|
|
|
|
|
|
// If you want to see the individual function sources:
|
|
|
|
|
// if (true) {
|
|
|
|
|
// Bun.write(CODEGEN_DIR + "/functions/" + low(basename) + cap(fn.name) + ".js", fn.source + "\n");
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let additionalPrivateNames = new Set();
|
|
|
|
|
|
|
|
|
|
function privateName(name) {
|
|
|
|
|
additionalPrivateNames.add(name);
|
|
|
|
|
return "builtinNames." + name + "PrivateName()";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// C++ codegen
|
|
|
|
|
let bundledCPP = `// Generated by ${import.meta.path}
|
|
|
|
|
namespace Zig { class GlobalObject; }
|
|
|
|
|
@@ -283,48 +322,78 @@ export async function bundleBuiltinFunctions({ requireTransformer }: BundleBuilt
|
|
|
|
|
#include "JSDOMGlobalObject.h"
|
|
|
|
|
#include "WebCoreJSClientData.h"
|
|
|
|
|
#include <JavaScriptCore/JSObjectInlines.h>
|
|
|
|
|
|
|
|
|
|
#include "BunBuiltinNames.h"
|
|
|
|
|
|
|
|
|
|
namespace WebCore {
|
|
|
|
|
|
|
|
|
|
static const LChar combinedSourceCodeBuffer[${combinedSourceCodeLength + 1}] = { ${combinedSourceCodeChars}, 0 };
|
|
|
|
|
static const std::span<const LChar> internalCombinedSource = { combinedSourceCodeBuffer, ${combinedSourceCodeLength} };
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
for (const { basename, functions } of files) {
|
|
|
|
|
bundledCPP += `/* ${basename}.ts */\n`;
|
|
|
|
|
bundledCPP += `
|
|
|
|
|
#pragma mark ${basename}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const lowerBasename = low(basename);
|
|
|
|
|
for (const fn of functions) {
|
|
|
|
|
const [code, count] = fmtCPPCharArray(fn.source, true);
|
|
|
|
|
const name = `${lowerBasename}${cap(fn.name)}Code`;
|
|
|
|
|
bundledCPP += `// ${fn.name}
|
|
|
|
|
const JSC::ConstructAbility s_${name}ConstructAbility = JSC::ConstructAbility::${fn.constructAbility};
|
|
|
|
|
const JSC::InlineAttribute s_${name}InlineAttribute = JSC::InlineAttribute::${
|
|
|
|
|
fn.directives.alwaysInline ? "Always" : "None"
|
|
|
|
|
};
|
|
|
|
|
const JSC::ConstructorKind s_${name}ConstructorKind = JSC::ConstructorKind::${fn.constructKind};
|
|
|
|
|
const JSC::ImplementationVisibility s_${name}ImplementationVisibility = JSC::ImplementationVisibility::${
|
|
|
|
|
fn.visibility
|
|
|
|
|
};
|
|
|
|
|
const int s_${name}Length = ${fn.source.length};
|
|
|
|
|
const JSC::Intrinsic s_${name}Intrinsic = JSC::NoIntrinsic;
|
|
|
|
|
const char s_${name}Bytes[${count}] = ${code};
|
|
|
|
|
const char* s_${name} = s_${name}Bytes;
|
|
|
|
|
`;
|
|
|
|
|
const name = `${basename}${cap(fn.name)}`;
|
|
|
|
|
bundledCPP += `
|
|
|
|
|
JSC::FunctionExecutable* ${lowerBasename}${cap(fn.name)}CodeGenerator(JSC::VM& vm)
|
|
|
|
|
{
|
|
|
|
|
auto &builtins = static_cast<JSVMClientData*>(vm.clientData)->builtinFunctions().${lowerBasename}Builtins();
|
|
|
|
|
auto *executable = builtins.${lowerBasename}${cap(fn.name)}CodeExecutable();
|
|
|
|
|
return executable->link(vm, nullptr, builtins.${lowerBasename}${cap(fn.name)}CodeSource(), std::nullopt, JSC::NoIntrinsic);
|
|
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
bundledCPP += `#define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\
|
|
|
|
|
JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \\
|
|
|
|
|
{\\
|
|
|
|
|
JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \\
|
|
|
|
|
return clientData->builtinFunctions().${lowerBasename}Builtins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().${lowerBasename}Builtins().codeName##Source(), std::nullopt, s_##codeName##Intrinsic); \\
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const initializeSourceCodeFn = (fn: BundledBuiltin, basename: string) => {
|
|
|
|
|
const name = `${low(basename)}${cap(fn.name)}CodeSource`;
|
|
|
|
|
return `m_${name}(SourceCode(sourceProvider.copyRef(), ${fn.sourceOffset}, ${fn.source.length + fn.sourceOffset}, 1, 1))`;
|
|
|
|
|
};
|
|
|
|
|
for (const { basename, internal, functions } of files) {
|
|
|
|
|
bundledCPP += `
|
|
|
|
|
#pragma mark ${basename}
|
|
|
|
|
|
|
|
|
|
${basename}BuiltinsWrapper::${basename}BuiltinsWrapper(JSC::VM& vm, RefPtr<JSC::SourceProvider> sourceProvider, BunBuiltinNames &builtinNames)
|
|
|
|
|
: m_vm(vm)`;
|
|
|
|
|
|
|
|
|
|
if (internal) {
|
|
|
|
|
bundledCPP += `, ${functions.map(fn => `m_${fn.name}PrivateName(${privateName(fn.name)})`).join(",\n ")}`;
|
|
|
|
|
}
|
|
|
|
|
WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
|
|
|
|
|
#undef DEFINE_BUILTIN_GENERATOR
|
|
|
|
|
|
|
|
|
|
`;
|
|
|
|
|
bundledCPP += `, ${functions.map(fn => initializeSourceCodeFn(fn, basename)).join(",\n ")} {}
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bundledCPP += `
|
|
|
|
|
RefPtr<JSC::SourceProvider> createBuiltinsSourceProvider() {
|
|
|
|
|
return JSC::StringSourceProvider::create(StringImpl::createWithoutCopying(internalCombinedSource), SourceOrigin(), String(), SourceTaintedOrigin());
|
|
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
bundledCPP += `
|
|
|
|
|
JSBuiltinFunctions::JSBuiltinFunctions(JSC::VM& vm, RefPtr<JSC::SourceProvider> provider, BunBuiltinNames& builtinNames) : m_vm(vm),
|
|
|
|
|
${files.map(({ basename }) => `m_${low(basename)}Builtins(vm, provider, builtinNames)`).join(", ")}
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
void JSBuiltinFunctions::exportNames() {
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
for (const { basename, internal } of files) {
|
|
|
|
|
if (internal) {
|
|
|
|
|
bundledCPP += ` m_${low(basename)}Builtins.exportNames();\n`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bundledCPP += `
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
bundledCPP += `
|
|
|
|
|
|
|
|
|
|
JSBuiltinInternalFunctions::JSBuiltinInternalFunctions(JSC::VM& vm)
|
|
|
|
|
: m_vm(vm)
|
|
|
|
|
JSBuiltinInternalFunctions::JSBuiltinInternalFunctions(JSC::VM& vm) : m_vm(vm)
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
for (const { basename, internal } of files) {
|
|
|
|
|
@@ -333,10 +402,9 @@ export async function bundleBuiltinFunctions({ requireTransformer }: BundleBuilt
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bundledCPP += `
|
|
|
|
|
{
|
|
|
|
|
UNUSED_PARAM(vm);
|
|
|
|
|
}
|
|
|
|
|
bundledCPP += `{
|
|
|
|
|
UNUSED_PARAM(vm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename Visitor>
|
|
|
|
|
void JSBuiltinInternalFunctions::visit(Visitor& visitor)
|
|
|
|
|
@@ -417,12 +485,10 @@ export async function bundleBuiltinFunctions({ requireTransformer }: BundleBuilt
|
|
|
|
|
const name = `${lowerBasename}${cap(fn.name)}Code`;
|
|
|
|
|
bundledHeader += `// ${fn.name}
|
|
|
|
|
#define WEBCORE_BUILTIN_${basename.toUpperCase()}_${fn.name.toUpperCase()} 1
|
|
|
|
|
extern const char* s_${name};
|
|
|
|
|
extern const int s_${name}Length;
|
|
|
|
|
extern const JSC::ConstructAbility s_${name}ConstructAbility;
|
|
|
|
|
extern const JSC::InlineAttribute s_${name}InlineAttribute;
|
|
|
|
|
extern const JSC::ConstructorKind s_${name}ConstructorKind;
|
|
|
|
|
extern const JSC::ImplementationVisibility s_${name}ImplementationVisibility;
|
|
|
|
|
static constexpr JSC::ConstructAbility s_${name}ConstructAbility = JSC::ConstructAbility::${fn.constructAbility};
|
|
|
|
|
static constexpr JSC::InlineAttribute s_${name}InlineAttribute = JSC::InlineAttribute::${fn.directives.alwaysInline ? "Always" : "None"};
|
|
|
|
|
static constexpr JSC::ConstructorKind s_${name}ConstructorKind = JSC::ConstructorKind::${fn.constructKind};
|
|
|
|
|
static constexpr JSC::ImplementationVisibility s_${name}ImplementationVisibility = JSC::ImplementationVisibility::${fn.visibility};
|
|
|
|
|
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
@@ -450,14 +516,7 @@ export async function bundleBuiltinFunctions({ requireTransformer }: BundleBuilt
|
|
|
|
|
|
|
|
|
|
class ${basename}BuiltinsWrapper : private JSC::WeakHandleOwner {
|
|
|
|
|
public:
|
|
|
|
|
explicit ${basename}BuiltinsWrapper(JSC::VM& vm)
|
|
|
|
|
: m_vm(vm)
|
|
|
|
|
WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(INITIALIZE_BUILTIN_NAMES)
|
|
|
|
|
#define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, overriddenName, length) , m_##name##Source(JSC::makeSource(StringImpl::createWithoutCopying({reinterpret_cast<const LChar*>(s_##name), static_cast<size_t>(length)}), { }, JSC::SourceTaintedOrigin::Untainted))
|
|
|
|
|
WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(INITIALIZE_BUILTIN_SOURCE_MEMBERS)
|
|
|
|
|
#undef INITIALIZE_BUILTIN_SOURCE_MEMBERS
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
explicit ${basename}BuiltinsWrapper(JSC::VM& vm, RefPtr<JSC::SourceProvider> sourceProvider, BunBuiltinNames &builtinNames);
|
|
|
|
|
|
|
|
|
|
#define EXPOSE_BUILTIN_EXECUTABLES(name, functionName, overriddenName, length) \\
|
|
|
|
|
JSC::UnlinkedFunctionExecutable* name##Executable(); \\
|
|
|
|
|
@@ -544,25 +603,9 @@ export async function bundleBuiltinFunctions({ requireTransformer }: BundleBuilt
|
|
|
|
|
}
|
|
|
|
|
bundledHeader += `class JSBuiltinFunctions {
|
|
|
|
|
public:
|
|
|
|
|
explicit JSBuiltinFunctions(JSC::VM& vm)
|
|
|
|
|
: m_vm(vm)
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
for (const { basename } of files) {
|
|
|
|
|
bundledHeader += ` , m_${low(basename)}Builtins(m_vm)\n`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bundledHeader += `
|
|
|
|
|
{
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
for (const { basename, internal } of files) {
|
|
|
|
|
if (internal) {
|
|
|
|
|
bundledHeader += ` m_${low(basename)}Builtins.exportNames();\n`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bundledHeader += ` }
|
|
|
|
|
explicit JSBuiltinFunctions(JSC::VM& vm, RefPtr<JSC::SourceProvider> provider, BunBuiltinNames &builtinNames);
|
|
|
|
|
void exportNames();
|
|
|
|
|
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
for (const { basename } of files) {
|
|
|
|
|
@@ -613,7 +656,53 @@ export async function bundleBuiltinFunctions({ requireTransformer }: BundleBuilt
|
|
|
|
|
|
|
|
|
|
} // namespace WebCore
|
|
|
|
|
`;
|
|
|
|
|
// Handle builtin names
|
|
|
|
|
{
|
|
|
|
|
const BunBuiltinNamesHeader = require("fs").readFileSync(
|
|
|
|
|
path.join(import.meta.dir, "../js/builtins/BunBuiltinNames.h"),
|
|
|
|
|
"utf8",
|
|
|
|
|
);
|
|
|
|
|
let definedBuiltinNamesStartI = BunBuiltinNamesHeader.indexOf(
|
|
|
|
|
"#define BUN_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME",
|
|
|
|
|
);
|
|
|
|
|
let definedBuiltinNamesMacroEndI = BunBuiltinNamesHeader.indexOf(
|
|
|
|
|
"--- END of BUN_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME ---",
|
|
|
|
|
);
|
|
|
|
|
const definedBuiltinNames = BunBuiltinNamesHeader.slice(definedBuiltinNamesStartI, definedBuiltinNamesMacroEndI)
|
|
|
|
|
.split("\n")
|
|
|
|
|
.map(x => x.trim())
|
|
|
|
|
.filter(x => x.startsWith("macro("))
|
|
|
|
|
.map(x => x.slice(x.indexOf("(") + 1, x.indexOf(")")))
|
|
|
|
|
.map(x => x.trim())
|
|
|
|
|
.sort();
|
|
|
|
|
|
|
|
|
|
const uniqueDefinedBuiltinNames = new Set();
|
|
|
|
|
for (let name of definedBuiltinNames) {
|
|
|
|
|
const prevSize = uniqueDefinedBuiltinNames.size;
|
|
|
|
|
uniqueDefinedBuiltinNames.add(name);
|
|
|
|
|
if (uniqueDefinedBuiltinNames.size === prevSize) {
|
|
|
|
|
throw new Error(`Duplicate private name "${name}" in BunBuiltinNames.h`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (let additionalPrivateName of additionalPrivateNames) {
|
|
|
|
|
if (uniqueDefinedBuiltinNames.has(additionalPrivateName)) {
|
|
|
|
|
additionalPrivateNames.delete(additionalPrivateName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let additionalPrivateNamesHeader = `// Generated by ${import.meta.path}
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#ifndef BUN_ADDITIONAL_BUILTIN_NAMES
|
|
|
|
|
#define BUN_ADDITIONAL_BUILTIN_NAMES(macro) \\
|
|
|
|
|
${Array.from(additionalPrivateNames)
|
|
|
|
|
.map(x => `macro(${x})`)
|
|
|
|
|
.join(" \\\n ")}
|
|
|
|
|
#endif
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
writeIfNotChanged(path.join(CODEGEN_DIR, "BunBuiltinNames+extras.h"), additionalPrivateNamesHeader);
|
|
|
|
|
}
|
|
|
|
|
writeIfNotChanged(path.join(CODEGEN_DIR, "WebCoreJSBuiltins.h"), bundledHeader);
|
|
|
|
|
writeIfNotChanged(path.join(CODEGEN_DIR, "WebCoreJSBuiltins.cpp"), bundledCPP);
|
|
|
|
|
|
|
|
|
|
|