mirror of
https://github.com/oven-sh/bun
synced 2026-02-05 00:18:53 +00:00
Compare commits
109 Commits
ciro/fix-p
...
don/fix/na
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a634127dca | ||
|
|
baee1c10d3 | ||
|
|
6353fa4806 | ||
|
|
f17ce2b756 | ||
|
|
c445cdaf13 | ||
|
|
ea65a2ad48 | ||
|
|
eb145870cb | ||
|
|
2ea879e29b | ||
|
|
a127f1ab59 | ||
|
|
506ea28b36 | ||
|
|
23ba9af43c | ||
|
|
1bb1f59b9e | ||
|
|
7403088c3b | ||
|
|
2b97d61deb | ||
|
|
e22c6c5dbe | ||
|
|
bdccbbc828 | ||
|
|
0b6d468b74 | ||
|
|
251c2b7d06 | ||
|
|
321500c625 | ||
|
|
3a231a62b4 | ||
|
|
7adb2b9502 | ||
|
|
c2edbe848f | ||
|
|
02d4534561 | ||
|
|
cfebfe7731 | ||
|
|
14b93e2ab9 | ||
|
|
9755e02e17 | ||
|
|
a23c11e381 | ||
|
|
d814f3e6d8 | ||
|
|
4a7e56b532 | ||
|
|
fb0f28aab9 | ||
|
|
ba8573494a | ||
|
|
14164920b5 | ||
|
|
2644bad5d4 | ||
|
|
584db03a74 | ||
|
|
f912e0abc4 | ||
|
|
6e887c8e45 | ||
|
|
374195ea30 | ||
|
|
0da7025fb0 | ||
|
|
180500181f | ||
|
|
c970922456 | ||
|
|
93af28751f | ||
|
|
4d2a8650e5 | ||
|
|
146ec7791b | ||
|
|
253faed1cf | ||
|
|
1fe2c3b426 | ||
|
|
fad856c03c | ||
|
|
2770ecad5c | ||
|
|
1684c6246d | ||
|
|
d2cdb5031d | ||
|
|
0c8658b350 | ||
|
|
fc7bd569f5 | ||
|
|
5620a7dfac | ||
|
|
1ccc13ecf7 | ||
|
|
4d004b90ca | ||
|
|
dcf0b719a5 | ||
|
|
8634ee3065 | ||
|
|
1819b01932 | ||
|
|
b39d84690c | ||
|
|
d63fe71a6d | ||
|
|
fa55ca31e1 | ||
|
|
a8d159da22 | ||
|
|
0861c03b37 | ||
|
|
7a918d24a7 | ||
|
|
7bef462257 | ||
|
|
9cfa3a558b | ||
|
|
97ae35dfde | ||
|
|
1ea14f483c | ||
|
|
ec751159c6 | ||
|
|
fa502506e5 | ||
|
|
06b16fc11e | ||
|
|
00a5c4af5a | ||
|
|
cc68f4f025 | ||
|
|
aac951bd47 | ||
|
|
34419c5f0d | ||
|
|
1595b1cc2b | ||
|
|
5366c9db33 | ||
|
|
87281b6d48 | ||
|
|
43fd9326ba | ||
|
|
26d3688e53 | ||
|
|
1ddf3fc097 | ||
|
|
73bcff9d01 | ||
|
|
c1708ea6ab | ||
|
|
447121235c | ||
|
|
1fa42d81af | ||
|
|
22a23add8d | ||
|
|
d4ce421982 | ||
|
|
322098fa54 | ||
|
|
9acb72d2ad | ||
|
|
25f6cbd471 | ||
|
|
b098c9ed89 | ||
|
|
212944a5b6 | ||
|
|
61bf221510 | ||
|
|
891057cd20 | ||
|
|
c51196a8dc | ||
|
|
f6ec0da125 | ||
|
|
b59b793a32 | ||
|
|
3a4df79a64 | ||
|
|
91f2be57b5 | ||
|
|
b612bc4f47 | ||
|
|
f454c27365 | ||
|
|
892764ec43 | ||
|
|
574a41b03f | ||
|
|
c8f8d2c0bb | ||
|
|
29839737df | ||
|
|
4d5ece3f63 | ||
|
|
93a89e5866 | ||
|
|
676e8d1632 | ||
|
|
5633ec4334 | ||
|
|
160bf9d563 |
@@ -391,6 +391,8 @@ function getBuildEnv(target, options) {
|
||||
ENABLE_ASSERTIONS: release ? "OFF" : "ON",
|
||||
ENABLE_LOGS: release ? "OFF" : "ON",
|
||||
ABI: abi === "musl" ? "musl" : undefined,
|
||||
|
||||
CMAKE_TLS_VERIFY: "0",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
3
.clangd
3
.clangd
@@ -6,6 +6,3 @@ CompileFlags:
|
||||
|
||||
Diagnostics:
|
||||
UnusedIncludes: None
|
||||
|
||||
HeaderInsertion:
|
||||
IncludeBlocks: Preserve # Do not auto-include headers.
|
||||
|
||||
378
.cursor/rules/javascriptcore-class.mdc
Normal file
378
.cursor/rules/javascriptcore-class.mdc
Normal file
@@ -0,0 +1,378 @@
|
||||
---
|
||||
description: JavaScript class implemented in C++
|
||||
globs: *.cpp
|
||||
---
|
||||
|
||||
# Implementing JavaScript classes in C++
|
||||
|
||||
If there is a publicly accessible Constructor and Prototype, then there are 3 classes:
|
||||
|
||||
- IF there are C++ class members we need a destructor, so `class Foo : public JSC::DestructibleObject`, if no C++ class fields (only JS properties) then we don't need a class at all usually. We can instead use JSC::constructEmptyObject(vm, structure) and `putDirectOffset` like in [NodeFSBinding.cpp](mdc:src/bun.js/bindings/NodeFSBinding.cpp).
|
||||
- class FooPrototype : public JSC::JSNonFinalObject
|
||||
- class FooConstructor : public JSC::InternalFunction
|
||||
|
||||
If there is no publicly accessible Constructor, just the Prototype and the class is necessary. In some cases, we can avoid the prototype entirely (but that's rare).
|
||||
|
||||
If there are C++ fields on the Foo class, the Foo class will need an iso subspace added to [DOMClientIsoSubspaces.h](mdc:src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h) and [DOMIsoSubspaces.h](mdc:src/bun.js/bindings/webcore/DOMIsoSubspaces.h). Prototype and Constructor do not need subspaces.
|
||||
|
||||
Usually you'll need to #include "root.h" at the top of C++ files or you'll get lint errors.
|
||||
|
||||
Generally, defining the subspace looks like this:
|
||||
```c++
|
||||
|
||||
class Foo : public JSC::DestructibleObject {
|
||||
|
||||
// ...
|
||||
|
||||
template<typename MyClassT, JSC::SubspaceAccess mode>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
|
||||
return nullptr;
|
||||
return WebCore::subspaceForImpl<MyClassT, WebCore::UseCustomHeapCellType::No>(
|
||||
vm,
|
||||
[](auto& spaces) { return spaces.m_clientSubspaceFor${MyClassT}.get(); },
|
||||
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceFor${MyClassT} = std::forward<decltype(space)>(space); },
|
||||
[](auto& spaces) { return spaces.m_subspaceFo${MyClassT}.get(); },
|
||||
[](auto& spaces, auto&& space) { spaces.m_subspaceFor${MyClassT} = std::forward<decltype(space)>(space); });
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
It's better to put it in the .cpp file instead of the .h file, when possible.
|
||||
|
||||
## Defining properties
|
||||
|
||||
Define properties on the prototype. Use a const HashTableValues like this:
|
||||
```C++
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckEmail);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckHost);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckIP);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckIssued);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckPrivateKey);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncToJSON);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncToLegacyObject);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncToString);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncVerify);
|
||||
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_ca);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint256);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint512);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_subject);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_subjectAltName);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_infoAccess);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_keyUsage);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_issuer);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_issuerCertificate);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_publicKey);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_raw);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_serialNumber);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validFrom);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validTo);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validFromDate);
|
||||
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validToDate);
|
||||
|
||||
static const HashTableValue JSX509CertificatePrototypeTableValues[] = {
|
||||
{ "ca"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_ca, 0 } },
|
||||
{ "checkEmail"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckEmail, 2 } },
|
||||
{ "checkHost"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckHost, 2 } },
|
||||
{ "checkIP"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckIP, 1 } },
|
||||
{ "checkIssued"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckIssued, 1 } },
|
||||
{ "checkPrivateKey"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckPrivateKey, 1 } },
|
||||
{ "fingerprint"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_fingerprint, 0 } },
|
||||
{ "fingerprint256"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_fingerprint256, 0 } },
|
||||
{ "fingerprint512"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_fingerprint512, 0 } },
|
||||
{ "infoAccess"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_infoAccess, 0 } },
|
||||
{ "issuer"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_issuer, 0 } },
|
||||
{ "issuerCertificate"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_issuerCertificate, 0 } },
|
||||
{ "keyUsage"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_keyUsage, 0 } },
|
||||
{ "publicKey"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_publicKey, 0 } },
|
||||
{ "raw"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_raw, 0 } },
|
||||
{ "serialNumber"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_serialNumber, 0 } },
|
||||
{ "subject"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_subject, 0 } },
|
||||
{ "subjectAltName"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_subjectAltName, 0 } },
|
||||
{ "toJSON"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncToJSON, 0 } },
|
||||
{ "toLegacyObject"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncToLegacyObject, 0 } },
|
||||
{ "toString"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncToString, 0 } },
|
||||
{ "validFrom"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validFrom, 0 } },
|
||||
{ "validFromDate"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessorOrValue), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validFromDate, 0 } },
|
||||
{ "validTo"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validTo, 0 } },
|
||||
{ "validToDate"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessorOrValue), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validToDate, 0 } },
|
||||
{ "verify"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncVerify, 1 } },
|
||||
};
|
||||
```
|
||||
|
||||
### Creating a prototype class
|
||||
|
||||
Follow a pattern like this:
|
||||
|
||||
```c++
|
||||
class JSX509CertificatePrototype final : public JSC::JSNonFinalObject {
|
||||
public:
|
||||
using Base = JSC::JSNonFinalObject;
|
||||
static constexpr unsigned StructureFlags = Base::StructureFlags;
|
||||
|
||||
static JSX509CertificatePrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
|
||||
{
|
||||
JSX509CertificatePrototype* prototype = new (NotNull, allocateCell<JSX509CertificatePrototype>(vm)) JSX509CertificatePrototype(vm, structure);
|
||||
prototype->finishCreation(vm);
|
||||
return prototype;
|
||||
}
|
||||
|
||||
template<typename, JSC::SubspaceAccess>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
return &vm.plainObjectSpace();
|
||||
}
|
||||
|
||||
DECLARE_INFO;
|
||||
|
||||
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
|
||||
{
|
||||
auto* structure = JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
|
||||
structure->setMayBePrototype(true);
|
||||
return structure;
|
||||
}
|
||||
|
||||
private:
|
||||
JSX509CertificatePrototype(JSC::VM& vm, JSC::Structure* structure)
|
||||
: Base(vm, structure)
|
||||
{
|
||||
}
|
||||
|
||||
void finishCreation(JSC::VM& vm);
|
||||
};
|
||||
|
||||
const ClassInfo JSX509CertificatePrototype::s_info = { "X509Certificate"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSX509CertificatePrototype) };
|
||||
|
||||
void JSX509CertificatePrototype::finishCreation(VM& vm)
|
||||
{
|
||||
Base::finishCreation(vm);
|
||||
reifyStaticProperties(vm, JSX509Certificate::info(), JSX509CertificatePrototypeTableValues, *this);
|
||||
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
|
||||
}
|
||||
|
||||
} // namespace Bun
|
||||
```
|
||||
|
||||
### Getter definition:
|
||||
```C++
|
||||
|
||||
JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_ca, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName))
|
||||
{
|
||||
VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
JSX509Certificate* thisObject = jsDynamicCast<JSX509Certificate*>(JSValue::decode(thisValue));
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
Bun::throwThisTypeError(*globalObject, scope, "JSX509Certificate"_s, "ca"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
return JSValue::encode(jsBoolean(thisObject->view().isCA()));
|
||||
}
|
||||
```
|
||||
|
||||
### Setter definition
|
||||
|
||||
```C++
|
||||
JSC_DEFINE_CUSTOM_SETTER(jsImportMetaObjectSetter_require, (JSGlobalObject * jsGlobalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, PropertyName propertyName))
|
||||
{
|
||||
ImportMetaObject* thisObject = jsDynamicCast<ImportMetaObject*>(JSValue::decode(thisValue));
|
||||
if (UNLIKELY(!thisObject))
|
||||
return false;
|
||||
|
||||
JSValue value = JSValue::decode(encodedValue);
|
||||
if (!value.isCell()) {
|
||||
// TODO:
|
||||
return true;
|
||||
}
|
||||
|
||||
thisObject->requireProperty.set(thisObject->vm(), thisObject, value.asCell());
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### Function definition
|
||||
|
||||
```C++
|
||||
JSC_DEFINE_HOST_FUNCTION(jsX509CertificateProtoFuncToJSON, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto *thisObject = jsDynamicCast<MyClassT*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
Bun::throwThisTypeError(*globalObject, scope, "MyClass"_s, "myFunctionName"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
return JSValue::encode(functionThatReturnsJSValue(vm, globalObject, thisObject));
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Constructor definition
|
||||
|
||||
```C++
|
||||
|
||||
JSC_DECLARE_HOST_FUNCTION(callStats);
|
||||
JSC_DECLARE_HOST_FUNCTION(constructStats);
|
||||
|
||||
class JSStatsConstructor final : public JSC::InternalFunction {
|
||||
public:
|
||||
using Base = JSC::InternalFunction;
|
||||
static constexpr unsigned StructureFlags = Base::StructureFlags;
|
||||
|
||||
static JSStatsConstructor* create(JSC::VM& vm, JSC::Structure* structure, JSC::JSObject* prototype)
|
||||
{
|
||||
JSStatsConstructor* constructor = new (NotNull, JSC::allocateCell<JSStatsConstructor>(vm)) JSStatsConstructor(vm, structure);
|
||||
constructor->finishCreation(vm, prototype);
|
||||
return constructor;
|
||||
}
|
||||
|
||||
DECLARE_INFO;
|
||||
|
||||
template<typename CellType, JSC::SubspaceAccess>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
return &vm.internalFunctionSpace();
|
||||
}
|
||||
|
||||
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
|
||||
{
|
||||
return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info());
|
||||
}
|
||||
|
||||
private:
|
||||
JSStatsConstructor(JSC::VM& vm, JSC::Structure* structure)
|
||||
: Base(vm, structure, callStats, constructStats)
|
||||
{
|
||||
}
|
||||
|
||||
void finishCreation(JSC::VM& vm, JSC::JSObject* prototype)
|
||||
{
|
||||
Base::finishCreation(vm, 0, "Stats"_s);
|
||||
putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
### Structure caching
|
||||
|
||||
If there's a class, prototype, and constructor:
|
||||
|
||||
1. Add the `JSC::LazyClassStructure` to [ZigGlobalObject.h](mdc:src/bun.js/bindings/ZigGlobalObject.h)
|
||||
2. Initialize the class structure in [ZigGlobalObject.cpp](mdc:src/bun.js/bindings/ZigGlobalObject.cpp) in `void GlobalObject::finishCreation(VM& vm)`
|
||||
3. Visit the class structure in visitChildren in [ZigGlobalObject.cpp](mdc:src/bun.js/bindings/ZigGlobalObject.cpp) in `void GlobalObject::visitChildrenImpl`
|
||||
|
||||
```c++
|
||||
|
||||
m_JSStatsBigIntClassStructure.initLater(
|
||||
[](LazyClassStructure::Initializer& init) {
|
||||
Bun::initJSBigIntStatsClassStructure(init);
|
||||
});
|
||||
```
|
||||
|
||||
If there's only a class, use `JSC::LazyProperty<JSGlobalObject, Structure>` instead of `JSC::LazyClassStructure`.
|
||||
|
||||
Then, implement the function that creates the structure:
|
||||
```c++
|
||||
void setupX509CertificateClassStructure(LazyClassStructure::Initializer& init)
|
||||
{
|
||||
auto* prototypeStructure = JSX509CertificatePrototype::createStructure(init.vm, init.global, init.global->objectPrototype());
|
||||
auto* prototype = JSX509CertificatePrototype::create(init.vm, init.global, prototypeStructure);
|
||||
|
||||
auto* constructorStructure = JSX509CertificateConstructor::createStructure(init.vm, init.global, init.global->functionPrototype());
|
||||
|
||||
auto* constructor = JSX509CertificateConstructor::create(init.vm, init.global, constructorStructure, prototype);
|
||||
|
||||
auto* structure = JSX509Certificate::createStructure(init.vm, init.global, prototype);
|
||||
init.setPrototype(prototype);
|
||||
init.setStructure(structure);
|
||||
init.setConstructor(constructor);
|
||||
}
|
||||
```
|
||||
|
||||
Then, use the structure by calling `globalObject.m_myStructureName.get(globalObject)`
|
||||
|
||||
```C++
|
||||
JSC_DEFINE_HOST_FUNCTION(x509CertificateConstructorConstruct, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
if (!callFrame->argumentCount()) {
|
||||
Bun::throwError(globalObject, scope, ErrorCode::ERR_MISSING_ARGS, "X509Certificate constructor requires at least one argument"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
JSValue arg = callFrame->uncheckedArgument(0);
|
||||
if (!arg.isCell()) {
|
||||
Bun::throwError(globalObject, scope, ErrorCode::ERR_INVALID_ARG_TYPE, "X509Certificate constructor argument must be a Buffer, TypedArray, or string"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
auto* zigGlobalObject = defaultGlobalObject(globalObject);
|
||||
Structure* structure = zigGlobalObject->m_JSX509CertificateClassStructure.get(zigGlobalObject);
|
||||
JSValue newTarget = callFrame->newTarget();
|
||||
if (UNLIKELY(zigGlobalObject->m_JSX509CertificateClassStructure.constructor(zigGlobalObject) != newTarget)) {
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
if (!newTarget) {
|
||||
throwTypeError(globalObject, scope, "Class constructor X509Certificate cannot be invoked without 'new'"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
auto* functionGlobalObject = defaultGlobalObject(getFunctionRealm(globalObject, newTarget.getObject()));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
structure = InternalFunction::createSubclassStructure(
|
||||
globalObject, newTarget.getObject(), functionGlobalObject->NodeVMScriptStructure());
|
||||
scope.release();
|
||||
}
|
||||
|
||||
return JSValue::encode(createX509Certificate(vm, globalObject, structure, arg));
|
||||
}
|
||||
```
|
||||
|
||||
### Expose to Zig
|
||||
|
||||
To expose the constructor to zig:
|
||||
|
||||
```c++
|
||||
extern "C" JSC::EncodedJSValue Bun__JSBigIntStatsObjectConstructor(Zig::GlobalObject* globalobject)
|
||||
{
|
||||
return JSValue::encode(globalobject->m_JSStatsBigIntClassStructure.constructor(globalobject));
|
||||
}
|
||||
```
|
||||
|
||||
Zig:
|
||||
```zig
|
||||
extern "c" fn Bun__JSBigIntStatsObjectConstructor(*JSC.JSGlobalObject) JSC.JSValue;
|
||||
pub const getBigIntStatsConstructor = Bun__JSBigIntStatsObjectConstructor;
|
||||
```
|
||||
|
||||
To create an object (instance) of a JS class defined in C++ from Zig, follow the __toJS convention like this:
|
||||
```c++
|
||||
// X509* is whatever we need to create the object
|
||||
extern "C" EncodedJSValue Bun__X509__toJS(Zig::GlobalObject* globalObject, X509* cert)
|
||||
{
|
||||
// ... implementation details
|
||||
auto* structure = globalObject->m_JSX509CertificateClassStructure.get(globalObject);
|
||||
return JSValue::encode(JSX509Certificate::create(globalObject->vm(), structure, globalObject, WTFMove(cert)));
|
||||
}
|
||||
```
|
||||
|
||||
And from Zig:
|
||||
```zig
|
||||
const X509 = opaque {
|
||||
// ... class
|
||||
|
||||
extern fn Bun__X509__toJS(*JSC.JSGlobalObject, *X509) JSC.JSValue;
|
||||
|
||||
pub fn toJS(this: *X509, globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
return Bun__X509__toJS(globalObject, this);
|
||||
}
|
||||
};
|
||||
```
|
||||
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -15,6 +15,7 @@
|
||||
*.lock text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.map text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.md text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.mdc text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.mjs text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.mts text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
|
||||
|
||||
2
.github/actions/setup-bun/action.yml
vendored
2
.github/actions/setup-bun/action.yml
vendored
@@ -4,7 +4,7 @@ description: An internal version of the 'oven-sh/setup-bun' action.
|
||||
inputs:
|
||||
bun-version:
|
||||
type: string
|
||||
description: "The version of bun to install: 'latest', 'canary', 'bun-v1.0.0', etc."
|
||||
description: "The version of bun to install: 'latest', 'canary', 'bun-v1.2.0', etc."
|
||||
default: latest
|
||||
required: false
|
||||
baseline:
|
||||
|
||||
2
.github/workflows/clang-format.yml
vendored
2
.github/workflows/clang-format.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
merge_group:
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.2.0"
|
||||
LLVM_VERSION: "18.1.8"
|
||||
LLVM_VERSION_MAJOR: "18"
|
||||
|
||||
|
||||
2
.github/workflows/clang-tidy.yml
vendored
2
.github/workflows/clang-tidy.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
merge_group:
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.2.0"
|
||||
LLVM_VERSION: "18.1.8"
|
||||
LLVM_VERSION_MAJOR: "18"
|
||||
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -5,7 +5,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.2.0"
|
||||
OXLINT_VERSION: "0.15.0"
|
||||
|
||||
jobs:
|
||||
|
||||
2
.github/workflows/prettier-format.yml
vendored
2
.github/workflows/prettier-format.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
merge_group:
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.2.0"
|
||||
|
||||
jobs:
|
||||
prettier-format:
|
||||
|
||||
56
.github/workflows/release.yml
vendored
56
.github/workflows/release.yml
vendored
@@ -44,6 +44,10 @@ on:
|
||||
description: Should types be released to npm?
|
||||
type: boolean
|
||||
default: false
|
||||
use-definitelytyped:
|
||||
description: "Should types be PR'd to DefinitelyTyped?"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
sign:
|
||||
@@ -66,7 +70,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.44"
|
||||
bun-version: "1.2.0"
|
||||
- name: Install Dependencies
|
||||
run: bun install
|
||||
- name: Sign Release
|
||||
@@ -94,7 +98,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.44"
|
||||
bun-version: "1.2.0"
|
||||
- name: Install Dependencies
|
||||
run: bun install
|
||||
- name: Release
|
||||
@@ -123,7 +127,7 @@ jobs:
|
||||
if: ${{ env.BUN_VERSION != 'canary' }}
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.44"
|
||||
bun-version: "1.2.0"
|
||||
- name: Setup Bun
|
||||
if: ${{ env.BUN_VERSION == 'canary' }}
|
||||
uses: ./.github/actions/setup-bun
|
||||
@@ -155,6 +159,48 @@ jobs:
|
||||
with:
|
||||
package: packages/bun-types/package.json
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
definitelytyped:
|
||||
name: Make pr to DefinitelyTyped to update `bun-types` version
|
||||
runs-on: ubuntu-latest
|
||||
needs: npm-types
|
||||
if: ${{ github.event_name == 'release' || github.event.inputs.use-definitelytyped == 'true' }}
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: DefinitelyTyped/DefinitelyTyped
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.2.0"
|
||||
- id: bun-version
|
||||
run: echo "BUN_VERSION=${BUN_VERSION#bun-v}" >> "$GITHUB_OUTPUT"
|
||||
- name: Update bun-types version in package.json
|
||||
run: |
|
||||
bun -e '
|
||||
const file = Bun.file("./types/bun/package.json");
|
||||
const json = await file.json();
|
||||
const version = "${{ steps.bun-version.outputs.BUN_VERSION }}";
|
||||
json.dependencies["bun-types"] = version;
|
||||
json.version = version.slice(0, version.lastIndexOf(".")) + ".9999";
|
||||
await file.write(JSON.stringify(json, null, 4) + "\n");
|
||||
'
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
if: ${{ env.BUN_LATEST == 'true' && env.BUN_VERSION != 'canary'}}
|
||||
with:
|
||||
token: ${{ secrets.ROBOBUN_TOKEN }}
|
||||
add-paths: ./types/bun/package.json
|
||||
title: "[bun] update to ${{ steps.bun-version.outputs.BUN_VERSION }}"
|
||||
commit-message: "[bun] update to ${{ steps.bun-version.outputs.BUN_VERSION }}"
|
||||
body: |
|
||||
Update `bun-types` version to ${{ steps.bun-version.outputs.BUN_VERSION }}
|
||||
|
||||
https://bun.sh/blog/${{ env.BUN_VERSION }}
|
||||
push-to-fork: oven-sh/DefinitelyTyped
|
||||
branch: ${{env.BUN_VERSION}}
|
||||
docker:
|
||||
name: Release to Dockerhub
|
||||
runs-on: ubuntu-latest
|
||||
@@ -265,7 +311,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.44"
|
||||
bun-version: "1.2.0"
|
||||
- name: Install Dependencies
|
||||
run: bun install
|
||||
- name: Release
|
||||
@@ -309,7 +355,7 @@ jobs:
|
||||
uses: ./.github/actions/setup-bun
|
||||
if: ${{ env.BUN_LATEST == 'true' }}
|
||||
with:
|
||||
bun-version: "1.1.44"
|
||||
bun-version: "1.2.0"
|
||||
- name: Bump version
|
||||
uses: ./.github/actions/bump
|
||||
if: ${{ env.BUN_LATEST == 'true' }}
|
||||
|
||||
2
.github/workflows/run-lint.yml
vendored
2
.github/workflows/run-lint.yml
vendored
@@ -4,7 +4,7 @@ permissions:
|
||||
contents: read
|
||||
env:
|
||||
LLVM_VERSION: 16
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.2.0"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
2
.github/workflows/test-bump.yml
vendored
2
.github/workflows/test-bump.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
required: true
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.2.0"
|
||||
|
||||
jobs:
|
||||
bump:
|
||||
|
||||
2
.github/workflows/update-sqlite3.yml
vendored
2
.github/workflows/update-sqlite3.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
||||
|
||||
# Convert numeric version to semantic version for display
|
||||
LATEST_MAJOR=$((10#$LATEST_VERSION_NUM / 1000000))
|
||||
LATEST_MINOR=$((($LATEST_VERSION_NUM / 1000) % 1000))
|
||||
LATEST_MINOR=$((($LATEST_VERSION_NUM / 10000) % 100))
|
||||
LATEST_PATCH=$((10#$LATEST_VERSION_NUM % 1000))
|
||||
LATEST_VERSION="$LATEST_MAJOR.$LATEST_MINOR.$LATEST_PATCH"
|
||||
|
||||
|
||||
2
.github/workflows/zig-format.yml
vendored
2
.github/workflows/zig-format.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
merge_group:
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.2.0"
|
||||
|
||||
jobs:
|
||||
zig-format:
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -16,6 +16,7 @@
|
||||
.vscode/clang*
|
||||
.vscode/cpp*
|
||||
.zig-cache
|
||||
.bake-debug
|
||||
*.a
|
||||
*.bc
|
||||
*.big
|
||||
@@ -151,6 +152,7 @@ src/bake/generated.ts
|
||||
test/cli/install/registry/packages/publish-pkg-*
|
||||
test/cli/install/registry/packages/@secret/publish-pkg-8
|
||||
test/js/third_party/prisma/prisma/sqlite/dev.db-journal
|
||||
tmp
|
||||
|
||||
# Dependencies
|
||||
/vendor
|
||||
@@ -178,4 +180,4 @@ test/js/third_party/prisma/prisma/sqlite/dev.db-journal
|
||||
|
||||
.buildkite/ci.yml
|
||||
*.sock
|
||||
scratch*.{js,ts,tsx,cjs,mjs}
|
||||
scratch*.{js,ts,tsx,cjs,mjs}
|
||||
|
||||
@@ -7,3 +7,4 @@ src/react-refresh.js
|
||||
*.min.js
|
||||
test/snippets
|
||||
test/js/node/test
|
||||
bun.lock
|
||||
|
||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -63,6 +63,7 @@
|
||||
"editor.tabSize": 4,
|
||||
"editor.defaultFormatter": "xaver.clang-format",
|
||||
},
|
||||
"clangd.arguments": ["--header-insertion=never"],
|
||||
|
||||
// JavaScript
|
||||
"prettier.enable": true,
|
||||
@@ -140,6 +141,7 @@
|
||||
},
|
||||
"files.associations": {
|
||||
"*.idl": "cpp",
|
||||
"*.mdc": "markdown",
|
||||
"array": "cpp",
|
||||
},
|
||||
"C_Cpp.files.exclude": {
|
||||
|
||||
@@ -12,6 +12,12 @@ list(APPEND CMAKE_MODULE_PATH
|
||||
include(Policies)
|
||||
include(Globals)
|
||||
|
||||
if (CMAKE_HOST_WIN32)
|
||||
# Workaround for TLS certificate verification issue on Windows when downloading from GitHub
|
||||
# Remove this once we've bumped the CI machines build image
|
||||
set(CMAKE_TLS_VERIFY 0)
|
||||
endif()
|
||||
|
||||
# --- Compilers ---
|
||||
|
||||
if(CMAKE_HOST_APPLE)
|
||||
|
||||
3
Makefile
3
Makefile
@@ -1301,6 +1301,7 @@ jsc-build-mac-compile-lto:
|
||||
.PHONY: jsc-build-mac-compile-debug
|
||||
jsc-build-mac-compile-debug:
|
||||
mkdir -p $(WEBKIT_DEBUG_DIR) $(WEBKIT_DIR);
|
||||
# to disable asan, remove -DENABLE_SANITIZERS=address and add -DENABLE_MALLOC_HEAP_BREAKDOWN=ON
|
||||
cd $(WEBKIT_DEBUG_DIR) && \
|
||||
ICU_INCLUDE_DIRS="$(HOMEBREW_PREFIX)opt/icu4c/include" \
|
||||
cmake \
|
||||
@@ -1309,7 +1310,6 @@ jsc-build-mac-compile-debug:
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DUSE_THIN_ARCHIVES=OFF \
|
||||
-DENABLE_FTL_JIT=ON \
|
||||
-DENABLE_MALLOC_HEAP_BREAKDOWN=ON \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
-DUSE_BUN_EVENT_LOOP=ON \
|
||||
@@ -1321,6 +1321,7 @@ jsc-build-mac-compile-debug:
|
||||
-DUSE_PTHREAD_JIT_PERMISSIONS_API=ON \
|
||||
-DENABLE_REMOTE_INSPECTOR=ON \
|
||||
-DUSE_VISIBILITY_ATTRIBUTE=1 \
|
||||
-DENABLE_SANITIZERS=address \
|
||||
$(WEBKIT_DIR) \
|
||||
$(WEBKIT_DEBUG_DIR) && \
|
||||
CFLAGS="$(CFLAGS) -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -ffat-lto-objects" \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bench",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "expect-to-equal",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bench",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bench",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "simple-react",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "react-hello-world",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "scan",
|
||||
|
||||
@@ -39,24 +39,24 @@ bench("Buffer.from(ArrayBuffer(100))", () => {
|
||||
return Buffer.from(hundred);
|
||||
});
|
||||
|
||||
bench("new Buffer(ArrayBuffer(100))", () => {
|
||||
return new Buffer(hundred);
|
||||
});
|
||||
|
||||
var hundredArray = new Uint8Array(100);
|
||||
bench("Buffer.from(Uint8Array(100))", () => {
|
||||
return Buffer.from(hundredArray);
|
||||
});
|
||||
|
||||
bench("new Buffer(Uint8Array(100))", () => {
|
||||
return new Buffer(hundredArray);
|
||||
});
|
||||
|
||||
var empty = new Uint8Array(0);
|
||||
bench("Buffer.from(Uint8Array(0))", () => {
|
||||
return Buffer.from(empty);
|
||||
});
|
||||
|
||||
bench("new Buffer(ArrayBuffer(100))", () => {
|
||||
return new Buffer(hundred);
|
||||
});
|
||||
|
||||
bench("new Buffer(Uint8Array(100))", () => {
|
||||
return new Buffer(hundredArray);
|
||||
});
|
||||
|
||||
bench("new Buffer(Uint8Array(0))", () => {
|
||||
return new Buffer(empty);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// import { Buffer } from "buffer";
|
||||
var buf = new Buffer(1024);
|
||||
var view = new DataView(buf.buffer);
|
||||
var INTERVAL = 9999999;
|
||||
var INTERVAL = 9_999_999;
|
||||
var time = (name, fn) => {
|
||||
for (let i = 0; i < INTERVAL; i++) fn();
|
||||
|
||||
|
||||
25
bench/snippets/path-relative.mjs
Normal file
25
bench/snippets/path-relative.mjs
Normal file
@@ -0,0 +1,25 @@
|
||||
import { posix } from "path";
|
||||
import { bench, run } from "../runner.mjs";
|
||||
|
||||
const pathConfigurations = [
|
||||
["", ""],
|
||||
[".", "."],
|
||||
["/foo/bar", "/foo/bar"],
|
||||
["/foo/bar/baz", "/foo/bar"],
|
||||
["/foo/bar", "/foo/bar/baz"],
|
||||
["/foo/bar/baz", "/foo/bar/qux"],
|
||||
["/foo/bar/baz", "/foo/bar/baz/qux"],
|
||||
["/foo/bar/baz", "/foo/bar/baz/qux/quux"],
|
||||
["/", "/foo"],
|
||||
["/foo", "/"],
|
||||
["foo/bar/baz", "foo/bar/qux"],
|
||||
["../foo/bar", "../foo/baz"],
|
||||
];
|
||||
|
||||
pathConfigurations.forEach(([from, to]) => {
|
||||
bench(`relative(${JSON.stringify(from)}, ${JSON.stringify(to)})`, () => {
|
||||
globalThis.abc = posix.relative(from, to);
|
||||
});
|
||||
});
|
||||
|
||||
await run();
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bench",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "websocket-server",
|
||||
|
||||
65
build.zig
65
build.zig
@@ -19,7 +19,7 @@ const OperatingSystem = @import("src/env.zig").OperatingSystem;
|
||||
const pathRel = fs.path.relative;
|
||||
|
||||
/// Do not rename this constant. It is scanned by some scripts to determine which zig version to install.
|
||||
const recommended_zig_version = "0.13.0";
|
||||
const recommended_zig_version = "0.14.0-dev.2987+183bb8b08";
|
||||
|
||||
comptime {
|
||||
if (!std.mem.eql(u8, builtin.zig_version_string, recommended_zig_version)) {
|
||||
@@ -46,6 +46,7 @@ const BunBuildOptions = struct {
|
||||
sha: []const u8,
|
||||
/// enable debug logs in release builds
|
||||
enable_logs: bool = false,
|
||||
enable_asan: bool,
|
||||
tracy_callstack_depth: u16,
|
||||
reported_nodejs_version: Version,
|
||||
/// To make iterating on some '@embedFile's faster, we load them at runtime
|
||||
@@ -81,10 +82,7 @@ const BunBuildOptions = struct {
|
||||
|
||||
var opts = b.addOptions();
|
||||
opts.addOption([]const u8, "base_path", b.pathFromRoot("."));
|
||||
opts.addOption([]const u8, "codegen_path", std.fs.path.resolve(b.graph.arena, &.{
|
||||
b.build_root.path.?,
|
||||
this.codegen_path,
|
||||
}) catch @panic("OOM"));
|
||||
opts.addOption([]const u8, "codegen_path", std.fs.path.resolve(b.graph.arena, &.{ b.build_root.path.?, this.codegen_path }) catch @panic("OOM"));
|
||||
|
||||
opts.addOption(bool, "codegen_embed", this.shouldEmbedCode());
|
||||
opts.addOption(u32, "canary_revision", this.canary_revision orelse 0);
|
||||
@@ -154,8 +152,6 @@ pub fn build(b: *Build) !void {
|
||||
std.log.info("zig compiler v{s}", .{builtin.zig_version_string});
|
||||
checked_file_exists = std.AutoHashMap(u64, void).init(b.allocator);
|
||||
|
||||
b.zig_lib_dir = b.zig_lib_dir orelse b.path("vendor/zig/lib");
|
||||
|
||||
// TODO: Upgrade path for 0.14.0
|
||||
// b.graph.zig_lib_directory = brk: {
|
||||
// const sub_path = "vendor/zig/lib";
|
||||
@@ -209,7 +205,7 @@ pub fn build(b: *Build) !void {
|
||||
const bun_version = b.option([]const u8, "version", "Value of `Bun.version`") orelse "0.0.0";
|
||||
|
||||
b.reference_trace = ref_trace: {
|
||||
const trace = b.option(u32, "reference-trace", "Set the reference trace") orelse 16;
|
||||
const trace = b.option(u32, "reference-trace", "Set the reference trace") orelse 24;
|
||||
break :ref_trace if (trace == 0) null else trace;
|
||||
};
|
||||
|
||||
@@ -277,6 +273,7 @@ pub fn build(b: *Build) !void {
|
||||
|
||||
.tracy_callstack_depth = b.option(u16, "tracy_callstack_depth", "") orelse 10,
|
||||
.enable_logs = b.option(bool, "enable_logs", "Enable logs in release") orelse false,
|
||||
.enable_asan = b.option(bool, "enable_asan", "Enable asan") orelse false,
|
||||
};
|
||||
|
||||
// zig build obj
|
||||
@@ -331,11 +328,25 @@ pub fn build(b: *Build) !void {
|
||||
.{ .os = .windows, .arch = .x86_64 },
|
||||
});
|
||||
}
|
||||
{
|
||||
const step = b.step("check-macos", "Check for semantic analysis errors on Windows");
|
||||
addMultiCheck(b, step, build_options, &.{
|
||||
.{ .os = .mac, .arch = .x86_64 },
|
||||
.{ .os = .mac, .arch = .aarch64 },
|
||||
});
|
||||
}
|
||||
{
|
||||
const step = b.step("check-linux", "Check for semantic analysis errors on Windows");
|
||||
addMultiCheck(b, step, build_options, &.{
|
||||
.{ .os = .linux, .arch = .x86_64 },
|
||||
.{ .os = .linux, .arch = .aarch64 },
|
||||
});
|
||||
}
|
||||
|
||||
// zig build translate-c-headers
|
||||
{
|
||||
const step = b.step("translate-c", "Copy generated translated-c-headers.zig to zig-out");
|
||||
step.dependOn(&b.addInstallFile(getTranslateC(b, b.host, .Debug).getOutput(), "translated-c-headers.zig").step);
|
||||
step.dependOn(&b.addInstallFile(getTranslateC(b, b.graph.host, .Debug).getOutput(), "translated-c-headers.zig").step);
|
||||
}
|
||||
|
||||
// zig build enum-extractor
|
||||
@@ -363,7 +374,7 @@ pub fn addMultiCheck(
|
||||
const check_target = b.resolveTargetQuery(.{
|
||||
.os_tag = OperatingSystem.stdOSTag(check.os),
|
||||
.cpu_arch = check.arch,
|
||||
.cpu_model = getCpuModel(check.os, check.arch) orelse .determined_by_cpu_arch,
|
||||
.cpu_model = getCpuModel(check.os, check.arch) orelse .determined_by_arch_os,
|
||||
.os_version_min = getOSVersionMin(check.os),
|
||||
.glibc_version = if (check.musl) null else getOSGlibCVersion(check.os),
|
||||
});
|
||||
@@ -381,6 +392,7 @@ pub fn addMultiCheck(
|
||||
.reported_nodejs_version = root_build_options.reported_nodejs_version,
|
||||
.codegen_path = root_build_options.codegen_path,
|
||||
.no_llvm = root_build_options.no_llvm,
|
||||
.enable_asan = root_build_options.enable_asan,
|
||||
};
|
||||
|
||||
var obj = addBunObject(b, &options);
|
||||
@@ -414,7 +426,7 @@ pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile {
|
||||
.name = if (opts.optimize == .Debug) "bun-debug" else "bun",
|
||||
.root_source_file = switch (opts.os) {
|
||||
.wasm => b.path("root_wasm.zig"),
|
||||
else => b.path("root.zig"),
|
||||
else => b.path("src/main.zig"),
|
||||
// else => b.path("root_css.zig"),
|
||||
},
|
||||
.target = opts.target,
|
||||
@@ -428,8 +440,15 @@ pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile {
|
||||
.omit_frame_pointer = false,
|
||||
.strip = false, // stripped at the end
|
||||
});
|
||||
if (opts.enable_asan) {
|
||||
if (@hasField(Build.Module, "sanitize_address")) {
|
||||
obj.root_module.sanitize_address = true;
|
||||
} else {
|
||||
const fail_step = b.addFail("asan is not supported on this platform");
|
||||
obj.step.dependOn(&fail_step.step);
|
||||
}
|
||||
}
|
||||
obj.bundle_compiler_rt = false;
|
||||
obj.formatted_panics = true;
|
||||
obj.root_module.omit_frame_pointer = false;
|
||||
|
||||
// Link libc
|
||||
@@ -497,16 +516,6 @@ fn exists(path: []const u8) bool {
|
||||
fn addInternalPackages(b: *Build, obj: *Compile, opts: *BunBuildOptions) void {
|
||||
const os = opts.os;
|
||||
|
||||
const io_path = switch (os) {
|
||||
.mac => "src/io/io_darwin.zig",
|
||||
.linux => "src/io/io_linux.zig",
|
||||
.windows => "src/io/io_windows.zig",
|
||||
else => "src/io/io_stub.zig",
|
||||
};
|
||||
obj.root_module.addAnonymousImport("async_io", .{
|
||||
.root_source_file = b.path(io_path),
|
||||
});
|
||||
|
||||
const zlib_internal_path = switch (os) {
|
||||
.windows => "src/deps/zlib.win32.zig",
|
||||
.linux, .mac => "src/deps/zlib.posix.zig",
|
||||
@@ -539,6 +548,7 @@ fn addInternalPackages(b: *Build, obj: *Compile, opts: *BunBuildOptions) void {
|
||||
.{ .file = "bun-error/index.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "bun-error/bun-error.css", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "fallback-decoder.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/react-refresh.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/assert.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/buffer.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/console.js", .enable = opts.shouldEmbedCode() },
|
||||
@@ -575,6 +585,15 @@ fn addInternalPackages(b: *Build, obj: *Compile, opts: *BunBuildOptions) void {
|
||||
});
|
||||
}
|
||||
}
|
||||
inline for (.{
|
||||
.{ .import = "completions-bash", .file = b.path("completions/bun.bash") },
|
||||
.{ .import = "completions-zsh", .file = b.path("completions/bun.zsh") },
|
||||
.{ .import = "completions-fish", .file = b.path("completions/bun.fish") },
|
||||
}) |entry| {
|
||||
obj.root_module.addAnonymousImport(entry.import, .{
|
||||
.root_source_file = entry.file,
|
||||
});
|
||||
}
|
||||
|
||||
if (os == .windows) {
|
||||
obj.root_module.addAnonymousImport("bun_shim_impl.exe", .{
|
||||
@@ -614,7 +633,7 @@ const WindowsShim = struct {
|
||||
.optimize = .ReleaseFast,
|
||||
.use_llvm = true,
|
||||
.use_lld = true,
|
||||
.unwind_tables = false,
|
||||
.unwind_tables = .none,
|
||||
.omit_frame_pointer = true,
|
||||
.strip = true,
|
||||
.linkage = .static,
|
||||
|
||||
72
bun.lock
72
bun.lock
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bun",
|
||||
@@ -45,21 +45,21 @@
|
||||
"packages": {
|
||||
"@biomejs/biome": ["@biomejs/biome@1.8.3", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "1.8.3", "@biomejs/cli-darwin-x64": "1.8.3", "@biomejs/cli-linux-arm64": "1.8.3", "@biomejs/cli-linux-arm64-musl": "1.8.3", "@biomejs/cli-linux-x64": "1.8.3", "@biomejs/cli-linux-x64-musl": "1.8.3", "@biomejs/cli-win32-arm64": "1.8.3", "@biomejs/cli-win32-x64": "1.8.3" }, "bin": { "biome": "bin/biome" } }, "sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w=="],
|
||||
|
||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.8.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A=="],
|
||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.8.3", "", { "os":"darwin", "cpu":"arm64" }, "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A=="],
|
||||
|
||||
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.8.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw=="],
|
||||
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.8.3", "", { "os":"darwin", "cpu":"x64" }, "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw=="],
|
||||
|
||||
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.8.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw=="],
|
||||
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.8.3", "", { "os":"linux", "cpu":"arm64" }, "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw=="],
|
||||
|
||||
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.8.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ=="],
|
||||
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.8.3", "", { "os":"linux", "cpu":"arm64" }, "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ=="],
|
||||
|
||||
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.8.3", "", { "os": "linux", "cpu": "x64" }, "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw=="],
|
||||
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.8.3", "", { "os":"linux", "cpu":"x64" }, "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw=="],
|
||||
|
||||
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.8.3", "", { "os": "linux", "cpu": "x64" }, "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA=="],
|
||||
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.8.3", "", { "os":"linux", "cpu":"x64" }, "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA=="],
|
||||
|
||||
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.8.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ=="],
|
||||
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.8.3", "", { "os":"win32", "cpu":"arm64" }, "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ=="],
|
||||
|
||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.8.3", "", { "os": "win32", "cpu": "x64" }, "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg=="],
|
||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.8.3", "", { "os":"win32", "cpu":"x64" }, "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg=="],
|
||||
|
||||
"@definitelytyped/dts-critic": ["@definitelytyped/dts-critic@0.0.191", "", { "dependencies": { "@definitelytyped/header-parser": "0.0.190", "command-exists": "^1.2.9", "semver": "^7.5.4", "tmp": "^0.2.1", "typescript": "^5.2.2", "yargs": "^17.7.2" } }, "sha512-j5HK3pQYiQwSXRLJzyhXJ6KxdzLl4gXXhz3ysCtLnRQkj+zsEfloDkEZ3x2bZMWS0OsKLXmR91JeQ2/c9DFEjg=="],
|
||||
|
||||
@@ -75,51 +75,51 @@
|
||||
|
||||
"@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.39.4", "", { "dependencies": { "comment-parser": "1.3.1", "esquery": "^1.5.0", "jsdoc-type-pratt-parser": "~4.0.0" } }, "sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os":"aix", "cpu":"ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os":"android", "cpu":"arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os":"android", "cpu":"arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os":"android", "cpu":"x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os":"darwin", "cpu":"arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os":"darwin", "cpu":"x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os":"freebsd", "cpu":"arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os":"freebsd", "cpu":"x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os":"linux", "cpu":"arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os":"linux", "cpu":"arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os":"linux", "cpu":"ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os":"linux", "cpu":"none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os":"linux", "cpu":"none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os":"linux", "cpu":"ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os":"linux", "cpu":"none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os":"linux", "cpu":"s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os":"linux", "cpu":"x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os":"none", "cpu":"x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os":"openbsd", "cpu":"x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os":"sunos", "cpu":"x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os":"win32", "cpu":"arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os":"win32", "cpu":"ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os":"win32", "cpu":"x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
|
||||
|
||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.0", "", { "dependencies": { "eslint-visitor-keys": "^3.3.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA=="],
|
||||
|
||||
@@ -257,7 +257,7 @@
|
||||
|
||||
"builtins": ["builtins@1.0.3", "", {}, "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ=="],
|
||||
|
||||
"bun-types": ["bun-types@workspace:packages/bun-types", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" }, "devDependencies": { "@biomejs/biome": "^1.5.3", "@definitelytyped/dtslint": "^0.0.199", "@definitelytyped/eslint-plugin": "^0.0.197", "typescript": "^5.0.2" } }],
|
||||
"bun-types": ["bun-types@workspace:packages/bun-types"],
|
||||
|
||||
"call-bind": ["call-bind@1.0.7", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.1" } }, "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w=="],
|
||||
|
||||
@@ -265,7 +265,7 @@
|
||||
|
||||
"camel-case": ["camel-case@4.1.2", "", { "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" } }, "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="],
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001695", "", {}, "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw=="],
|
||||
|
||||
"capital-case": ["capital-case@1.0.4", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", "upper-case-first": "^2.0.2" } }, "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A=="],
|
||||
|
||||
@@ -923,10 +923,14 @@
|
||||
|
||||
"are-we-there-yet/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||
|
||||
"autoprefixer/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="],
|
||||
|
||||
"babel-code-frame/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A=="],
|
||||
|
||||
"babel-code-frame/js-tokens": ["js-tokens@3.0.2", "", {}, "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg=="],
|
||||
|
||||
"browserslist/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="],
|
||||
|
||||
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
"eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
@@ -44,6 +44,13 @@ if(WIN32)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_ASAN)
|
||||
register_compiler_flags(
|
||||
DESCRIPTION "Enable AddressSanitizer"
|
||||
-fsanitize=address
|
||||
)
|
||||
endif()
|
||||
|
||||
# --- Optimization level ---
|
||||
if(DEBUG)
|
||||
register_compiler_flags(
|
||||
|
||||
@@ -86,6 +86,11 @@ optionx(ENABLE_LTO BOOL "If LTO (link-time optimization) should be used" DEFAULT
|
||||
if(LINUX)
|
||||
optionx(ENABLE_VALGRIND BOOL "If Valgrind support should be enabled" DEFAULT OFF)
|
||||
endif()
|
||||
if(DEBUG AND APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
|
||||
optionx(ENABLE_ASAN BOOL "If ASAN support should be enabled" DEFAULT ON)
|
||||
else()
|
||||
optionx(ENABLE_ASAN BOOL "If ASAN support should be enabled" DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
optionx(ENABLE_PRETTIER BOOL "If prettier should be ran" DEFAULT OFF)
|
||||
|
||||
|
||||
@@ -28,7 +28,12 @@ else()
|
||||
message(FATAL_ERROR "Unsupported architecture: ${CMAKE_HOST_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
set(ZIG_NAME zig-${ZIG_OS}-${ZIG_ARCH}-${ZIG_VERSION})
|
||||
set(ZIG_ASAN "")
|
||||
if(ENABLE_ASAN)
|
||||
set(ZIG_ASAN "+asan")
|
||||
endif()
|
||||
|
||||
set(ZIG_NAME zig-${ZIG_OS}-${ZIG_ARCH}-${ZIG_VERSION}${ZIG_ASAN})
|
||||
|
||||
if(CMAKE_HOST_WIN32)
|
||||
set(ZIG_EXE "zig.exe")
|
||||
@@ -38,7 +43,7 @@ else()
|
||||
set(ZIG_FILENAME ${ZIG_NAME}.tar.xz)
|
||||
endif()
|
||||
|
||||
set(ZIG_DOWNLOAD_URL https://ziglang.org/download/${ZIG_VERSION}/${ZIG_FILENAME})
|
||||
set(ZIG_DOWNLOAD_URL https://bun-ci-assets.bun.sh/${ZIG_FILENAME})
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
|
||||
@@ -179,6 +179,32 @@ register_command(
|
||||
${BUN_NODE_FALLBACKS_OUTPUTS}
|
||||
)
|
||||
|
||||
# An embedded copy of react-refresh is used when the user forgets to install it.
|
||||
# The library is not versioned alongside React.
|
||||
set(BUN_REACT_REFRESH_OUTPUT ${BUN_NODE_FALLBACKS_OUTPUT}/react-refresh.js)
|
||||
register_command(
|
||||
TARGET
|
||||
bun-node-fallbacks-react-refresh
|
||||
COMMENT
|
||||
"Building node-fallbacks/react-refresh.js"
|
||||
CWD
|
||||
${BUN_NODE_FALLBACKS_SOURCE}
|
||||
COMMAND
|
||||
${BUN_EXECUTABLE} build
|
||||
${BUN_NODE_FALLBACKS_SOURCE}/node_modules/react-refresh/cjs/react-refresh-runtime.development.js
|
||||
--outfile=${BUN_REACT_REFRESH_OUTPUT}
|
||||
--target=browser
|
||||
--format=cjs
|
||||
--minify
|
||||
--define:process.env.NODE_ENV=\"'development'\"
|
||||
SOURCES
|
||||
${BUN_NODE_FALLBACKS_SOURCE}/package.json
|
||||
${BUN_NODE_FALLBACKS_SOURCE}/bun.lock
|
||||
${BUN_NODE_FALLBACKS_NODE_MODULES}
|
||||
OUTPUTS
|
||||
${BUN_REACT_REFRESH_OUTPUT}
|
||||
)
|
||||
|
||||
set(BUN_ERROR_CODE_SCRIPT ${CWD}/src/codegen/generate-node-errors.ts)
|
||||
|
||||
set(BUN_ERROR_CODE_SOURCES
|
||||
@@ -404,6 +430,7 @@ set(BUN_OBJECT_LUT_SOURCES
|
||||
${CWD}/src/bun.js/bindings/ZigGlobalObject.lut.txt
|
||||
${CWD}/src/bun.js/bindings/JSBuffer.cpp
|
||||
${CWD}/src/bun.js/bindings/BunProcess.cpp
|
||||
${CWD}/src/bun.js/bindings/ProcessBindingBuffer.cpp
|
||||
${CWD}/src/bun.js/bindings/ProcessBindingConstants.cpp
|
||||
${CWD}/src/bun.js/bindings/ProcessBindingNatives.cpp
|
||||
${CWD}/src/bun.js/modules/NodeModuleModule.cpp
|
||||
@@ -415,6 +442,7 @@ set(BUN_OBJECT_LUT_OUTPUTS
|
||||
${CODEGEN_PATH}/ZigGlobalObject.lut.h
|
||||
${CODEGEN_PATH}/JSBuffer.lut.h
|
||||
${CODEGEN_PATH}/BunProcess.lut.h
|
||||
${CODEGEN_PATH}/ProcessBindingBuffer.lut.h
|
||||
${CODEGEN_PATH}/ProcessBindingConstants.lut.h
|
||||
${CODEGEN_PATH}/ProcessBindingNatives.lut.h
|
||||
${CODEGEN_PATH}/NodeModuleModule.lut.h
|
||||
@@ -498,8 +526,7 @@ file(GLOB_RECURSE BUN_ZIG_SOURCES ${CONFIGURE_DEPENDS}
|
||||
|
||||
list(APPEND BUN_ZIG_SOURCES
|
||||
${CWD}/build.zig
|
||||
${CWD}/root.zig
|
||||
${CWD}/root_wasm.zig
|
||||
${CWD}/src/main.zig
|
||||
${BUN_BINDGEN_ZIG_OUTPUTS}
|
||||
)
|
||||
|
||||
@@ -508,6 +535,7 @@ set(BUN_ZIG_GENERATED_SOURCES
|
||||
${BUN_FALLBACK_DECODER_OUTPUT}
|
||||
${BUN_RUNTIME_JS_OUTPUT}
|
||||
${BUN_NODE_FALLBACKS_OUTPUTS}
|
||||
${BUN_REACT_REFRESH_OUTPUT}
|
||||
${BUN_ERROR_CODE_OUTPUTS}
|
||||
${BUN_ZIG_GENERATED_CLASSES_OUTPUTS}
|
||||
${BUN_JAVASCRIPT_OUTPUTS}
|
||||
@@ -827,6 +855,15 @@ if(NOT WIN32)
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ENABLE_ASAN)
|
||||
target_compile_options(${bun} PUBLIC
|
||||
-fsanitize=address
|
||||
)
|
||||
target_link_libraries(${bun} PUBLIC
|
||||
-fsanitize=address
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_options(${bun} PUBLIC
|
||||
-Werror=return-type
|
||||
-Werror=return-stack-address
|
||||
@@ -1052,6 +1089,7 @@ add_custom_target(dependencies DEPENDS ${BUN_TARGETS})
|
||||
|
||||
if(APPLE)
|
||||
target_link_libraries(${bun} PRIVATE icucore resolv)
|
||||
target_compile_definitions(${bun} PRIVATE U_DISABLE_RENAMING=1)
|
||||
endif()
|
||||
|
||||
if(USE_STATIC_SQLITE)
|
||||
|
||||
@@ -4,7 +4,7 @@ register_repository(
|
||||
REPOSITORY
|
||||
oven-sh/mimalloc
|
||||
COMMIT
|
||||
82b2c2277a4d570187c07b376557dc5bde81d848
|
||||
1beadf9651a7bfdec6b5367c380ecc3fe1c40d1a
|
||||
)
|
||||
|
||||
set(MIMALLOC_CMAKE_ARGS
|
||||
@@ -19,6 +19,10 @@ set(MIMALLOC_CMAKE_ARGS
|
||||
-DMI_SKIP_COLLECT_ON_EXIT=ON
|
||||
)
|
||||
|
||||
if(ENABLE_ASAN)
|
||||
list(APPEND MIMALLOC_CMAKE_ARGS -DMI_TRACK_ASAN=ON)
|
||||
endif()
|
||||
|
||||
if(DEBUG)
|
||||
list(APPEND MIMALLOC_CMAKE_ARGS -DMI_DEBUG_FULL=ON)
|
||||
endif()
|
||||
|
||||
@@ -9,6 +9,14 @@ find_command(
|
||||
>=1.1.26
|
||||
)
|
||||
|
||||
if (NOT CI)
|
||||
# If node.js is not installed, it is extremely easy to make this path point to
|
||||
# a tempdir such as /private/tmp/bun-node-ce532901c/bun, which may cause this
|
||||
# CMake configuration break after tempdir is cleaned up (ex. after reboot).
|
||||
get_filename_component(BUN_EXECUTABLE ${BUN_EXECUTABLE} REALPATH)
|
||||
set(BUN_EXECUTABLE ${BUN_EXECUTABLE} CACHE FILEPATH "Bun executable" FORCE)
|
||||
endif()
|
||||
|
||||
# If this is not set, some advanced features are not checked.
|
||||
# https://github.com/oven-sh/bun/blob/cd7f6a1589db7f1e39dc4e3f4a17234afbe7826c/src/bun.js/javascript.zig#L1069-L1072
|
||||
setenv(BUN_GARBAGE_COLLECTOR_LEVEL 1)
|
||||
|
||||
@@ -2,7 +2,7 @@ option(WEBKIT_VERSION "The version of WebKit to use")
|
||||
option(WEBKIT_LOCAL "If a local version of WebKit should be used instead of downloading")
|
||||
|
||||
if(NOT WEBKIT_VERSION)
|
||||
set(WEBKIT_VERSION e6cb36cabed465c28c7bcbb28d86e8466ea36e8d)
|
||||
set(WEBKIT_VERSION 57004f91903936881b3301594d9d67708f1ff64c)
|
||||
endif()
|
||||
|
||||
string(SUBSTRING ${WEBKIT_VERSION} 0 16 WEBKIT_VERSION_PREFIX)
|
||||
@@ -79,6 +79,10 @@ else()
|
||||
set(WEBKIT_SUFFIX "${WEBKIT_SUFFIX}")
|
||||
endif()
|
||||
|
||||
if(ENABLE_ASAN)
|
||||
set(WEBKIT_SUFFIX "${WEBKIT_SUFFIX}-asan")
|
||||
endif()
|
||||
|
||||
set(WEBKIT_NAME bun-webkit-${WEBKIT_OS}-${WEBKIT_ARCH}${WEBKIT_SUFFIX})
|
||||
set(WEBKIT_FILENAME ${WEBKIT_NAME}.tar.gz)
|
||||
setx(WEBKIT_DOWNLOAD_URL https://github.com/oven-sh/WebKit/releases/download/autobuild-${WEBKIT_VERSION}/${WEBKIT_FILENAME})
|
||||
|
||||
@@ -20,8 +20,8 @@ else()
|
||||
unsupported(CMAKE_SYSTEM_NAME)
|
||||
endif()
|
||||
|
||||
optionx(ZIG_VERSION STRING "The zig version of the compiler to download" DEFAULT "0.13.0")
|
||||
optionx(ZIG_COMMIT STRING "The zig commit to use in oven-sh/zig" DEFAULT "131a009ba2eb127a3447d05b9e12f710429aa5ee")
|
||||
optionx(ZIG_VERSION STRING "The zig version of the compiler to download" DEFAULT "0.14.0-dev.2987+183bb8b08")
|
||||
optionx(ZIG_COMMIT STRING "The zig commit to use in oven-sh/zig" DEFAULT "02c57c7ee3b8fde7528c74dd06490834d2d6fae9")
|
||||
optionx(ZIG_TARGET STRING "The zig target to use" DEFAULT ${DEFAULT_ZIG_TARGET})
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
@@ -79,6 +79,7 @@ register_command(
|
||||
-DZIG_PATH=${ZIG_PATH}
|
||||
-DZIG_VERSION=${ZIG_VERSION}
|
||||
-DZIG_COMMIT=${ZIG_COMMIT}
|
||||
-DENABLE_ASAN=${ENABLE_ASAN}
|
||||
-P ${CWD}/cmake/scripts/DownloadZig.cmake
|
||||
SOURCES
|
||||
${CWD}/cmake/scripts/DownloadZig.cmake
|
||||
|
||||
@@ -67,14 +67,18 @@ ARG BUN_INSTALL_BIN=/usr/local/bin
|
||||
ENV BUN_INSTALL_BIN=${BUN_INSTALL_BIN}
|
||||
|
||||
COPY --from=build /usr/local/bin/bun /usr/local/bin/
|
||||
RUN mkdir -p /usr/local/bun-node-fallback-bin && ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node
|
||||
ENV PATH "${PATH}:/usr/local/bun-node-fallback-bin"
|
||||
|
||||
# Temporarily use the `build`-stage image binaries to create a symlink:
|
||||
RUN --mount=type=bind,from=build,source=/usr/bin,target=/usr/bin \
|
||||
--mount=type=bind,from=build,source=/bin,target=/bin <<EOF
|
||||
--mount=type=bind,from=build,source=/bin,target=/bin \
|
||||
--mount=type=bind,from=build,source=/usr/lib,target=/usr/lib \
|
||||
--mount=type=bind,from=build,source=/lib,target=/lib \
|
||||
<<EOF
|
||||
ln -s /usr/local/bin/bun /usr/local/bin/bunx
|
||||
which bunx
|
||||
mkdir -p /usr/local/bun-node-fallback-bin
|
||||
ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/nodebun
|
||||
EOF
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/bun"]
|
||||
|
||||
@@ -196,6 +196,8 @@ import icon from "./icon.png" with { type: "file" };
|
||||
import { file } from "bun";
|
||||
|
||||
const bytes = await file(icon).arrayBuffer();
|
||||
// await fs.promises.readFile(icon)
|
||||
// fs.readFileSync(icon)
|
||||
```
|
||||
|
||||
### Embed SQLite databases
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
As of Bun v1.1.44, we've added initial support for bundling frontend apps directly in Bun's HTTP server: `Bun.serve()`. Run your frontend and backend in the same app with no extra steps.
|
||||
Using `Bun.serve()`'s `static` option, you can run your frontend and backend in the same app with no extra steps.
|
||||
|
||||
To get started, import your HTML files and pass them to the `static` option in `Bun.serve()`.
|
||||
To get started, import HTML files and pass them to the `static` option in `Bun.serve()`.
|
||||
|
||||
```ts
|
||||
import dashboard from "./dashboard.html";
|
||||
@@ -33,7 +33,7 @@ const server = Bun.serve({
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`Listening on ${server.url}`)
|
||||
console.log(`Listening on ${server.url}`);
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -211,6 +211,7 @@ For example, enable TailwindCSS on your routes by installing and adding the `bun
|
||||
```sh
|
||||
$ bun add bun-plugin-tailwind
|
||||
```
|
||||
|
||||
```toml#bunfig.toml
|
||||
[serve.static]
|
||||
plugins = ["bun-plugin-tailwind"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
As of Bun v1.1.43, Bun's bundler now has first-class support for HTML. Build static sites, landing pages, and web applications with zero configuration. Just point Bun at your HTML file and it handles everything else.
|
||||
Bun's bundler has first-class support for HTML. Build static sites, landing pages, and web applications with zero configuration. Just point Bun at your HTML file and it handles everything else.
|
||||
|
||||
```html#index.html
|
||||
<!doctype html>
|
||||
@@ -13,45 +13,228 @@ As of Bun v1.1.43, Bun's bundler now has first-class support for HTML. Build sta
|
||||
</html>
|
||||
```
|
||||
|
||||
One command is all you need (won't be experimental after Bun v1.2):
|
||||
To get started, pass HTML files to `bun`.
|
||||
|
||||
{% bunDevServerTerminal alt="bun ./index.html" path="./index.html" routes="" /%}
|
||||
|
||||
Bun's development server provides powerful features with zero configuration:
|
||||
|
||||
- **Automatic Bundling** - Bundles and serves your HTML, JavaScript, and CSS
|
||||
- **Multi-Entry Support** - Handles multiple HTML entry points and glob entry points
|
||||
- **Modern JavaScript** - TypeScript & JSX support out of the box
|
||||
- **Smart Configuration** - Reads `tsconfig.json` for paths, JSX options, experimental decorators, and more
|
||||
- **Plugins** - Plugins for TailwindCSS and more
|
||||
- **ESM & CommonJS** - Use ESM and CommonJS in your JavaScript, TypeScript, and JSX files
|
||||
- **CSS Bundling & Minification** - Bundles CSS from `<link>` tags and `@import` statements
|
||||
- **Asset Management**
|
||||
- Automatic copying & hashing of images and assets
|
||||
- Rewrites asset paths in JavaScript, CSS, and HTML
|
||||
|
||||
## Single Page Apps (SPA)
|
||||
|
||||
When you pass a single .html file to Bun, Bun will use it as a fallback route for all paths. This makes it perfect for single page apps that use client-side routing:
|
||||
|
||||
{% bunDevServerTerminal alt="bun index.html" path="index.html" routes="" /%}
|
||||
|
||||
Your React or other SPA will work out of the box — no configuration needed. All routes like `/about`, `/users/123`, etc. will serve the same HTML file, letting your client-side router handle the navigation.
|
||||
|
||||
```html#index.html
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>My SPA</title>
|
||||
<script src="./app.tsx" type="module"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Multi-page apps (MPA)
|
||||
|
||||
Some projects have several separate routes or HTML files as entry points. To support multiple entry points, pass them all to `bun`
|
||||
|
||||
{% bunDevServerTerminal alt="bun ./index.html ./about.html" path="./index.html ./about.html" routes="[{\"path\": \"/\", \"file\": \"./index.html\"}, {\"path\": \"/about\", \"file\": \"./about.html\"}]" /%}
|
||||
|
||||
This will serve:
|
||||
|
||||
- `index.html` at `/`
|
||||
- `about.html` at `/about`
|
||||
|
||||
### Glob patterns
|
||||
|
||||
To specify multiple files, you can use glob patterns that end in `.html`:
|
||||
|
||||
{% bunDevServerTerminal alt="bun ./**/*.html" path="./**/*.html" routes="[{\"path\": \"/\", \"file\": \"./index.html\"}, {\"path\": \"/about\", \"file\": \"./about.html\"}]" /%}
|
||||
|
||||
### Path normalization
|
||||
|
||||
The base path is chosen from the longest common prefix among all the files.
|
||||
|
||||
{% bunDevServerTerminal alt="bun ./index.html ./about/index.html ./about/foo/index.html" path="./index.html ./about/index.html ./about/foo/index.html" routes="[{\"path\": \"/\", \"file\": \"./index.html\"}, {\"path\": \"/about\", \"file\": \"./about/index.html\"}, {\"path\": \"/about/foo\", \"file\": \"./about/foo/index.html\"}]" /%}
|
||||
|
||||
## JavaScript, TypeScript, and JSX
|
||||
|
||||
Bun's transpiler natively implements JavaScript, TypeScript, and JSX support. [Learn more about loaders in Bun](/docs/bundler/loaders).
|
||||
|
||||
Bun's transpiler is also used at runtime.
|
||||
|
||||
### ES Modules & CommonJS
|
||||
|
||||
You can use ESM and CJS in your JavaScript, TypeScript, and JSX files. Bun will handle the transpilation and bundling automatically.
|
||||
|
||||
There is no pre-build or separate optimization step. It's all done at the same time.
|
||||
|
||||
Learn more about [module resolution in Bun](/docs/runtime/modules).
|
||||
|
||||
## CSS
|
||||
|
||||
Bun's CSS parser is also natively implemented (clocking in around 58,000 lines of Zig).
|
||||
|
||||
It's also a CSS bundler. You can use `@import` in your CSS files to import other CSS files.
|
||||
|
||||
For example:
|
||||
|
||||
```css#styles.css
|
||||
@import "./abc.css";
|
||||
|
||||
.container {
|
||||
background-color: blue;
|
||||
}
|
||||
```
|
||||
|
||||
```css#abc.css
|
||||
body {
|
||||
background-color: red;
|
||||
}
|
||||
```
|
||||
|
||||
This outputs:
|
||||
|
||||
```css#styles.css
|
||||
body {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.container {
|
||||
background-color: blue;
|
||||
}
|
||||
```
|
||||
|
||||
### Referencing local assets in CSS
|
||||
|
||||
You can reference local assets in your CSS files.
|
||||
|
||||
```css#styles.css
|
||||
body {
|
||||
background-image: url("./logo.png");
|
||||
}
|
||||
```
|
||||
|
||||
This will copy `./logo.png` to the output directory and rewrite the path in the CSS file to include a content hash.
|
||||
|
||||
```css#styles.css
|
||||
body {
|
||||
background-image: url("./logo-[ABC123].png");
|
||||
}
|
||||
```
|
||||
|
||||
### Importing CSS in JavaScript
|
||||
|
||||
To associate a CSS file with a JavaScript file, you can import it in your JavaScript file.
|
||||
|
||||
```ts#app.ts
|
||||
import "./styles.css";
|
||||
import "./more-styles.css";
|
||||
```
|
||||
|
||||
This generates `./app.css` and `./app.js` in the output directory. All CSS files imported from JavaScript will be bundled into a single CSS file per entry point. If you import the same CSS file from multiple JavaScript files, it will only be included once in the output CSS file.
|
||||
|
||||
## Plugins
|
||||
|
||||
The dev server supports plugins.
|
||||
|
||||
### Tailwind CSS
|
||||
|
||||
To use TailwindCSS, install the `bun-plugin-tailwind` plugin:
|
||||
|
||||
```bash
|
||||
# Or any npm client
|
||||
$ bun install --dev bun-plugin-tailwind
|
||||
```
|
||||
|
||||
Then, add the plugin to your `bunfig.toml`:
|
||||
|
||||
```toml
|
||||
[serve.static]
|
||||
plugins = ["bun-plugin-tailwind"]
|
||||
```
|
||||
|
||||
Then, reference TailwindCSS in your HTML via `<link>` tag, `@import` in CSS, or `import` in JavaScript.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```html#index.html
|
||||
<!-- Reference TailwindCSS in your HTML -->
|
||||
<link rel="stylesheet" href="tailwindcss" />
|
||||
```
|
||||
|
||||
```css#styles.css
|
||||
/* Import TailwindCSS in your CSS */
|
||||
@import "tailwindcss";
|
||||
```
|
||||
|
||||
```ts#app.ts
|
||||
/* Import TailwindCSS in your JavaScript */
|
||||
import "tailwindcss";
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
Only one of those are necessary, not all three.
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
While the server is running:
|
||||
|
||||
- `o + Enter` - Open in browser
|
||||
- `c + Enter` - Clear console
|
||||
- `q + Enter` (or Ctrl+C) - Quit server
|
||||
|
||||
## Build for Production
|
||||
|
||||
When you're ready to deploy, use `bun build` to create optimized production bundles:
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```bash#CLI
|
||||
$ bun build ./index.html --outdir=dist
|
||||
$ bun build ./index.html --minify --outdir=dist
|
||||
```
|
||||
|
||||
```ts#API
|
||||
Bun.build({
|
||||
entrypoints: ["./index.html"],
|
||||
outdir: "./dist",
|
||||
minify: {
|
||||
whitespace: true,
|
||||
identifiers: true,
|
||||
syntax: true,
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
Bun automatically:
|
||||
Currently, plugins are only supported through `Bun.build`'s API or through `bunfig.toml` with the frontend dev server - not yet supported in `bun build`'s CLI.
|
||||
|
||||
- Bundles, tree-shakes, and optimizes your JavaScript, JSX and TypeScript
|
||||
- Bundles and optimizes your CSS
|
||||
- Copies & hashes images and other assets
|
||||
- Updates all references to local files or packages in your HTML
|
||||
### Watch Mode
|
||||
|
||||
## Zero Config, Maximum Performance
|
||||
|
||||
The HTML bundler is enabled by default after Bun v1.2+. Drop in your existing HTML files and Bun will handle:
|
||||
|
||||
- **TypeScript & JSX** - Write modern JavaScript for browsers without the setup
|
||||
- **CSS** - Bundle CSS stylesheets directly from `<link rel="stylesheet">` or `@import`
|
||||
- **Images & Assets** - Automatic copying & hashing & rewriting of assets in JavaScript, CSS, and HTML
|
||||
|
||||
## Watch mode
|
||||
|
||||
You can run `bun build --watch` to watch for changes and rebuild automatically.
|
||||
You can run `bun build --watch` to watch for changes and rebuild automatically. This works nicely for library development.
|
||||
|
||||
You've never seen a watch mode this fast.
|
||||
|
||||
## Plugin API
|
||||
### Plugin API
|
||||
|
||||
Need more control? Configure the bundler through the JavaScript API and use Bun's builtin `HTMLRewriter` to preprocess HTML.
|
||||
|
||||
@@ -102,3 +285,22 @@ Bun automatically handles all common web assets:
|
||||
- Any `<link>` tag with an `href` attribute pointing to a local file is rewritten to the new path, and hashed
|
||||
|
||||
All paths are resolved relative to your HTML file, making it easy to organize your project however you want.
|
||||
|
||||
## This is a work in progress
|
||||
|
||||
- No HMR support yet
|
||||
- Need more plugins
|
||||
- Need more configuration options for things like asset handling
|
||||
- Need a way to configure CORS, headers, etc.
|
||||
|
||||
If you want to submit a PR, most of the [code is here](https://github.com/oven-sh/bun/blob/main/src/js/internal/html.ts). You could even copy paste that file into your project and use it as a starting point.
|
||||
|
||||
## How this works
|
||||
|
||||
This is a small wrapper around Bun's support for HTML imports in JavaScript.
|
||||
|
||||
### Adding a backend to your frontend
|
||||
|
||||
To add a backend to your frontend, you can use the `"static"` option in `Bun.serve`.
|
||||
|
||||
Learn more in [the full-stack docs](/docs/bundler/fullstack).
|
||||
|
||||
@@ -1629,3 +1629,5 @@ declare class ResolveMessage {
|
||||
toString(): string;
|
||||
}
|
||||
```
|
||||
|
||||
{% bunCLIUsage command="build" /%}
|
||||
@@ -192,8 +192,6 @@ Otherwise, the database to embed is copied into the `outdir` with a hashed filen
|
||||
|
||||
### `html`
|
||||
|
||||
**HTML loader**. Default for `.html` after Bun v1.2.0.
|
||||
|
||||
The html loader processes HTML files and bundles any referenced assets. It will:
|
||||
|
||||
- Bundle and hash referenced JavaScript files (`<script src="...">`)
|
||||
|
||||
@@ -169,3 +169,5 @@ This will add the following line to your `package.json`:
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% bunCLIUsage command="add" /%}
|
||||
@@ -2,10 +2,97 @@
|
||||
**Note** — You don’t need `bun create` to use Bun. You don’t need any configuration at all. This command exists to make getting started a bit quicker and easier.
|
||||
{% /callout %}
|
||||
|
||||
Template a new Bun project with `bun create`. This is a flexible command that can be used to create a new project with a `create-<template>` npm package, a GitHub repo, or a local template.
|
||||
Template a new Bun project with `bun create`. This is a flexible command that can be used to create a new project from a React component, a `create-<template>` npm package, a GitHub repo, or a local template.
|
||||
|
||||
If you're looking to create a brand new empty project, use [`bun init`](https://bun.sh/docs/cli/init).
|
||||
|
||||
## From a React component
|
||||
|
||||
`bun create ./MyComponent.tsx` turns an existing React component into a complete dev environment with hot reload and production builds in one command.
|
||||
|
||||
```bash
|
||||
$ bun create ./MyComponent.jsx # .tsx also supported
|
||||
```
|
||||
|
||||
{% raw %}
|
||||
|
||||
<video style="aspect-ratio: 2062 / 1344; width: 100%; height: 100%; object-fit: contain;" loop autoplay muted playsinline>
|
||||
<source src="/bun-create-shadcn.mp4" style="width: 100%; height: 100%; object-fit: contain;" type="video/mp4">
|
||||
</video>
|
||||
|
||||
{% /raw %}
|
||||
|
||||
{% callout %}
|
||||
🚀 **Create React App Successor** — `bun create <component>` provides everything developers loved about Create React App, but with modern tooling, faster builds, and backend support.
|
||||
{% /callout %}
|
||||
|
||||
#### How this works
|
||||
|
||||
When you run `bun create <component>`, Bun:
|
||||
|
||||
1. Uses [Bun's JavaScript bundler](https://bun.sh/docs/bundler) to analyze your module graph.
|
||||
2. Collects all the dependencies needed to run the component.
|
||||
3. Scans the exports of the entry point for a React component.
|
||||
4. Generates a `package.json` file with the dependencies and scripts needed to run the component.
|
||||
5. Installs any missing dependencies using [`bun install --only-missing`](https://bun.sh/docs/cli/install).
|
||||
6. Generates the following files:
|
||||
- `${component}.html`
|
||||
- `${component}.client.tsx` (entry point for the frontend)
|
||||
- `${component}.css` (css file)
|
||||
7. Starts a frontend dev server automatically.
|
||||
|
||||
### Using TailwindCSS with Bun
|
||||
|
||||
[TailwindCSS](https://tailwindcss.com/) is an extremely popular utility-first CSS framework used to style web applications.
|
||||
|
||||
When you run `bun create <component>`, Bun scans your JSX/TSX file for TailwindCSS class names (and any files it imports). If it detects TailwindCSS class names, it will add the following dependencies to your `package.json`:
|
||||
|
||||
```json#package.json
|
||||
{
|
||||
"dependencies": {
|
||||
"tailwindcss": "^4",
|
||||
"bun-plugin-tailwind": "latest"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We also configure `bunfig.toml` to use Bun's TailwindCSS plugin with `Bun.serve()`
|
||||
|
||||
```toml#bunfig.toml
|
||||
[serve.static]
|
||||
plugins = ["bun-plugin-tailwind"]
|
||||
```
|
||||
|
||||
And a `${component}.css` file with `@import "tailwindcss";` at the top:
|
||||
|
||||
```css#MyComponent.css
|
||||
@import "tailwindcss";
|
||||
```
|
||||
|
||||
### Using `shadcn/ui` with Bun
|
||||
|
||||
[`shadcn/ui`](https://ui.shadcn.com/) is an extremely popular component library tool for building web applications.
|
||||
|
||||
`bun create <component>` scans for any shadcn/ui components imported from `@/components/ui`.
|
||||
|
||||
If it finds any, it runs:
|
||||
|
||||
```bash
|
||||
# Assuming bun detected imports to @/components/ui/accordion and @/components/ui/button
|
||||
$ bunx shadcn@canary add accordion button # and any other components
|
||||
```
|
||||
|
||||
Since `shadcn/ui` itself uses TailwindCSS, `bun create` also adds the necessary TailwindCSS dependencies to your `package.json` and configures `bunfig.toml` to use Bun's TailwindCSS plugin with `Bun.serve()` as described above.
|
||||
|
||||
Additionally, we setup the following:
|
||||
|
||||
- `tsconfig.json` to alias `"@/*"` to `"src/*"` or `.` (depending on if there is a `src/` directory)
|
||||
- `components.json` so that shadcn/ui knows its a shadcn/ui project
|
||||
- `styles/globals.css` file that configures Tailwind v4 in the way that shadcn/ui expects
|
||||
- `${component}.build.ts` file that builds the component for production with `bun-plugin-tailwind` configured
|
||||
|
||||
`bun create ./MyComponent.jsx` is one of the easiest ways to run code generated from LLMs like [Claude](https://claude.ai) or ChatGPT locally.
|
||||
|
||||
## From `npm`
|
||||
|
||||
```sh
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
In your project folder root (where `package.json` is):
|
||||
|
||||
```bash
|
||||
$ bun bun ./entry-point-1.js ./entry-point-2.jsx
|
||||
$ bun dev
|
||||
```
|
||||
|
||||
By default, `bun dev` will look for any HTML files in the `public` directory and serve that. For browsers navigating to the page, the `.html` file extension is optional in the URL, and `index.html` will automatically rewrite for the directory.
|
||||
|
||||
Here are examples of routing from `public/` and how they’re matched:
|
||||
| Dev Server URL | File Path |
|
||||
|----------------|-----------|
|
||||
| /dir | public/dir/index.html |
|
||||
| / | public/index.html |
|
||||
| /index | public/index.html |
|
||||
| /hi | public/hi.html |
|
||||
| /file | public/file.html |
|
||||
| /font/Inter.woff2 | public/font/Inter.woff2 |
|
||||
| /hello | public/index.html |
|
||||
|
||||
If `public/index.html` exists, it becomes the default page instead of a 404 page, unless that pathname has a file extension.
|
||||
@@ -38,3 +38,5 @@ If you pass `-y` or `--yes`, it will assume you want to continue without asking
|
||||
At the end, it runs `bun install` to install `@types/bun`.
|
||||
|
||||
{% /details %}
|
||||
|
||||
{% bunCLIUsage command="init" /%}
|
||||
|
||||
@@ -235,3 +235,5 @@ jobs:
|
||||
- name: Build app
|
||||
run: bun run build
|
||||
```
|
||||
|
||||
{% bunCLIUsage command="install" /%}
|
||||
|
||||
@@ -36,3 +36,5 @@ In addition, the `--save` flag can be used to add `cool-pkg` to the `dependencie
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% bunCLIUsage command="link" /%}
|
||||
@@ -1,63 +1,47 @@
|
||||
Use `bun outdated` to display a table of outdated dependencies with their latest versions for the current workspace:
|
||||
Use `bun outdated` to check for outdated dependencies in your project. This command displays a table of dependencies that have newer versions available.
|
||||
|
||||
```sh
|
||||
$ bun outdated
|
||||
{% bunOutdatedTerminal displayGlob="" filter="" glob="" /%}
|
||||
|
||||
|--------------------------------------------------------------------|
|
||||
| Package | Current | Update | Latest |
|
||||
|----------------------------------------|---------|--------|--------|
|
||||
| @types/bun (dev) | 1.1.6 | 1.1.7 | 1.1.7 |
|
||||
|----------------------------------------|---------|--------|--------|
|
||||
| @types/react (dev) | 18.3.3 | 18.3.4 | 18.3.4 |
|
||||
|----------------------------------------|---------|--------|--------|
|
||||
| @typescript-eslint/eslint-plugin (dev) | 7.16.1 | 7.18.0 | 8.2.0 |
|
||||
|----------------------------------------|---------|--------|--------|
|
||||
| @typescript-eslint/parser (dev) | 7.16.1 | 7.18.0 | 8.2.0 |
|
||||
|----------------------------------------|---------|--------|--------|
|
||||
| esbuild (dev) | 0.21.5 | 0.21.5 | 0.23.1 |
|
||||
|----------------------------------------|---------|--------|--------|
|
||||
| eslint (dev) | 9.7.0 | 9.9.1 | 9.9.1 |
|
||||
|----------------------------------------|---------|--------|--------|
|
||||
| typescript (dev) | 5.5.3 | 5.5.4 | 5.5.4 |
|
||||
|--------------------------------------------------------------------|
|
||||
```
|
||||
## Version Information
|
||||
|
||||
The `Update` column shows the version that would be installed if you ran `bun update [package]`. This version is the latest version that satisfies the version range specified in your `package.json`.
|
||||
The output table shows three version columns:
|
||||
|
||||
The `Latest` column shows the latest version available from the registry. `bun update --latest [package]` will update to this version.
|
||||
- **Current**: The version currently installed
|
||||
- **Update**: The latest version that satisfies your package.json version range
|
||||
- **Latest**: The latest version published to the registry
|
||||
|
||||
Dependency names can be provided to filter the output (pattern matching is supported):
|
||||
### Dependency Filters
|
||||
|
||||
```sh
|
||||
$ bun outdated "@types/*"
|
||||
`bun outdated` supports searching for outdated dependencies by package names and glob patterns.
|
||||
|
||||
|------------------------------------------------|
|
||||
| Package | Current | Update | Latest |
|
||||
|--------------------|---------|--------|--------|
|
||||
| @types/bun (dev) | 1.1.6 | 1.1.8 | 1.1.8 |
|
||||
|--------------------|---------|--------|--------|
|
||||
| @types/react (dev) | 18.3.3 | 18.3.4 | 18.3.4 |
|
||||
|------------------------------------------------|
|
||||
```
|
||||
To check if specific dependencies are outdated, pass the package names as positional arguments:
|
||||
|
||||
## `--filter`
|
||||
{% bunOutdatedTerminal displayGlob="eslint-plugin-security eslint-plugin-sonarjs" glob="eslint-plugin-*" /%}
|
||||
|
||||
The `--filter` flag can be used to select workspaces to include in the output. Workspace names or paths can be used as patterns.
|
||||
You can also pass glob patterns to check for outdated packages:
|
||||
|
||||
```sh
|
||||
$ bun outdated --filter <pattern>
|
||||
```
|
||||
{% bunOutdatedTerminal displayGlob="'eslint*'" glob="eslint*" /%}
|
||||
|
||||
For example, to only show outdated dependencies for workspaces in the `./apps` directory:
|
||||
For example, to check for outdated `@types/*` packages:
|
||||
|
||||
```sh
|
||||
$ bun outdated --filter './apps/*'
|
||||
```
|
||||
{% bunOutdatedTerminal displayGlob="'@types/*'" glob="@types/*" /%}
|
||||
|
||||
If you want to do the same, but exclude the `./apps/api` workspace:
|
||||
Or to exclude all `@types/*` packages:
|
||||
|
||||
```sh
|
||||
$ bun outdated --filter './apps/*' --filter '!./apps/api'
|
||||
```
|
||||
{% bunOutdatedTerminal displayGlob="'!@types/*'" glob="!@types/*" /%}
|
||||
|
||||
Refer to [Package Manager > Filtering](https://bun.sh/docs/cli/filter#bun-install-and-bun-outdated) for more information on `--filter`.
|
||||
### Workspace Filters
|
||||
|
||||
Use the `--filter` flag to check for outdated dependencies in a different workspace package:
|
||||
|
||||
{% bunOutdatedTerminal glob="t*" filter="@monorepo/types" /%}
|
||||
|
||||
You can pass multiple `--filter` flags to check multiple workspaces:
|
||||
|
||||
{% bunOutdatedTerminal glob="{e,t}*" displayGlob="--filter @monorepo/types --filter @monorepo/cli" /%}
|
||||
|
||||
You can also pass glob patterns to filter by workspace names:
|
||||
|
||||
{% bunOutdatedTerminal glob="{e,t}*" displayGlob="--filter='@monorepo/{types,cli}'" /%}
|
||||
|
||||
{% bunCLIUsage command="outdated" /%}
|
||||
|
||||
@@ -7,3 +7,5 @@ To get started with patch, first prepare the package for patching with [`bun pat
|
||||
By default, `bun patch-commit` will use the `patches` directory in the temporary directory.
|
||||
|
||||
You can specify a different directory with the `--patches-dir` flag.
|
||||
|
||||
{% bunCLIUsage command="patch-commit" /%}
|
||||
@@ -105,3 +105,4 @@ $ bun publish --otp 123456
|
||||
### `--gzip-level`
|
||||
|
||||
Specify the level of gzip compression to use when packing the package. Only applies to `bun publish` without a tarball path argument. Values range from `0` to `9` (default is `9`).
|
||||
{% bunCLIUsage command="publish" /%}
|
||||
@@ -3,3 +3,5 @@ To remove a dependency:
|
||||
```bash
|
||||
$ bun remove ts-node
|
||||
```
|
||||
|
||||
{% bunCLIUsage command="remove" /%}
|
||||
|
||||
@@ -205,3 +205,5 @@ When there is a package.json script and a file with the same name, `bun run` pri
|
||||
2. Source files, eg `bun run src/main.js`
|
||||
3. Binaries from project packages, eg `bun add eslint && bun run eslint`
|
||||
4. (`bun run` only) System commands, eg `bun run ls`
|
||||
|
||||
{% bunCLIUsage command="run" /%}
|
||||
@@ -247,3 +247,5 @@ $ bun test foo
|
||||
```
|
||||
|
||||
Any test file in the directory with an _absolute path_ that contains one of the targets will run. Glob patterns are not yet supported. -->
|
||||
|
||||
{% bunCLIUsage command="test" /%}
|
||||
|
||||
@@ -5,3 +5,5 @@ $ cd /path/to/cool-pkg
|
||||
$ bun unlink
|
||||
bun unlink v1.x (7416672e)
|
||||
```
|
||||
|
||||
{% bunCLIUsage command="unlink" /%}
|
||||
|
||||
@@ -32,3 +32,5 @@ For example, with the following `package.json`:
|
||||
|
||||
- `bun update` would update to a version that matches `17.x`.
|
||||
- `bun update --latest` would update to a version that matches `18.x` or later.
|
||||
|
||||
{% bunCLIUsage command="update" /%}
|
||||
@@ -98,7 +98,7 @@ import { Database } from "bun:sqlite";
|
||||
|
||||
const sqlite = new Database("sqlite.db");
|
||||
const db = drizzle(sqlite);
|
||||
await migrate(db, { migrationsFolder: "./drizzle" });
|
||||
migrate(db, { migrationsFolder: "./drizzle" });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
# ...
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
+ with:
|
||||
+ bun-version: 1.0.11 # or "latest", "canary", <sha>
|
||||
+ bun-version: 1.2.0 # or "latest", "canary", <sha>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
37
docs/guides/runtime/delete-directory.md
Normal file
37
docs/guides/runtime/delete-directory.md
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
name: Delete directories
|
||||
---
|
||||
|
||||
To recursively delete a directory and all its contents, use `rm` from `node:fs/promises`. This is like running `rm -rf` in JavaScript.
|
||||
|
||||
```ts
|
||||
import { rm } from "node:fs/promises";
|
||||
|
||||
// Delete a directory and all its contents
|
||||
await rm("path/to/directory", { recursive: true, force: true });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
These options configure the deletion behavior:
|
||||
|
||||
- `recursive: true` - Delete subdirectories and their contents
|
||||
- `force: true` - Don't throw errors if the directory doesn't exist
|
||||
|
||||
You can also use it without `force` to ensure the directory exists:
|
||||
|
||||
```ts
|
||||
try {
|
||||
await rm("path/to/directory", { recursive: true });
|
||||
} catch (error) {
|
||||
if (error.code === "ENOENT") {
|
||||
console.log("Directory doesn't exist");
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
See [Docs > API > FileSystem](https://bun.sh/docs/api/file-io) for more filesystem operations.
|
||||
19
docs/guides/runtime/delete-file.md
Normal file
19
docs/guides/runtime/delete-file.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Delete files
|
||||
---
|
||||
|
||||
To delete a file, use `Bun.file(path).delete()`.
|
||||
|
||||
```ts
|
||||
// Delete a file
|
||||
const file = Bun.file("path/to/file.txt");
|
||||
await file.delete();
|
||||
|
||||
// Now the file doesn't exist
|
||||
const exists = await file.exists();
|
||||
// => false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
See [Docs > API > FileSystem](https://bun.sh/docs/api/file-io) for more filesystem operations.
|
||||
26
docs/guides/runtime/heap-snapshot.md
Normal file
26
docs/guides/runtime/heap-snapshot.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: Inspect memory usage using V8 heap snapshots
|
||||
---
|
||||
|
||||
Bun implements V8's heap snapshot API, which allows you to create snapshots of the heap at runtime. This helps debug memory leaks in your JavaScript/TypeScript application.
|
||||
|
||||
```ts#snapshot.ts
|
||||
import v8 from "node:v8";
|
||||
|
||||
// Creates a heap snapshot file with an auto-generated name
|
||||
const snapshotPath = v8.writeHeapSnapshot();
|
||||
console.log(`Heap snapshot written to: ${snapshotPath}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Inspect memory in Chrome DevTools
|
||||
|
||||
To view V8 heap snapshots in Chrome DevTools:
|
||||
|
||||
1. Open Chrome DevTools (F12 or right-click and select "Inspect")
|
||||
2. Go to the "Memory" tab
|
||||
3. Click the "Load" button (folder icon)
|
||||
4. Select your `.heapsnapshot` file
|
||||
|
||||
{% image src="/images/chrome-devtools-memory.png" alt="Chrome DevTools Memory Tab" width="100%" /%}
|
||||
@@ -55,3 +55,5 @@ $ bun patch --commit react --patches-dir=mypatches
|
||||
# `patch-commit` is available for compatibility with pnpm
|
||||
$ bun patch-commit react
|
||||
```
|
||||
|
||||
{% bunCLIUsage command="patch" /%}
|
||||
@@ -94,7 +94,9 @@ $ bun --revision
|
||||
|
||||
If you've installed Bun but are seeing a `command not found` error, you may have to manually add the installation directory (`~/.bun/bin`) to your `PATH`.
|
||||
|
||||
{% details summary="How to add to your `PATH`" %}
|
||||
### How to add your `PATH`
|
||||
|
||||
{% details summary="Linux / Mac" %}
|
||||
First, determine what shell you're using:
|
||||
|
||||
```sh
|
||||
@@ -129,6 +131,26 @@ Save the file. You'll need to open a new shell/terminal window for the changes t
|
||||
|
||||
{% /details %}
|
||||
|
||||
{% details summary="Windows" %}
|
||||
First, determine if the bun binary is properly installed on your system:
|
||||
|
||||
```pwsh
|
||||
& "$env:USERPROFILE\.bun\bin\bun" --version
|
||||
```
|
||||
|
||||
If the command runs successfully but `bun --version` is not recognized, it means that bun is not in your system's `PATH`. To fix this, open a Powershell terminal and run the following command:
|
||||
|
||||
```pwsh
|
||||
[System.Environment]::SetEnvironmentVariable(
|
||||
"Path",
|
||||
[System.Environment]::GetEnvironmentVariable("Path", "User") + ";$env:USERPROFILE\.bun\bin",
|
||||
[System.EnvironmentVariableTarget]::User
|
||||
)
|
||||
```
|
||||
After running the command, restart your terminal and test with `bun --version`
|
||||
|
||||
{% /details %}
|
||||
|
||||
## Upgrading
|
||||
|
||||
Once installed, the binary can upgrade itself.
|
||||
|
||||
11
docs/nav.ts
11
docs/nav.ts
@@ -27,7 +27,7 @@ export default {
|
||||
divider("Intro"),
|
||||
page("index", "What is Bun?", {
|
||||
description:
|
||||
"Bun is an all-in-one runtime for JavaScript and TypeScript apps. Run, bundle, and test apps with one fast tool.",
|
||||
"Bun is an all-in-one runtime for JavaScript and TypeScript apps. Build, run, and test apps with one fast tool.",
|
||||
}),
|
||||
page("installation", "Installation", {
|
||||
description: "Install Bun with npm, Homebrew, Docker, or the official install script.",
|
||||
@@ -181,7 +181,7 @@ export default {
|
||||
"Bun's package manager installs all packages into a shared global cache to avoid redundant re-downloads.",
|
||||
}),
|
||||
page("install/workspaces", "Workspaces", {
|
||||
description: "Bun's package manager supports workspaces and mono-repo development workflows.",
|
||||
description: "Bun's package manager supports workspaces and monorepo development workflows.",
|
||||
}),
|
||||
page("install/lifecycle", "Lifecycle scripts", {
|
||||
description: "How Bun handles package lifecycle scripts with trustedDependencies",
|
||||
@@ -194,7 +194,8 @@ export default {
|
||||
"Bun's lockfile `bun.lock` tracks your resolved dependency tree, making future installs fast and repeatable.",
|
||||
}),
|
||||
page("install/registries", "Scopes and registries", {
|
||||
description: "How to configure private scopes and custom package registries.",
|
||||
description:
|
||||
"How to configure private scopes, custom package registries, authenticating with npm token, and more.",
|
||||
}),
|
||||
page("install/overrides", "Overrides and resolutions", {
|
||||
description: "Specify version ranges for nested dependencies",
|
||||
@@ -214,8 +215,8 @@ export default {
|
||||
page("bundler", "`Bun.build`", {
|
||||
description: "Bundle code for consumption in the browser with Bun's native bundler.",
|
||||
}),
|
||||
page("bundler/html", "HTML", {
|
||||
description: `Bundle html files with Bun's native bundler.`,
|
||||
page("bundler/html", "Bundle frontend & static sites", {
|
||||
description: `Zero-config HTML bundler for single-page apps and multi-page apps. Automatic bundling, TailwindCSS plugins, TypeScript, JSX, React support, and incredibly fast builds`,
|
||||
}),
|
||||
page("bundler/fullstack", "Fullstack Dev Server", {
|
||||
description: "Serve your frontend and backend from the same app with Bun's dev server.",
|
||||
|
||||
@@ -180,6 +180,25 @@ Whether to skip test files when computing coverage statistics. Default `false`.
|
||||
coverageSkipTestFiles = false
|
||||
```
|
||||
|
||||
### `test.coverageReporter`
|
||||
|
||||
By default, coverage reports will be printed to the console. For persistent code coverage reports in CI environments and for other tools use `lcov`.
|
||||
|
||||
```toml
|
||||
[test]
|
||||
coverageReporter = ["text", "lcov"] # default ["text"]
|
||||
```
|
||||
|
||||
### `test.coverageDir`
|
||||
|
||||
Set path where coverage reports will be saved. Please notice, that it works only for persistent `coverageReporter` like `lcov`.
|
||||
|
||||
```toml
|
||||
[test]
|
||||
coverageDir = "path/to/somewhere" # default "coverage"
|
||||
```
|
||||
|
||||
|
||||
## Package manager
|
||||
|
||||
Package management is a complex issue; to support a range of use cases, the behavior of `bun install` can be configured under the `[install]` section.
|
||||
|
||||
@@ -56,9 +56,9 @@ By default, `await`ing will return stdout and stderr as `Buffer`s.
|
||||
```js
|
||||
import { $ } from "bun";
|
||||
|
||||
const { stdout, stderr } = await $`echo "Hello World!"`.quiet();
|
||||
const { stdout, stderr } = await $`echo "Hello!"`.quiet();
|
||||
|
||||
console.log(stdout); // Buffer(6) [ 72, 101, 108, 108, 111, 32 ]
|
||||
console.log(stdout); // Buffer(7) [ 72, 101, 108, 108, 111, 33, 10 ]
|
||||
console.log(stderr); // Buffer(0) []
|
||||
```
|
||||
|
||||
|
||||
@@ -58,3 +58,82 @@ export const foo = "Hello world!"
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
## Experimental Decorators
|
||||
|
||||
Bun supports the pre-TypeScript 5.0 experimental decorators syntax.
|
||||
|
||||
```ts#hello.ts
|
||||
// Simple logging decorator
|
||||
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
const originalMethod = descriptor.value;
|
||||
|
||||
descriptor.value = function(...args: any[]) {
|
||||
console.log(`Calling ${propertyKey} with:`, args);
|
||||
return originalMethod.apply(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
class Example {
|
||||
@log
|
||||
greet(name: string) {
|
||||
return `Hello ${name}!`;
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
const example = new Example();
|
||||
example.greet("world"); // Logs: "Calling greet with: ['world']"
|
||||
```
|
||||
|
||||
To enable it, add `"experimentalDecorators": true` to your `tsconfig.json`:
|
||||
|
||||
```jsonc#tsconfig.json
|
||||
{
|
||||
"compilerOptions": {
|
||||
// ... rest of your config
|
||||
"experimentalDecorators": true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
We generally don't recommend using this in new codebases, but plenty of existing codebases have come to rely on it.
|
||||
|
||||
### emitDecoratorMetadata
|
||||
|
||||
Bun supports `emitDecoratorMetadata` in your `tsconfig.json`. This enables emitting design-time type metadata for decorated declarations in source files.
|
||||
|
||||
```ts#emit-decorator-metadata.ts
|
||||
import "reflect-metadata";
|
||||
|
||||
class User {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
function Injectable(target: Function) {
|
||||
// Get metadata about constructor parameters
|
||||
const params = Reflect.getMetadata("design:paramtypes", target);
|
||||
console.log("Dependencies:", params); // [User]
|
||||
}
|
||||
|
||||
@Injectable
|
||||
class UserService {
|
||||
constructor(private user: User) {}
|
||||
}
|
||||
|
||||
// Creates new UserService instance with dependencies
|
||||
const container = new UserService(new User());
|
||||
```
|
||||
|
||||
To enable it, add `"emitDecoratorMetadata": true` to your `tsconfig.json`:
|
||||
|
||||
```jsonc#tsconfig.json
|
||||
{
|
||||
"compilerOptions": {
|
||||
// ... rest of your config
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "macros",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "simple-react",
|
||||
@@ -1659,7 +1659,7 @@
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"ws": ["ws@7.5.9", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="],
|
||||
"ws": ["ws@7.5.9", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="],
|
||||
|
||||
"xml-name-validator": ["xml-name-validator@3.0.0", "", {}, "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="],
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
process handle -p true -s false -n false SIGUSR1
|
||||
# Tell LLDB what to do when the debugged process receives SIGPWR: pass it through to the process
|
||||
# (-p), but do not stop the process (-s) or notify the user (-n).
|
||||
#
|
||||
# JSC's garbage collector sends this signal (as configured by Bun WebKit in
|
||||
# Thread::initializePlatformThreading() in ThreadingPOSIX.cpp) to the JS thread to suspend or resume
|
||||
# it. So stopping the process would just create noise when debugging any long-running script.
|
||||
process handle -p true -s false -n false SIGPWR
|
||||
|
||||
command script import misctools/lldb/lldb_pretty_printers.py
|
||||
type category enable zig.lang
|
||||
|
||||
@@ -35,7 +35,7 @@ fn spamMe(count: usize) void {
|
||||
while (i < count) : (i += 1) {
|
||||
waker.wake() catch unreachable;
|
||||
}
|
||||
Output.prettyErrorln("[EVFILT_MACHPORT] Sent {any}", .{bun.fmt.fmtDuration(timer.read())});
|
||||
Output.prettyErrorln("[EVFILT_MACHPORT] Sent {any}", .{std.fmt.fmtDuration(timer.read())});
|
||||
}
|
||||
const thread_count = 1;
|
||||
pub fn machMain(runs: usize) anyerror!void {
|
||||
@@ -67,7 +67,7 @@ pub fn machMain(runs: usize) anyerror!void {
|
||||
elapsed += timer.read();
|
||||
}
|
||||
|
||||
Output.prettyErrorln("[EVFILT_MACHPORT] Recv {any}", .{bun.fmt.fmtDuration(elapsed)});
|
||||
Output.prettyErrorln("[EVFILT_MACHPORT] Recv {any}", .{std.fmt.fmtDuration(elapsed)});
|
||||
}
|
||||
var user_waker: bun.Async.UserFilterWaker = undefined;
|
||||
|
||||
@@ -80,7 +80,7 @@ fn spamMeUserFilter(count: usize) void {
|
||||
user_waker.wake() catch unreachable;
|
||||
}
|
||||
|
||||
Output.prettyErrorln("[EVFILT_USER] Sent {any}", .{bun.fmt.fmtDuration(timer.read())});
|
||||
Output.prettyErrorln("[EVFILT_USER] Sent {any}", .{std.fmt.fmtDuration(timer.read())});
|
||||
}
|
||||
pub fn userMain(runs: usize) anyerror!void {
|
||||
defer Output.flush();
|
||||
@@ -111,7 +111,7 @@ pub fn userMain(runs: usize) anyerror!void {
|
||||
elapsed += timer.read();
|
||||
}
|
||||
|
||||
Output.prettyErrorln("[EVFILT_USER] Recv {any}", .{bun.fmt.fmtDuration(elapsed)});
|
||||
Output.prettyErrorln("[EVFILT_USER] Recv {any}", .{std.fmt.fmtDuration(elapsed)});
|
||||
Output.flush();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"build",
|
||||
"test/snapshots/**",
|
||||
"bench/react-hello-world/*.js",
|
||||
"bun.lock",
|
||||
|
||||
"test/js/node/**/parallel/**",
|
||||
"test/js/node/test/fixtures", // full of JS with intentional syntax errors
|
||||
|
||||
10
package.json
10
package.json
@@ -1,16 +1,19 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "bun",
|
||||
"version": "1.2.1",
|
||||
"version": "1.2.3",
|
||||
"workspaces": [
|
||||
"./packages/bun-types"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@mdn/browser-compat-data": "~5.5.28",
|
||||
"@types/bun": "*",
|
||||
"@types/react": "^18.3.3",
|
||||
"@typescript-eslint/eslint-plugin": "^7.11.0",
|
||||
"@typescript-eslint/parser": "^7.11.0",
|
||||
"@vscode/debugadapter": "^1.65.0",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"caniuse-lite": "^1.0.30001620",
|
||||
"esbuild": "^0.21.4",
|
||||
"eslint": "^9.4.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
@@ -21,10 +24,7 @@
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"source-map-js": "^1.2.0",
|
||||
"typescript": "^5.7.2",
|
||||
"caniuse-lite": "^1.0.30001620",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"@mdn/browser-compat-data": "~5.5.28"
|
||||
"typescript": "^5.7.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"bun-types": "workspace:packages/bun-types"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bun-debug-adapter-protocol",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "web-inspector-bun",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bun-inspector-protocol",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
"@types/p-queue": ["@types/p-queue@3.2.1", "", { "dependencies": { "p-queue": "*" } }, "sha512-tgAdn5zEs05NuHzOyRM34cMO0rczStphR/kLo/ZJwwwJ5S2+QVxwA6gST3vDHWPB1oDfUuT6wOouhJvJkBCA0w=="],
|
||||
|
||||
"bun": ["bun@workspace:runners/bun", {}],
|
||||
"bun": ["bun@workspace:runners/bun"],
|
||||
|
||||
"bun-types": ["bun-types@1.0.4-canary.20230929T233451", "", {}, "sha512-Ke/y3GX0T2ZYKx0UKKCnFRRP9bXzVRcRZCrIlF5/aRNEpgbfrMBw+s5imPqrV2CqJ7q6kIbMikCahzMr4N9PTg=="],
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
"prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="],
|
||||
|
||||
"qunit": ["qunit@workspace:runners/qunit", {}],
|
||||
"qunit": ["qunit@workspace:runners/qunit"],
|
||||
|
||||
"tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="],
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
|
||||
@@ -2,16 +2,12 @@
|
||||
name = "bun-native-plugin"
|
||||
description = "Rustified wrapper for writing native plugins for Bun."
|
||||
license = "MIT"
|
||||
version = "0.1.2"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.94"
|
||||
# use local path in dev and publish to crates.io in prod
|
||||
bun-macro = { path = "./bun-macro", version = "0.1.0" }
|
||||
napi = { version = "2.14.1", default-features = false, features = ["napi4"] }
|
||||
|
||||
[features]
|
||||
default = ["napi"]
|
||||
napi = []
|
||||
|
||||
|
||||
@@ -473,6 +473,10 @@ impl<'a> OnBeforeParse<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// This is unsafe as you must ensure that no other invocation of the plugin (or JS!)
|
||||
/// simultaneously holds a mutable reference to the external.
|
||||
///
|
||||
/// Get the external object from the `OnBeforeParse` arguments.
|
||||
///
|
||||
/// The external object is set by the plugin definition inside of JS:
|
||||
@@ -521,42 +525,35 @@ impl<'a> OnBeforeParse<'a> {
|
||||
/// },
|
||||
/// };
|
||||
/// ```
|
||||
pub unsafe fn external<T: 'static + Sync>(&self) -> PluginResult<Option<&'static T>> {
|
||||
pub unsafe fn external<'b, T: 'static + Sync>(
|
||||
&self,
|
||||
from_raw: unsafe fn(*mut c_void) -> Option<&'b T>,
|
||||
) -> PluginResult<Option<&'b T>> {
|
||||
if unsafe { (*self.args_raw).external.is_null() } {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let external: *mut TaggedObject<T> =
|
||||
unsafe { (*self.args_raw).external as *mut TaggedObject<T> };
|
||||
let external = unsafe { from_raw((*self.args_raw).external as *mut _) };
|
||||
|
||||
unsafe {
|
||||
if (*external).type_id != TypeId::of::<T>() {
|
||||
return Err(Error::ExternalTypeMismatch);
|
||||
}
|
||||
|
||||
Ok((*external).object.as_ref())
|
||||
}
|
||||
Ok(external)
|
||||
}
|
||||
|
||||
/// The same as [`crate::bun_native_plugin::OnBeforeParse::external`], but returns a mutable reference.
|
||||
///
|
||||
/// This is unsafe as you must ensure that no other invocation of the plugin
|
||||
/// # Safety
|
||||
/// This is unsafe as you must ensure that no other invocation of the plugin (or JS!)
|
||||
/// simultaneously holds a mutable reference to the external.
|
||||
pub unsafe fn external_mut<T: 'static + Sync>(&mut self) -> PluginResult<Option<&mut T>> {
|
||||
pub unsafe fn external_mut<'b, T: 'static + Sync>(
|
||||
&mut self,
|
||||
from_raw: unsafe fn(*mut c_void) -> Option<&'b mut T>,
|
||||
) -> PluginResult<Option<&'b mut T>> {
|
||||
if unsafe { (*self.args_raw).external.is_null() } {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let external: *mut TaggedObject<T> =
|
||||
unsafe { (*self.args_raw).external as *mut TaggedObject<T> };
|
||||
let external = unsafe { from_raw((*self.args_raw).external as *mut _) };
|
||||
|
||||
unsafe {
|
||||
if (*external).type_id != TypeId::of::<T>() {
|
||||
return Err(Error::ExternalTypeMismatch);
|
||||
}
|
||||
|
||||
Ok((*external).object.as_mut())
|
||||
}
|
||||
Ok(external)
|
||||
}
|
||||
|
||||
/// Get the input source code for the current file.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bun-plugin",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bun-polyfills",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
|
||||
73
packages/bun-types/bun.d.ts
vendored
73
packages/bun-types/bun.d.ts
vendored
@@ -2009,35 +2009,51 @@ declare module "bun" {
|
||||
*/
|
||||
type SQLOptions = {
|
||||
/** Connection URL (can be string or URL object) */
|
||||
url: URL | string;
|
||||
url?: URL | string;
|
||||
/** Database server hostname */
|
||||
host: string;
|
||||
host?: string;
|
||||
/** Database server hostname (alias for host) */
|
||||
hostname?: string;
|
||||
/** Database server port number */
|
||||
port: number | string;
|
||||
port?: number | string;
|
||||
/** Database user for authentication */
|
||||
username: string;
|
||||
username?: string;
|
||||
/** Database user for authentication (alias for username) */
|
||||
user?: string;
|
||||
/** Database password for authentication */
|
||||
password: string;
|
||||
password?: string;
|
||||
/** Database password for authentication (alias for password) */
|
||||
pass?: string;
|
||||
/** Name of the database to connect to */
|
||||
database: string;
|
||||
database?: string;
|
||||
/** Name of the database to connect to (alias for database) */
|
||||
db?: string;
|
||||
/** Database adapter/driver to use */
|
||||
adapter: string;
|
||||
/** Maximum time in milliseconds to wait for connection to become available */
|
||||
idleTimeout: number;
|
||||
/** Maximum time in milliseconds to wait when establishing a connection */
|
||||
connectionTimeout: number;
|
||||
/** Maximum lifetime in milliseconds of a connection */
|
||||
maxLifetime: number;
|
||||
adapter?: string;
|
||||
/** Maximum time in seconds to wait for connection to become available */
|
||||
idleTimeout?: number;
|
||||
/** Maximum time in seconds to wait for connection to become available (alias for idleTimeout) */
|
||||
idle_timeout?: number;
|
||||
/** Maximum time in seconds to wait when establishing a connection */
|
||||
connectionTimeout?: number;
|
||||
/** Maximum time in seconds to wait when establishing a connection (alias for connectionTimeout) */
|
||||
connection_timeout?: number;
|
||||
/** Maximum lifetime in seconds of a connection */
|
||||
maxLifetime?: number;
|
||||
/** Maximum lifetime in seconds of a connection (alias for maxLifetime) */
|
||||
max_lifetime?: number;
|
||||
/** Whether to use TLS/SSL for the connection */
|
||||
tls: boolean;
|
||||
tls?: TLSOptions | boolean;
|
||||
/** Whether to use TLS/SSL for the connection (alias for tls) */
|
||||
ssl?: TLSOptions | boolean;
|
||||
/** Callback function executed when a connection is established */
|
||||
onconnect: (client: SQL) => void;
|
||||
onconnect?: (client: SQL) => void;
|
||||
/** Callback function executed when a connection is closed */
|
||||
onclose: (client: SQL) => void;
|
||||
onclose?: (client: SQL) => void;
|
||||
/** Maximum number of connections in the pool */
|
||||
max: number;
|
||||
max?: number;
|
||||
/** By default values outside i32 range are returned as strings. If this is true, values outside i32 range are returned as BigInts. */
|
||||
bigint: boolean;
|
||||
bigint?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -3686,7 +3702,17 @@ declare module "bun" {
|
||||
* Render contextual errors? This enables bun's error page
|
||||
* @default process.env.NODE_ENV !== 'production'
|
||||
*/
|
||||
development?: boolean;
|
||||
development?:
|
||||
| boolean
|
||||
| {
|
||||
/**
|
||||
* Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use)
|
||||
*
|
||||
* @default true if process.env.NODE_ENV !== 'production'
|
||||
*
|
||||
*/
|
||||
hmr?: boolean;
|
||||
};
|
||||
|
||||
error?: (this: Server, error: ErrorLike) => Response | Promise<Response> | undefined | Promise<undefined>;
|
||||
|
||||
@@ -5309,7 +5335,10 @@ declare module "bun" {
|
||||
|
||||
interface PluginBuilder {
|
||||
/**
|
||||
* Register a callback which will be invoked when bundling starts.
|
||||
* Register a callback which will be invoked when bundling starts. When
|
||||
* using hot module reloading, this is called at the start of each
|
||||
* incremental rebuild.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* Bun.plugin({
|
||||
@@ -5406,9 +5435,9 @@ declare module "bun" {
|
||||
* - `browser`: The plugin will be applied to browser builds
|
||||
* - `node`: The plugin will be applied to Node.js builds
|
||||
*
|
||||
* If in Bun's runtime, the default target is `bun`.
|
||||
* If unspecified, it is assumed that the plugin is compatible with all targets.
|
||||
*
|
||||
* If unspecified, it is assumed that the plugin is compatible with the default target.
|
||||
* This field is not read by Bun.plugin
|
||||
*/
|
||||
target?: Target;
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"prebuild": "echo $(pwd)",
|
||||
"copy-docs": "rm -rf docs && cp -rL ../../docs/ ./docs && sed -i 's/\\$BUN_LATEST_VERSION/'\"${BUN_VERSION:-1.0.0}\"'/g' ./docs/**/*.md",
|
||||
"copy-docs": "rm -rf docs && cp -rL ../../docs/ ./docs && find ./docs -type f -name '*.md' -exec sed -i 's/\\$BUN_LATEST_VERSION/'\"${BUN_VERSION#bun-v:-1.0.0}\"'/g' {} +",
|
||||
"build": "bun run copy-docs && bun scripts/build.ts && bun run fmt",
|
||||
"test": "tsc",
|
||||
"fmt": "echo $(which biome) && biome format --write ."
|
||||
|
||||
@@ -387,8 +387,15 @@ int bsd_socket_multicast_interface(LIBUS_SOCKET_DESCRIPTOR fd, const struct sock
|
||||
static int bsd_socket_set_membership4(LIBUS_SOCKET_DESCRIPTOR fd, const struct sockaddr_in *addr, const struct sockaddr_in *iface, int drop) {
|
||||
struct ip_mreq mreq;
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
|
||||
mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
|
||||
mreq.imr_interface.s_addr = iface->sin_addr.s_addr;
|
||||
|
||||
if (iface != NULL) {
|
||||
mreq.imr_interface.s_addr = iface->sin_addr.s_addr;
|
||||
} else {
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
|
||||
int option = drop ? IP_DROP_MEMBERSHIP : IP_ADD_MEMBERSHIP;
|
||||
return setsockopt(fd, IPPROTO_IP, option, &mreq, sizeof(mreq));
|
||||
}
|
||||
@@ -397,13 +404,15 @@ static int bsd_socket_set_membership6(LIBUS_SOCKET_DESCRIPTOR fd, const struct s
|
||||
struct ipv6_mreq mreq;
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
mreq.ipv6mr_multiaddr = addr->sin6_addr;
|
||||
mreq.ipv6mr_interface = iface->sin6_scope_id;
|
||||
if (iface != NULL) {
|
||||
mreq.ipv6mr_interface = iface->sin6_scope_id;
|
||||
}
|
||||
int option = drop ? IPV6_LEAVE_GROUP : IPV6_JOIN_GROUP;
|
||||
return setsockopt(fd, IPPROTO_IP, option, &mreq, sizeof(mreq));
|
||||
}
|
||||
|
||||
int bsd_socket_set_membership(LIBUS_SOCKET_DESCRIPTOR fd, const struct sockaddr_storage *addr, const struct sockaddr_storage *iface, int drop) {
|
||||
if (addr->ss_family != iface->ss_family) {
|
||||
if (iface != NULL && addr->ss_family != iface->ss_family) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1589,22 +1589,40 @@ struct us_listen_socket_t *us_internal_ssl_socket_context_listen_unix(
|
||||
socket_ext_size, error);
|
||||
}
|
||||
|
||||
// https://github.com/oven-sh/bun/issues/16995
|
||||
static void us_internal_zero_ssl_data_for_connected_socket_before_onopen(struct us_internal_ssl_socket_t *s) {
|
||||
s->ssl = NULL;
|
||||
s->ssl_write_wants_read = 0;
|
||||
s->ssl_read_wants_write = 0;
|
||||
s->fatal_error = 0;
|
||||
s->handshake_state = HANDSHAKE_PENDING;
|
||||
}
|
||||
|
||||
// TODO does this need more changes?
|
||||
struct us_connecting_socket_t *us_internal_ssl_socket_context_connect(
|
||||
struct us_socket_t *us_internal_ssl_socket_context_connect(
|
||||
struct us_internal_ssl_socket_context_t *context, const char *host,
|
||||
int port, int options, int socket_ext_size, int* is_connected) {
|
||||
return us_socket_context_connect(
|
||||
int port, int options, int socket_ext_size, int* is_connecting) {
|
||||
struct us_internal_ssl_socket_t *s = (struct us_internal_ssl_socket_t *)us_socket_context_connect(
|
||||
2, &context->sc, host, port, options,
|
||||
sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) +
|
||||
socket_ext_size, is_connected);
|
||||
socket_ext_size, is_connecting);
|
||||
if (*is_connecting) {
|
||||
us_internal_zero_ssl_data_for_connected_socket_before_onopen(s);
|
||||
}
|
||||
|
||||
return (struct us_socket_t*)s;
|
||||
}
|
||||
struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect_unix(
|
||||
struct us_socket_t *us_internal_ssl_socket_context_connect_unix(
|
||||
struct us_internal_ssl_socket_context_t *context, const char *server_path,
|
||||
size_t pathlen, int options, int socket_ext_size) {
|
||||
return (struct us_internal_ssl_socket_t *)us_socket_context_connect_unix(
|
||||
struct us_socket_t *s = (struct us_socket_t *)us_socket_context_connect_unix(
|
||||
0, &context->sc, server_path, pathlen, options,
|
||||
sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) +
|
||||
socket_ext_size);
|
||||
if (s) {
|
||||
us_internal_zero_ssl_data_for_connected_socket_before_onopen((struct us_internal_ssl_socket_t*) s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static void ssl_on_open_without_sni(struct us_internal_ssl_socket_t *s, int is_client, char *ip, int ip_length) {
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <string.h>
|
||||
static const int root_certs_size = sizeof(root_certs) / sizeof(root_certs[0]);
|
||||
|
||||
extern "C" void BUN__warn__extra_ca_load_failed(const char* filename, const char* error_msg);
|
||||
|
||||
// This callback is used to avoid the default passphrase callback in OpenSSL
|
||||
// which will typically prompt for the passphrase. The prompting is designed
|
||||
// for the OpenSSL CLI, but works poorly for this case because it involves
|
||||
@@ -27,57 +29,82 @@ us_ssl_ctx_get_X509_without_callback_from(struct us_cert_string_t content) {
|
||||
in = BIO_new_mem_buf(content.str, content.len);
|
||||
if (in == NULL) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
x = PEM_read_bio_X509(in, NULL, us_no_password_callback, NULL);
|
||||
if (x == NULL) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
|
||||
}
|
||||
|
||||
x = PEM_read_bio_X509(in, NULL, us_no_password_callback, NULL);
|
||||
if (x == NULL) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
|
||||
goto end;
|
||||
// NOTE: PEM_read_bio_X509 allocates, so input BIO must be freed.
|
||||
BIO_free(in);
|
||||
}
|
||||
|
||||
// NOTE: PEM_read_bio_X509 allocates, so input BIO must be freed.
|
||||
BIO_free(in);
|
||||
return x;
|
||||
end:
|
||||
X509_free(x);
|
||||
BIO_free(in);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static X509 *
|
||||
us_ssl_ctx_get_X509_without_callback_from_file(const char *filename) {
|
||||
static STACK_OF(X509) *us_ssl_ctx_load_all_certs_from_file(const char *filename) {
|
||||
BIO *in = NULL;
|
||||
STACK_OF(X509) *certs = NULL;
|
||||
X509 *x = NULL;
|
||||
BIO *in;
|
||||
unsigned long last_err;
|
||||
|
||||
ERR_clear_error(); // clear error stack for SSL_CTX_use_certificate()
|
||||
|
||||
in = BIO_new(BIO_s_file());
|
||||
in = BIO_new_file(filename, "r");
|
||||
if (in == NULL) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (BIO_read_filename(in, filename) <= 0) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
x = PEM_read_bio_X509(in, NULL, us_no_password_callback, NULL);
|
||||
if (x == NULL) {
|
||||
certs = sk_X509_new_null();
|
||||
if (certs == NULL) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
|
||||
goto end;
|
||||
}
|
||||
|
||||
while ((x = PEM_read_bio_X509(in, NULL, us_no_password_callback, NULL))) {
|
||||
if (!sk_X509_push(certs, x)) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
|
||||
X509_free(x);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
last_err = ERR_peek_last_error();
|
||||
// Ignore error if its EOF/no start line found.
|
||||
if (ERR_GET_LIB(last_err) == ERR_LIB_PEM && ERR_GET_REASON(last_err) == PEM_R_NO_START_LINE) {
|
||||
ERR_clear_error();
|
||||
} else {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (sk_X509_num(certs) == 0) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
|
||||
goto end;
|
||||
}
|
||||
return x;
|
||||
end:
|
||||
X509_free(x);
|
||||
|
||||
BIO_free(in);
|
||||
return certs;
|
||||
|
||||
end:
|
||||
BIO_free(in);
|
||||
if (certs) {
|
||||
sk_X509_pop_free(certs, X509_free);
|
||||
}
|
||||
|
||||
char error_msg[256];
|
||||
ERR_error_string_n(ERR_peek_last_error(), error_msg, sizeof(error_msg));
|
||||
BUN__warn__extra_ca_load_failed(filename, error_msg);
|
||||
ERR_clear_error();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void us_internal_init_root_certs(X509 *root_cert_instances[sizeof(root_certs) / sizeof(root_certs[0])], X509 *&root_extra_cert_instances) {
|
||||
static void us_internal_init_root_certs(
|
||||
X509 *root_cert_instances[root_certs_size],
|
||||
STACK_OF(X509) *&root_extra_cert_instances) {
|
||||
static std::atomic_flag root_cert_instances_lock = ATOMIC_FLAG_INIT;
|
||||
static std::atomic_bool root_cert_instances_initialized = 0;
|
||||
|
||||
if (std::atomic_load(&root_cert_instances_initialized) == 1)
|
||||
return;
|
||||
|
||||
@@ -92,13 +119,9 @@ static void us_internal_init_root_certs(X509 *root_cert_instances[sizeof(root_ce
|
||||
}
|
||||
|
||||
// get extra cert option from environment variable
|
||||
const char *extra_cert = getenv("NODE_EXTRA_CA_CERTS");
|
||||
if (extra_cert) {
|
||||
size_t length = strlen(extra_cert);
|
||||
if (length > 0) {
|
||||
root_extra_cert_instances =
|
||||
us_ssl_ctx_get_X509_without_callback_from_file(extra_cert);
|
||||
}
|
||||
const char *extra_certs = getenv("NODE_EXTRA_CA_CERTS");
|
||||
if (extra_certs && extra_certs[0]) {
|
||||
root_extra_cert_instances = us_ssl_ctx_load_all_certs_from_file(extra_certs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,9 +145,8 @@ extern "C" X509_STORE *us_get_default_ca_store() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static X509 *root_cert_instances[sizeof(root_certs) / sizeof(root_certs[0])] = {
|
||||
NULL};
|
||||
static X509 *root_extra_cert_instances = NULL;
|
||||
static X509 *root_cert_instances[root_certs_size] = {NULL};
|
||||
static STACK_OF(X509) *root_extra_cert_instances = NULL;
|
||||
|
||||
us_internal_init_root_certs(root_cert_instances, root_extra_cert_instances);
|
||||
|
||||
@@ -138,8 +160,11 @@ extern "C" X509_STORE *us_get_default_ca_store() {
|
||||
}
|
||||
|
||||
if (root_extra_cert_instances) {
|
||||
X509_up_ref(root_extra_cert_instances);
|
||||
X509_STORE_add_cert(store, root_extra_cert_instances);
|
||||
for (int i = 0; i < sk_X509_num(root_extra_cert_instances); i++) {
|
||||
X509 *cert = sk_X509_value(root_extra_cert_instances, i);
|
||||
X509_up_ref(cert);
|
||||
X509_STORE_add_cert(store, cert);
|
||||
}
|
||||
}
|
||||
|
||||
return store;
|
||||
|
||||
@@ -247,7 +247,7 @@ void us_loop_run(struct us_loop_t *loop) {
|
||||
}
|
||||
}
|
||||
|
||||
extern int Bun__JSC_onBeforeWait(void*);
|
||||
extern void Bun__JSC_onBeforeWait(void*);
|
||||
extern void Bun__JSC_onAfterWait(void*);
|
||||
|
||||
void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout) {
|
||||
@@ -265,10 +265,8 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout
|
||||
/* Emit pre callback */
|
||||
us_internal_loop_pre(loop);
|
||||
|
||||
int needs_after_wait = 0;
|
||||
if (loop->data.jsc_vm) {
|
||||
needs_after_wait = Bun__JSC_onBeforeWait(loop->data.jsc_vm);
|
||||
}
|
||||
/* Safe if jsc_vm is NULL */
|
||||
Bun__JSC_onBeforeWait(loop->data.jsc_vm);
|
||||
|
||||
/* Fetch ready polls */
|
||||
#ifdef LIBUS_USE_EPOLL
|
||||
@@ -280,9 +278,7 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout
|
||||
} while (IS_EINTR(loop->num_ready_polls));
|
||||
#endif
|
||||
|
||||
if (needs_after_wait) {
|
||||
Bun__JSC_onAfterWait(loop->data.jsc_vm);
|
||||
}
|
||||
Bun__JSC_onAfterWait(loop->data.jsc_vm);
|
||||
|
||||
/* Iterate ready polls, dispatching them by type */
|
||||
for (loop->current_ready_poll = 0; loop->current_ready_poll < loop->num_ready_polls; loop->current_ready_poll++) {
|
||||
|
||||
@@ -400,11 +400,11 @@ struct us_listen_socket_t *us_internal_ssl_socket_context_listen_unix(
|
||||
us_internal_ssl_socket_context_r context, const char *path,
|
||||
size_t pathlen, int options, int socket_ext_size, int* error);
|
||||
|
||||
struct us_connecting_socket_t *us_internal_ssl_socket_context_connect(
|
||||
struct us_socket_t *us_internal_ssl_socket_context_connect(
|
||||
us_internal_ssl_socket_context_r context, const char *host,
|
||||
int port, int options, int socket_ext_size, int* is_resolved);
|
||||
|
||||
struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect_unix(
|
||||
struct us_socket_t *us_internal_ssl_socket_context_connect_unix(
|
||||
us_internal_ssl_socket_context_r context, const char *server_path,
|
||||
size_t pathlen, int options, int socket_ext_size);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "mock-debug",
|
||||
@@ -148,9 +148,9 @@
|
||||
|
||||
"buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
|
||||
|
||||
"bun-debug-adapter-protocol": ["bun-debug-adapter-protocol@workspace:../bun-debug-adapter-protocol", { "dependencies": { "semver": "^7.5.4", "source-map-js": "^1.0.2" } }],
|
||||
"bun-debug-adapter-protocol": ["bun-debug-adapter-protocol@workspace:../bun-debug-adapter-protocol"],
|
||||
|
||||
"bun-inspector-protocol": ["bun-inspector-protocol@workspace:../bun-inspector-protocol", { "dependencies": { "ws": "^8.13.0" } }],
|
||||
"bun-inspector-protocol": ["bun-inspector-protocol@workspace:../bun-inspector-protocol"],
|
||||
|
||||
"bun-types": ["bun-types@1.1.29", "", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-En3/TzSPMPyl5UlUB1MHzHpcrZDakTm7mS203eLoX1fBoEa3PW+aSS8GAqVJ7Is/m34Z5ogL+ECniLY0uDaCPw=="],
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bun-wasm",
|
||||
|
||||
13
root.zig
13
root.zig
@@ -1,13 +0,0 @@
|
||||
pub usingnamespace @import("./src/main.zig");
|
||||
|
||||
/// These functions are used throughout Bun's codebase.
|
||||
pub const bun = @import("./src/bun.zig");
|
||||
|
||||
pub const completions = struct {
|
||||
pub const bash = @embedFile("./completions/bun.bash");
|
||||
pub const zsh = @embedFile("./completions/bun.zsh");
|
||||
pub const fish = @embedFile("./completions/bun.fish");
|
||||
};
|
||||
|
||||
pub const JavaScriptCore = @import("./src/jsc.zig");
|
||||
pub const C = @import("./src/c.zig");
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user