Compare commits

...

2 Commits

Author SHA1 Message Date
Jarred Sumner
fa19bce388 Update NodeValidator.cpp 2025-03-07 00:34:38 -08:00
Jarred Sumner
a8ddc537ed Add bunch of nitpicky micro-optimizations 2025-03-07 00:25:33 -08:00
7 changed files with 100 additions and 58 deletions

View File

@@ -0,0 +1,7 @@
import { bench, run } from "../runner.mjs";
bench("new TextDecoder", () => {
return new TextDecoder("utf-8", { fatal: true });
});
await run();

View File

@@ -299,6 +299,12 @@ static WebCore::BufferEncodingType parseEncoding(JSC::ThrowScope& scope, JSC::JS
uint32_t validateOffset(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, JSC::JSValue name, uint32_t min, uint32_t max)
{
if (UNLIKELY(!value.isNumber())) return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, name, "number"_s, value);
if (value.isInt32()) {
auto value_num = static_cast<int64_t>(value.asInt32());
if (UNLIKELY(value_num < static_cast<int64_t>(min) || value_num > static_cast<int64_t>(max))) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, min, max, value);
return static_cast<uint32_t>(value_num);
}
auto value_num = value.asNumber();
if (UNLIKELY(std::fmod(value_num, 1.0) != 0)) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, "an integer"_s, value);
if (UNLIKELY(value_num < min || value_num > max)) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, min, max, value);
@@ -308,6 +314,12 @@ uint32_t validateOffset(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObjec
uint32_t validateOffset(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, WTF::ASCIILiteral name, uint32_t min, uint32_t max)
{
if (UNLIKELY(!value.isNumber())) return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, name, "number"_s, value);
if (value.isInt32()) {
auto value_num = static_cast<int64_t>(value.asInt32());
if (UNLIKELY(value_num < static_cast<int64_t>(min) || value_num > static_cast<int64_t>(max))) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, min, max, value);
return static_cast<uint32_t>(value_num);
}
auto value_num = value.asNumber();
if (UNLIKELY(std::fmod(value_num, 1.0) != 0)) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, "an integer"_s, value);
if (UNLIKELY(value_num < min || value_num > max)) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, min, max, value);

View File

@@ -665,15 +665,14 @@ JSMockModule JSMockModule::create(JSC::JSGlobalObject* globalObject)
structure = structure->addPropertyTransition(
init.vm,
structure,
JSC::Identifier::fromString(init.vm, "type"_s),
init.vm.propertyNames->type,
0,
offset);
structure = structure->addPropertyTransition(
init.vm,
structure,
JSC::Identifier::fromString(init.vm, "value"_s),
init.vm.propertyNames->value,
0,
offset);

View File

