mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
explosions
This commit is contained in:
@@ -535,6 +535,22 @@ pub fn inspect(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.J
|
||||
return ret;
|
||||
}
|
||||
|
||||
export fn Bun__inspect(globalThis: *JSGlobalObject, value: JSValue) ZigString {
|
||||
// very stable memory address
|
||||
var array = MutableString.init(getAllocator(globalThis), 0) catch unreachable;
|
||||
var buffered_writer = MutableString.BufferedWriter{ .context = &array };
|
||||
const writer = buffered_writer.writer();
|
||||
|
||||
var formatter = ConsoleObject.Formatter{
|
||||
.globalThis = globalThis,
|
||||
.quote_strings = true,
|
||||
};
|
||||
writer.print("{}", .{value.toFmt(&formatter)}) catch return ZigString.Empty;
|
||||
buffered_writer.flush() catch return ZigString.Empty;
|
||||
|
||||
return ZigString.init(array.slice()).withEncoding();
|
||||
}
|
||||
|
||||
pub fn getInspect(globalObject: *JSC.JSGlobalObject, _: *JSC.JSObject) JSC.JSValue {
|
||||
const fun = JSC.createCallback(globalObject, ZigString.static("inspect"), 2, inspect);
|
||||
var str = ZigString.init("nodejs.util.inspect.custom");
|
||||
@@ -944,14 +960,11 @@ export fn Bun__resolve(global: *JSGlobalObject, specifier: JSValue, source: JSVa
|
||||
return JSC.JSPromise.resolvedPromiseValue(global, value);
|
||||
}
|
||||
|
||||
export fn Bun__resolveSync(global: *JSGlobalObject, specifier: JSValue, source: JSValue, is_esm: bool) JSC.JSValue {
|
||||
const specifier_str = specifier.toBunString(global);
|
||||
defer specifier_str.deref();
|
||||
|
||||
export fn Bun__resolveSync(global: *JSGlobalObject, specifier: *const bun.String, source: JSValue, is_esm: bool) JSC.JSValue {
|
||||
const source_str = source.toBunString(global);
|
||||
defer source_str.deref();
|
||||
|
||||
return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source_str, is_esm, true));
|
||||
return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier.*, source_str, is_esm, true));
|
||||
}
|
||||
|
||||
export fn Bun__resolveSyncWithStrings(global: *JSGlobalObject, specifier: *bun.String, source: *bun.String, is_esm: bool) JSC.JSValue {
|
||||
@@ -4566,8 +4579,11 @@ const InternalTestingAPIs = struct {
|
||||
};
|
||||
|
||||
comptime {
|
||||
_ = Crypto.JSPasswordObject.JSPasswordObject__create;
|
||||
BunObject.exportAll();
|
||||
if (Environment.export_cpp_apis) {
|
||||
_ = Crypto.JSPasswordObject.JSPasswordObject__create;
|
||||
_ = Bun__inspect;
|
||||
BunObject.exportAll();
|
||||
}
|
||||
}
|
||||
|
||||
const assert = bun.assert;
|
||||
|
||||
@@ -375,8 +375,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen,
|
||||
#else
|
||||
WTF::String msg = WTF::String::fromUTF8(dlerror());
|
||||
#endif
|
||||
JSC::throwTypeError(globalObject, scope, msg);
|
||||
return {};
|
||||
return Bun::ERR::DLOPEN_FAILED(scope, globalObject, msg);
|
||||
}
|
||||
|
||||
if (callCountAtStart != globalObject->napiModuleRegisterCallCount) {
|
||||
@@ -1868,6 +1867,8 @@ static JSValue constructProcessConfigObject(VM& vm, JSObject* processObject)
|
||||
JSC::JSObject* variables = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1);
|
||||
variables->putDirect(vm, JSC::Identifier::fromString(vm, "v8_enable_i8n_support"_s),
|
||||
JSC::jsNumber(1), 0);
|
||||
variables->putDirect(vm, JSC::Identifier::fromString(vm, "node_module_version"_s),
|
||||
JSC::jsNumber(REPORTED_NODEJS_ABI_VERSION), 0);
|
||||
variables->putDirect(vm, JSC::Identifier::fromString(vm, "enable_lto"_s), JSC::jsBoolean(false), 0);
|
||||
config->putDirect(vm, JSC::Identifier::fromString(vm, "target_defaults"_s), JSC::constructEmptyObject(globalObject), 0);
|
||||
config->putDirect(vm, JSC::Identifier::fromString(vm, "variables"_s), variables, 0);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
* different value. In that case, it will have a stale value.
|
||||
*/
|
||||
|
||||
#include "ErrorCode.h"
|
||||
#include "headers.h"
|
||||
|
||||
#include "JavaScriptCore/Synchronousness.h"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "ErrorCode.h"
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "ZigGlobalObject.h"
|
||||
#include "DOMException.h"
|
||||
#include "JavaScriptCore/Error.h"
|
||||
@@ -23,6 +25,8 @@
|
||||
#include "JavaScriptCore/JSInternalFieldObjectImplInlines.h"
|
||||
#include "JSDOMException.h"
|
||||
|
||||
#include "ErrorCode.h"
|
||||
|
||||
static JSC::JSObject* createErrorPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::ErrorType type, WTF::ASCIILiteral name, WTF::ASCIILiteral code, bool isDOMExceptionPrototype = false)
|
||||
{
|
||||
JSC::JSObject* prototype;
|
||||
@@ -171,6 +175,9 @@ JSObject* createError(Zig::JSGlobalObject* globalObject, ErrorCode code, JSC::JS
|
||||
return createError(vm, globalObject, code, message);
|
||||
}
|
||||
|
||||
// export fn Bun__inspect(globalThis: *JSGlobalObject, value: JSValue) ZigString
|
||||
extern "C" ZigString Bun__inspect(JSC::JSGlobalObject* globalObject, JSValue value);
|
||||
|
||||
WTF::String JSValueToStringSafe(JSC::JSGlobalObject* globalObject, JSValue arg)
|
||||
{
|
||||
ASSERT(!arg.isEmpty());
|
||||
@@ -179,11 +186,7 @@ WTF::String JSValueToStringSafe(JSC::JSGlobalObject* globalObject, JSValue arg)
|
||||
|
||||
auto cell = arg.asCell();
|
||||
switch (cell->type()) {
|
||||
case JSC::JSType::StringType: {
|
||||
return arg.toWTFStringForConsole(globalObject);
|
||||
}
|
||||
case JSC::JSType::SymbolType: {
|
||||
|
||||
auto symbol = jsCast<Symbol*>(cell);
|
||||
auto result = symbol->tryGetDescriptiveString();
|
||||
if (result.has_value())
|
||||
@@ -197,14 +200,14 @@ WTF::String JSValueToStringSafe(JSC::JSGlobalObject* globalObject, JSValue arg)
|
||||
auto name = JSC::getCalculatedDisplayName(vm, cell->getObject());
|
||||
if (catchScope.exception()) {
|
||||
catchScope.clearException();
|
||||
name = "Function"_s;
|
||||
name = ""_s;
|
||||
}
|
||||
|
||||
if (!name.isNull() && name.length() > 0) {
|
||||
return makeString("[Function: "_s, name, ']');
|
||||
}
|
||||
|
||||
return "Function"_s;
|
||||
return "[Function: (anonymous)]"_s;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -213,34 +216,132 @@ WTF::String JSValueToStringSafe(JSC::JSGlobalObject* globalObject, JSValue arg)
|
||||
}
|
||||
}
|
||||
|
||||
return arg.toWTFStringForConsole(globalObject);
|
||||
ZigString zstring = Bun__inspect(globalObject, arg);
|
||||
BunString bstring(BunStringTag::ZigString, BunStringImpl(zstring));
|
||||
return bstring.toWTFString();
|
||||
}
|
||||
|
||||
WTF::String determineSpecificType(JSC::JSGlobalObject* globalObject, JSValue value)
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_CATCH_SCOPE(vm);
|
||||
|
||||
if (value.isNull()) {
|
||||
return String("null"_s);
|
||||
}
|
||||
if (value.isUndefined()) {
|
||||
return String("undefined"_s);
|
||||
}
|
||||
if (value.isBigInt()) {
|
||||
auto str = value.toStringOrNull(globalObject);
|
||||
if (!str) return {};
|
||||
return makeString("type bigint ("_s, str->getString(globalObject), "n)"_s);
|
||||
}
|
||||
if (value.isNumber()) {
|
||||
double d = value.asNumber();
|
||||
double infinity = std::numeric_limits<double>::infinity();
|
||||
if (value == 0) return (1 / d == -infinity) ? String("type number (-0)"_s) : String("type number (0)"_s);
|
||||
if (d != d) return String("type number (NaN)"_s);
|
||||
if (d == infinity) return String("type number (Infinity)"_s);
|
||||
if (d == -infinity) return String("type number (-Infinity)"_s);
|
||||
auto str = value.toStringOrNull(globalObject);
|
||||
if (!str) return {};
|
||||
return makeString("type number ("_s, str->getString(globalObject), ")"_s);
|
||||
}
|
||||
if (value.isBoolean()) {
|
||||
return value.asBoolean() ? String("type boolean (true)"_s) : String("type boolean (false)"_s);
|
||||
}
|
||||
if (value.isSymbol()) {
|
||||
auto cell = value.asCell();
|
||||
auto symbol = jsCast<Symbol*>(cell);
|
||||
auto result = symbol->tryGetDescriptiveString();
|
||||
auto description = result.has_value() ? result.value() : String("Symbol()"_s);
|
||||
return makeString("type symbol ("_s, description, ")"_s);
|
||||
}
|
||||
if (value.isCallable()) {
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_CATCH_SCOPE(vm);
|
||||
auto cell = value.asCell();
|
||||
auto name = JSC::getCalculatedDisplayName(vm, cell->getObject());
|
||||
if (scope.exception()) {
|
||||
scope.clearException();
|
||||
name = String(""_s);
|
||||
}
|
||||
if (!name.isNull() && name.length() > 0) {
|
||||
return makeString("function "_s, name);
|
||||
}
|
||||
return String("function"_s);
|
||||
}
|
||||
if (value.isObject()) {
|
||||
auto constructor = value.get(globalObject, vm.propertyNames->constructor);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
if (constructor.toBoolean(globalObject)) {
|
||||
auto name = constructor.get(globalObject, vm.propertyNames->name);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto str = name.toString(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return makeString("an instance of "_s, str->getString(globalObject));
|
||||
}
|
||||
// return `${lazyInternalUtilInspect().inspect(value, { depth: -1 })}`;
|
||||
auto str = JSValueToStringSafe(globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return str;
|
||||
}
|
||||
if (value.isString()) {
|
||||
auto str = value.toString(globalObject)->getString(globalObject);
|
||||
if (str.length() > 28) {
|
||||
str = str.substring(0, 25);
|
||||
str = makeString(str, "..."_s);
|
||||
if (!str.contains('\'')) {
|
||||
return makeString("type string ('"_s, str, "')"_s);
|
||||
}
|
||||
}
|
||||
// return `type string (${JSONStringify(value)})`;
|
||||
str = JSValueToStringSafe(globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return makeString("type string ("_s, str, ")"_s);
|
||||
}
|
||||
|
||||
// value = lazyInternalUtilInspect().inspect(value, { colors: false });
|
||||
auto str = JSValueToStringSafe(globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return str;
|
||||
}
|
||||
|
||||
namespace Message {
|
||||
|
||||
WTF::String ERR_INVALID_ARG_TYPE(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, const StringView& arg_name, const StringView& expected_type, JSValue actual_value)
|
||||
{
|
||||
auto actual_value_string = JSValueToStringSafe(globalObject, actual_value);
|
||||
auto actual_value_string = determineSpecificType(globalObject, actual_value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
return makeString("The \""_s, arg_name, "\" argument must be of type "_s, expected_type, ". Received: "_s, actual_value_string);
|
||||
return makeString("The \""_s, arg_name, "\" argument must be of type "_s, expected_type, ". Received "_s, actual_value_string);
|
||||
}
|
||||
|
||||
WTF::String ERR_INVALID_ARG_TYPE(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, const StringView& arg_name, ArgList expected_types, JSValue actual_value)
|
||||
{
|
||||
WTF::StringBuilder result;
|
||||
|
||||
auto actual_value_string = JSValueToStringSafe(globalObject, actual_value);
|
||||
auto actual_value_string = determineSpecificType(globalObject, actual_value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
result.append("The \""_s, arg_name, "\" argument must be of type "_s);
|
||||
result.append("The "_s);
|
||||
|
||||
if (arg_name.contains(' ')) {
|
||||
result.append(arg_name);
|
||||
} else {
|
||||
result.append("\""_s);
|
||||
result.append(arg_name);
|
||||
result.append("\" argument"_s);
|
||||
}
|
||||
result.append(" must be of type "_s);
|
||||
|
||||
unsigned length = expected_types.size();
|
||||
if (length == 1) {
|
||||
result.append(expected_types.at(0).toWTFString(globalObject));
|
||||
} else if (length == 2) {
|
||||
result.append(expected_types.at(0).toWTFString(globalObject));
|
||||
result.append(" or "_s);
|
||||
result.append(", or "_s);
|
||||
result.append(expected_types.at(1).toWTFString(globalObject));
|
||||
} else {
|
||||
for (unsigned i = 0; i < length - 1; i++) {
|
||||
@@ -249,11 +350,11 @@ WTF::String ERR_INVALID_ARG_TYPE(JSC::ThrowScope& scope, JSC::JSGlobalObject* gl
|
||||
JSValue expected_type = expected_types.at(i);
|
||||
result.append(expected_type.toWTFString(globalObject));
|
||||
}
|
||||
result.append(" or "_s);
|
||||
result.append(", or "_s);
|
||||
result.append(expected_types.at(length - 1).toWTFString(globalObject));
|
||||
}
|
||||
|
||||
result.append(". Received: "_s, actual_value_string);
|
||||
result.append(". Received "_s, actual_value_string);
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
@@ -291,20 +392,26 @@ WTF::String ERR_OUT_OF_RANGE(JSC::ThrowScope& scope, JSC::JSGlobalObject* global
|
||||
auto input = JSValueToStringSafe(globalObject, val_input);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
return makeString("The value of \""_s, arg_name, "\" is out of range. It must be "_s, range, ". Received: "_s, input);
|
||||
return makeString("The value of \""_s, arg_name, "\" is out of range. It must be "_s, range, ". Received "_s, input);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ERR {
|
||||
|
||||
JSC::EncodedJSValue throwCode(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, ErrorCode code, const WTF::String& message)
|
||||
{
|
||||
throwScope.throwException(globalObject, createError(globalObject, code, message));
|
||||
return {};
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue INVALID_ARG_TYPE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& arg_name, const WTF::String& expected_type, JSC::JSValue val_actual_value)
|
||||
{
|
||||
auto arg_kind = arg_name.startsWith("options."_s) ? "property"_s : "argument"_s;
|
||||
auto arg_kind = String(arg_name).startsWith("options."_s) ? "property"_s : "argument"_s;
|
||||
auto ty_first_char = expected_type[0];
|
||||
auto ty_kind = ty_first_char >= 'A' && ty_first_char <= 'Z' ? "an instance of"_s : "of type"_s;
|
||||
|
||||
auto actual_value = JSValueToStringSafe(globalObject, val_actual_value);
|
||||
auto actual_value = determineSpecificType(globalObject, val_actual_value);
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
auto message = makeString("The \""_s, arg_name, "\" "_s, arg_kind, " must be "_s, ty_kind, " "_s, expected_type, ". Received "_s, actual_value);
|
||||
@@ -320,7 +427,7 @@ JSC::EncodedJSValue INVALID_ARG_TYPE(JSC::ThrowScope& throwScope, JSC::JSGlobalO
|
||||
auto ty_first_char = expected_type[0];
|
||||
auto ty_kind = ty_first_char >= 'A' && ty_first_char <= 'Z' ? "an instance of"_s : "of type"_s;
|
||||
|
||||
auto actual_value = JSValueToStringSafe(globalObject, val_actual_value);
|
||||
auto actual_value = determineSpecificType(globalObject, val_actual_value);
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
auto message = makeString("The \""_s, arg_name, "\" "_s, arg_kind, " must be "_s, ty_kind, " "_s, expected_type, ". Received "_s, actual_value);
|
||||
@@ -438,8 +545,12 @@ JSC::EncodedJSValue STRING_TOO_LONG(JSC::ThrowScope& throwScope, JSC::JSGlobalOb
|
||||
return {};
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue BUFFER_OUT_OF_BOUNDS(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject)
|
||||
JSC::EncodedJSValue BUFFER_OUT_OF_BOUNDS(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& name)
|
||||
{
|
||||
if (!name.isEmpty()) {
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_BUFFER_OUT_OF_BOUNDS, makeString("\""_s, name, "\" is outside of buffer bounds"_s)));
|
||||
return {};
|
||||
}
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_BUFFER_OUT_OF_BOUNDS, "Attempt to access memory outside buffer bounds"_s));
|
||||
return {};
|
||||
}
|
||||
@@ -469,6 +580,12 @@ JSC::EncodedJSValue SOCKET_BAD_PORT(JSC::ThrowScope& throwScope, JSC::JSGlobalOb
|
||||
return {};
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue DLOPEN_FAILED(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* global, const WTF::String& message)
|
||||
{
|
||||
throwScope.throwException(global, createError(global, ErrorCode::ERR_DLOPEN_FAILED, message));
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static JSC::JSValue ERR_INVALID_ARG_TYPE(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue arg0, JSValue arg1, JSValue arg2)
|
||||
|
||||
@@ -92,6 +92,7 @@ JSC::EncodedJSValue STRING_TOO_LONG(JSC::ThrowScope& throwScope, JSC::JSGlobalOb
|
||||
JSC::EncodedJSValue BUFFER_OUT_OF_BOUNDS(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject);
|
||||
JSC::EncodedJSValue UNKNOWN_SIGNAL(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue signal, bool triedUppercase = false);
|
||||
JSC::EncodedJSValue SOCKET_BAD_PORT(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue name, JSC::JSValue port, bool allowZero);
|
||||
JSC::EncodedJSValue DLOPEN_FAILED(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* global, const WTF::String& message);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ export default [
|
||||
["ERR_STREAM_RELEASE_LOCK", Error, "AbortError"],
|
||||
["ERR_INCOMPATIBLE_OPTION_PAIR", TypeError, "TypeError"],
|
||||
["ERR_INVALID_URI", URIError, "URIError"],
|
||||
["ERR_DLOPEN_FAILED", Error],
|
||||
|
||||
// Bun-specific
|
||||
["ERR_FORMDATA_PARSE_ERROR", TypeError],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "ErrorCode.h"
|
||||
#include "root.h"
|
||||
#include "headers.h"
|
||||
|
||||
@@ -189,9 +190,13 @@ extern "C" JSC::EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObje
|
||||
JSC::JSValue moduleName = callFrame->argument(0);
|
||||
JSC::JSValue fromValue = callFrame->argument(1);
|
||||
|
||||
if (moduleName.isUndefinedOrNull()) {
|
||||
JSC::throwTypeError(globalObject, scope, "expects a string"_s);
|
||||
scope.release();
|
||||
if (!moduleName.isString()) {
|
||||
Bun::ERR::INVALID_ARG_TYPE(scope, lexicalGlobalObject, "id"_s, "string"_s, moduleName);
|
||||
return {};
|
||||
}
|
||||
auto moduleNameString = moduleName.toWTFString(globalObject);
|
||||
if (moduleNameString.isEmpty()) {
|
||||
Bun::ERR::INVALID_ARG_VALUE(scope, lexicalGlobalObject, "id"_s, moduleName, "must be a non-empty string"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -260,7 +265,8 @@ extern "C" JSC::EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObje
|
||||
}
|
||||
}
|
||||
|
||||
auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), from, isESM);
|
||||
BunString moduleNameBunString = Bun::toString(moduleNameString);
|
||||
auto result = Bun__resolveSync(globalObject, &moduleNameBunString, from, isESM);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
if (!JSC::JSValue::decode(result).isString()) {
|
||||
@@ -284,9 +290,13 @@ extern "C" JSC::EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlo
|
||||
JSValue from = callFrame->argument(1);
|
||||
bool isESM = callFrame->argument(2).asBoolean();
|
||||
|
||||
if (moduleName.isUndefinedOrNull()) {
|
||||
JSC::throwTypeError(lexicalGlobalObject, scope, "expected module name as a string"_s);
|
||||
scope.release();
|
||||
if (!moduleName.isString()) {
|
||||
Bun::ERR::INVALID_ARG_TYPE(scope, lexicalGlobalObject, "id"_s, "string"_s, moduleName);
|
||||
return {};
|
||||
}
|
||||
auto moduleNameString = moduleName.toWTFString(globalObject);
|
||||
if (moduleNameString.isEmpty()) {
|
||||
Bun::ERR::INVALID_ARG_VALUE(scope, lexicalGlobalObject, "id"_s, moduleName, "must be a non-empty string"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -294,9 +304,8 @@ extern "C" JSC::EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlo
|
||||
|
||||
if (globalObject->onLoadPlugins.hasVirtualModules()) {
|
||||
if (moduleName.isString()) {
|
||||
auto moduleString = moduleName.toWTFString(globalObject);
|
||||
if (auto resolvedString = globalObject->onLoadPlugins.resolveVirtualModule(moduleString, from.toWTFString(globalObject))) {
|
||||
if (moduleString == resolvedString.value())
|
||||
if (auto resolvedString = globalObject->onLoadPlugins.resolveVirtualModule(moduleNameString, from.toWTFString(globalObject))) {
|
||||
if (moduleNameString == resolvedString.value())
|
||||
return JSC::JSValue::encode(moduleName);
|
||||
return JSC::JSValue::encode(jsString(vm, resolvedString.value()));
|
||||
}
|
||||
@@ -331,7 +340,8 @@ extern "C" JSC::EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlo
|
||||
}
|
||||
}
|
||||
|
||||
auto result = Bun__resolveSync(lexicalGlobalObject, JSC::JSValue::encode(moduleName), JSValue::encode(from), isESM);
|
||||
BunString moduleNameBunString = Bun::toString(moduleNameString);
|
||||
auto result = Bun__resolveSync(lexicalGlobalObject, &moduleNameBunString, JSValue::encode(from), isESM);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
if (!JSC::JSValue::decode(result).isString()) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
extern "C" JSC_DECLARE_HOST_FUNCTION(functionImportMeta__resolveSync);
|
||||
extern "C" JSC_DECLARE_HOST_FUNCTION(functionImportMeta__resolveSyncPrivate);
|
||||
extern "C" JSC::EncodedJSValue Bun__resolve(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from, bool is_esm);
|
||||
extern "C" JSC::EncodedJSValue Bun__resolveSync(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from, bool is_esm);
|
||||
extern "C" JSC::EncodedJSValue Bun__resolveSync(JSC::JSGlobalObject* global, const BunString* specifier, JSC::EncodedJSValue from, bool is_esm);
|
||||
extern "C" JSC::EncodedJSValue Bun__resolveSyncWithSource(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, BunString* from, bool is_esm);
|
||||
extern "C" JSC::EncodedJSValue Bun__resolveSyncWithStrings(JSC::JSGlobalObject* global, BunString* specifier, BunString* from, bool is_esm);
|
||||
|
||||
|
||||
@@ -202,6 +202,10 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsBuiltinModule,
|
||||
auto moduleStr = moduleName.toWTFString(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, JSValue::encode(jsBoolean(false)));
|
||||
|
||||
// Bun does not yet implement this module, but to mimic node:module, this special case is needed.
|
||||
if (moduleStr == "node:test"_s) {
|
||||
return JSValue::encode(jsBoolean(true));
|
||||
}
|
||||
return JSValue::encode(jsBoolean(Bun::isBuiltinModule(moduleStr)));
|
||||
}
|
||||
|
||||
@@ -329,13 +333,15 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionResolveFileName,
|
||||
JSC::JSValue moduleName = callFrame->argument(0);
|
||||
JSC::JSValue fromValue = callFrame->argument(1);
|
||||
|
||||
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
|
||||
if (moduleName.isUndefinedOrNull()) {
|
||||
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
|
||||
JSC::throwTypeError(globalObject, scope,
|
||||
"Module._resolveFilename expects a string"_s);
|
||||
scope.release();
|
||||
return JSC::JSValue::encode(JSC::JSValue {});
|
||||
}
|
||||
WTF::String moduleNameString = moduleName.toWTFString(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
if (
|
||||
// fast path: it's a real CommonJS module object.
|
||||
@@ -354,8 +360,8 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionResolveFileName,
|
||||
}
|
||||
}
|
||||
|
||||
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
|
||||
auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), JSValue::encode(fromValue), false);
|
||||
BunString moduleNameBunString = Bun::toString(moduleNameString);
|
||||
auto result = Bun__resolveSync(globalObject, &moduleNameBunString, JSValue::encode(fromValue), false);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
if (!JSC::JSValue::decode(result).isString()) {
|
||||
|
||||
16
test/js/node/test/parallel/test-module-isBuiltin.js
Normal file
16
test/js/node/test/parallel/test-module-isBuiltin.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const { isBuiltin } = require('module');
|
||||
|
||||
// Includes modules in lib/ (even deprecated ones)
|
||||
assert(isBuiltin('http'));
|
||||
assert(isBuiltin('sys'));
|
||||
assert(isBuiltin('node:fs'));
|
||||
assert(isBuiltin('node:test'));
|
||||
|
||||
// Does not include internal modules
|
||||
assert(!isBuiltin('internal/errors'));
|
||||
assert(!isBuiltin('test'));
|
||||
assert(!isBuiltin(''));
|
||||
assert(!isBuiltin(undefined));
|
||||
98
test/js/node/test/parallel/test-module-loading-error.js
Normal file
98
test/js/node/test/parallel/test-module-loading-error.js
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
const errorMessagesByPlatform = {
|
||||
win32: ['is not a valid Win32 application'],
|
||||
linux: ['file too short', 'Exec format error'],
|
||||
sunos: ['unknown file type', 'not an ELF file'],
|
||||
darwin: ['file too short', 'not a mach-o file'],
|
||||
aix: ['Cannot load module',
|
||||
'Cannot run a file that does not have a valid format.',
|
||||
'Exec format error'],
|
||||
ibmi: ['Cannot load module',
|
||||
'The module has too many section headers',
|
||||
'or the file has been truncated.'],
|
||||
};
|
||||
// If we don't know a priori what the error would be, we accept anything.
|
||||
const platform = common.isIBMi ? 'ibmi' : process.platform;
|
||||
const errorMessages = errorMessagesByPlatform[platform] || [''];
|
||||
|
||||
// On Windows, error messages are MUI dependent
|
||||
// Ref: https://github.com/nodejs/node/issues/13376
|
||||
let localeOk = true;
|
||||
if (common.isWindows) {
|
||||
const powerShellFindMUI =
|
||||
'powershell -NoProfile -ExecutionPolicy Unrestricted -c ' +
|
||||
'"(Get-UICulture).TwoLetterISOLanguageName"';
|
||||
try {
|
||||
// If MUI != 'en' we'll ignore the content of the message
|
||||
localeOk = execSync(powerShellFindMUI).toString('utf8').trim() === 'en';
|
||||
} catch {
|
||||
// It's only a best effort try to find the MUI
|
||||
}
|
||||
}
|
||||
|
||||
assert.throws(
|
||||
() => { require('../fixtures/module-loading-error.node'); },
|
||||
(e) => {
|
||||
if (localeOk && !errorMessages.some((msg) => e.message.includes(msg)))
|
||||
return false;
|
||||
return e.name === 'Error';
|
||||
}
|
||||
);
|
||||
|
||||
const re = /^The "id" argument must be of type string\. Received /;
|
||||
[1, false, null, undefined, {}].forEach((value) => {
|
||||
console.log(value);
|
||||
assert.throws(
|
||||
() => { require(value); },
|
||||
{
|
||||
name: 'TypeError',
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: re
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
assert.throws(
|
||||
() => { require(''); },
|
||||
{
|
||||
name: 'TypeError',
|
||||
code: 'ERR_INVALID_ARG_VALUE',
|
||||
// Bun uses `"` instead of `'` in util.inspect
|
||||
message: 'The argument \'id\' must be a non-empty string. Received ""'
|
||||
});
|
||||
|
||||
// Folder read operation succeeds in AIX.
|
||||
// For libuv change, see https://github.com/libuv/libuv/pull/2025.
|
||||
// https://github.com/nodejs/node/pull/48477#issuecomment-1604586650
|
||||
assert.throws(
|
||||
() => { require('../fixtures/packages/is-dir'); },
|
||||
common.isAIX ? { code: 'ERR_INVALID_PACKAGE_CONFIG' } : {
|
||||
code: 'MODULE_NOT_FOUND',
|
||||
message: /Cannot find module '\.\.\/fixtures\/packages\/is-dir'/
|
||||
}
|
||||
);
|
||||
10
test/js/node/test/parallel/test-module-version.js
Normal file
10
test/js/node/test/parallel/test-module-version.js
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// check for existence
|
||||
assert(Object.hasOwn(process.config.variables, 'node_module_version'));
|
||||
|
||||
// Ensure that `node_module_version` is an Integer > 0
|
||||
assert(Number.isInteger(process.config.variables.node_module_version));
|
||||
assert(process.config.variables.node_module_version > 0);
|
||||
Reference in New Issue
Block a user