@@ -55,6 +55,7 @@ template<typename T> JSC::EncodedJSValue V::validateInteger(JSC::ThrowScope& sco
}
template<typename T> JSC::EncodedJSValue V::validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, ASCIILiteral name, JSC::JSValue min, JSC::JSValue max, T* out)
{
if (!value.isNumber()) return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, name, "number"_s, value);
if (min.isUndefined()) min = jsDoubleNumber(JSC::minSafeInteger());
if (max.isUndefined()) max = jsDoubleNumber(JSC::maxSafeInteger());
@@ -192,6 +193,19 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_checkRangesOrGetDefault, (JSC::JSGlobalObjec
auto lower = callFrame->argument(2);
auto upper = callFrame->argument(3);
if (LIKELY(number.isInt32())) {
auto number_num = number.asInt32();
ASSERT_WITH_MESSAGE(lower.isInt32(), "lower must be an integer. Make sure constants set it to a jsNumber().");
ASSERT_WITH_MESSAGE(upper.isInt32(), "upper must be an integer. Make sure constants set it to a jsNumber().");
auto lower_num = lower.asInt32();
auto upper_num = upper.asInt32();
if (number_num < lower_num || number_num > upper_num) {
return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, lower_num, upper_num, number);
}
return JSValue::encode(number);
}
auto finite = Bun::V::validateFiniteNumber(scope, globalObject, number, name);
RETURN_IF_EXCEPTION(scope, {});
auto finite_real = JSValue::decode(finite).asBoolean();
@@ -256,14 +270,29 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validatePort, (JSC::JSGlobalObject * globalO
auto scope = DECLARE_THROW_SCOPE(vm);
auto port = callFrame->argument(0);
auto name = callFrame->argument(1);
auto nameValue = callFrame->argument(1);
auto allowZero = callFrame->argument(2);
if (name.isUndefined()) name = jsString(vm, String("Port"_s));
if (allowZero.isUndefined()) allowZero = jsBoolean(true);
const auto name = [&]() -> JSC::JSValue {
if (nameValue.isUndefined()) return jsString(vm, String("Port"_s));
return nameValue;
};
if (allowZero.isUndefined()) allowZero = jsBoolean(true);
auto allowZero_b = allowZero.toBoolean(globalObject);
if (!port.isNumber() && !port.isString()) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (LIKELY(port.isInt32())) {
int number = port.asInt32();
if (UNLIKELY(number < 0 || number > 0xffff)) {
return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name(), port, allowZero_b);
}
if (UNLIKELY(number == 0 && !allowZero_b)) {
return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name(), port, allowZero_b);
}
return JSValue::encode(port);
}
if (!port.isNumber() && !port.isString()) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name(), port, allowZero_b);
if (port.isString()) {
auto port_str = port.getString(globalObject);
@@ -299,19 +328,19 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validatePort, (JSC::JSGlobalObject * globalO
return false;
});
if (trimmed.length() == 0) {
return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name(), port, allowZero_b);
}
}
auto port_num = port.toNumber(globalObject);
RETURN_IF_EXCEPTION(scope, {});
if (std::isnan(port_num)) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (std::isinf(port_num)) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (std::fmod(port_num, 1.0) != 0) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (port_num < 0) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (port_num > 0xffff) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (port_num == 0 && !allowZero_b) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (UNLIKELY(std::isnan(port_num))) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name(), port, allowZero_b);
if (UNLIKELY(std::isinf(port_num))) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name(), port, allowZero_b);
if (UNLIKELY(std::fmod(port_num, 1.0) != 0)) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name(), port, allowZero_b);
if (UNLIKELY(port_num < 0)) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name(), port, allowZero_b);
if (UNLIKELY(port_num > 0xffff)) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name(), port, allowZero_b);
if (UNLIKELY(port_num == 0 && !allowZero_b)) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name(), port, allowZero_b);
return JSValue::encode(port);
}
@@ -326,8 +355,8 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateAbortSignal, (JSC::JSGlobalObject *
if (!signal.isUndefined()) {
auto* object = signal.getObject();
if (!object) return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, name, "AbortSignal"_s, signal);
if (object->inherits<WebCore::JSAbortSignal>()) {
if (UNLIKELY(!object)) return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, name, "AbortSignal"_s, signal);
if (LIKELY(object->inherits<WebCore::JSAbortSignal>())) {
return JSValue::encode(jsUndefined());
}
@@ -351,38 +380,25 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateArray, (JSC::JSGlobalObject * global
}
JSC::EncodedJSValue V::validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name, JSValue minLength)
{
auto& vm = JSC::getVM(globalObject);
if (minLength.isUndefined()) minLength = jsNumber(0);
if (!JSC::isArray(globalObject, value)) return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, name, "Array"_s, value);
auto length = value.get(globalObject, Identifier::fromString(vm, "length"_s));
auto* object = value.toObject(globalObject);
auto length = object->getArrayLength();
auto minLength_num = minLength.isUndefined() ? 0 : minLength.toNumber(globalObject);
RETURN_IF_EXCEPTION(scope, {});
auto length_num = length.toNumber(globalObject);
RETURN_IF_EXCEPTION(scope, {});
auto minLength_num = minLength.toNumber(globalObject);
RETURN_IF_EXCEPTION(scope, {});
if (length_num < minLength_num) {
if (length < minLength_num) {
return Bun::ERR::INVALID_ARG_VALUE(scope, globalObject, name, value, makeString("must be longer than "_s, minLength_num));
}
return JSValue::encode(jsUndefined());
}
JSC::EncodedJSValue V::validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, ASCIILiteral name, JSValue minLength)
{
auto& vm = JSC::getVM(globalObject);
if (minLength.isUndefined()) minLength = jsNumber(0);
if (!JSC::isArray(globalObject, value)) return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, name, "Array"_s, value);
auto length = value.get(globalObject, Identifier::fromString(vm, "length"_s));
auto* object = value.toObject(globalObject);
auto length = object->getArrayLength();
auto minLength_num = minLength.isUndefined() ? 0 : minLength.toNumber(globalObject);
RETURN_IF_EXCEPTION(scope, {});
auto length_num = length.toNumber(globalObject);
RETURN_IF_EXCEPTION(scope, {});
auto minLength_num = minLength.toNumber(globalObject);
RETURN_IF_EXCEPTION(scope, {});
if (length_num < minLength_num) {
if (length < minLength_num) {
return Bun::ERR::INVALID_ARG_VALUE(scope, globalObject, name, value, makeString("must be longer than "_s, minLength_num));
}
return JSValue::encode(jsUndefined());
@@ -511,10 +527,14 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateEncoding, (JSC::JSGlobalObject * glo
length = impl->byteLength();
}
} else if (auto* object = data.getObject()) {
JSValue lengthValue = object->getIfPropertyExists(globalObject, vm.propertyNames->length);
RETURN_IF_EXCEPTION(scope, {});
length = lengthValue.toLength(globalObject);
RETURN_IF_EXCEPTION(scope, {});
if (JSC::isJSArray(object)) {
length = object->getArrayLength();
} else {
JSValue lengthValue = object->getIfPropertyExists(globalObject, vm.propertyNames->length);
RETURN_IF_EXCEPTION(scope, {});
length = lengthValue.toLength(globalObject);
RETURN_IF_EXCEPTION(scope, {});
}
}
if (length % 2 != 0) {
return Bun::ERR::INVALID_ARG_VALUE(scope, globalObject, "encoding"_s, encoding, makeString("is invalid for data of length "_s, length));

View File

@@ -727,12 +727,14 @@ std::optional<ncrypto::EVPKeyPointer> preparePublicOrPrivateKey(JSGlobalObject*
return std::nullopt;
}
const auto& builtinNames = WebCore::builtinNames(vm);
// Handle options object with key property
JSValue key = optionsObj->get(lexicalGlobalObject, Identifier::fromString(vm, "key"_s));
RETURN_IF_EXCEPTION(scope, {});
JSValue formatValue = optionsObj->get(lexicalGlobalObject, Identifier::fromString(vm, "format"_s));
JSValue formatValue = optionsObj->get(lexicalGlobalObject, builtinNames.formatPublicName());
RETURN_IF_EXCEPTION(scope, {});
JSValue typeValue = optionsObj->get(lexicalGlobalObject, Identifier::fromString(vm, "type"_s));
JSValue typeValue = optionsObj->get(lexicalGlobalObject, vm.propertyNames->type);
RETURN_IF_EXCEPTION(scope, {});
JSValue passphrase = optionsObj->get(lexicalGlobalObject, Identifier::fromString(vm, "passphrase"_s));
RETURN_IF_EXCEPTION(scope, {});

View File

@@ -20,8 +20,9 @@ inline void generateNativeModule_AbortControllerModule(
auto* abortController = WebCore::JSAbortController::getConstructor(vm, globalObject).getObject();
JSValue abortSignal = WebCore::JSAbortSignal::getConstructor(vm, globalObject);
const auto& builtinNames = WebCore::builtinNames(vm);
const auto controllerIdent = Identifier::fromString(vm, "AbortController"_s);
const auto signalIdent = Identifier::fromString(vm, "AbortSignal"_s);
const auto& signalIdent = builtinNames.AbortSignalPublicName();
const Identifier& esModuleMarker = vm.propertyNames->__esModule;
exportNames.append(vm.propertyNames->defaultKeyword);

View File

@@ -10511,12 +10511,13 @@ function toCryptoKey(key, asPublic) {
return key.$bunNativePtr || key;
}
const nested = key.key;
// Nested CryptoKey.
if (key.key instanceof KeyObject || key.key instanceof CryptoKey) {
if (asPublic && key.key.type === "private") {
return _createPublicKey(key.key).$bunNativePtr;
if (nested instanceof KeyObject || nested instanceof CryptoKey) {
if (asPublic && nested.type === "private") {
return _createPublicKey(nested).$bunNativePtr;
}
return key.key.$bunNativePtr || key.key;
return nested.$bunNativePtr || nested;
}
// One of string, ArrayBuffer, Buffer, TypedArray, DataView, or Object.
@@ -10587,10 +10588,11 @@ function Sign(algorithm, options): void {
}
validateString(algorithm, "algorithm");
this[kHandle] = new _Sign();
this[kHandle].init(algorithm);
const handle = new _Sign();
handle.init(algorithm);
this[kHandle] = handle;
StreamModule.Writable.$apply(this, [options]);
StreamModule.Writable.$call(this, options);
}
$toClass(Sign, "Sign", StreamModule.Writable);
@@ -10622,10 +10624,11 @@ function Verify(algorithm, options): void {
}
validateString(algorithm, "algorithm");
this[kHandle] = new _Verify();
this[kHandle].init(algorithm);
const handle = new _Verify();
handle.init(algorithm);
this[kHandle] = handle;
StreamModule.Writable.$apply(this, [options]);
StreamModule.Writable.$call(this, options);
}
$toClass(Verify, "Verify", StreamModule.Writable);
@@ -10650,11 +10653,9 @@ crypto_exports.createVerify = createVerify;
if (!new.target) {
return new Hash(algorithm, options);
}
this[kHandle] = new _Hash(algorithm, options);
const handle = new _Hash(algorithm, options);
this[kHandle] = handle;
LazyTransform.$apply(this, [options]);
LazyTransform.$call(this, options);
}
$toClass(Hash, "Hash", LazyTransform);