mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
Throw ERR_INVALID_THIS in DOM types (#13484)
This commit is contained in:
@@ -35,8 +35,11 @@
|
||||
#include <wtf/RefCounted.h>
|
||||
#include <wtf/text/WTFString.h>
|
||||
#include "blob.h"
|
||||
|
||||
namespace WebCore {
|
||||
|
||||
class ScriptExecutionContext;
|
||||
|
||||
template<typename> class ExceptionOr;
|
||||
class HTMLElement;
|
||||
class HTMLFormElement;
|
||||
@@ -84,6 +87,7 @@ public:
|
||||
size_t m_index { 0 };
|
||||
};
|
||||
Iterator createIterator() { return Iterator { *this }; }
|
||||
Iterator createIterator(const ScriptExecutionContext* context) { return Iterator { *this }; }
|
||||
|
||||
private:
|
||||
// explicit DOMFormData(ScriptExecutionContext*, const PAL::TextEncoding& = PAL::UTF8Encoding());
|
||||
|
||||
@@ -399,6 +399,11 @@ extern "C" JSC::EncodedJSValue WebCore__CommonAbortReason__toJS(JSC::JSGlobalObj
|
||||
return JSC::JSValue::encode(WebCore::toJS(globalObject, abortReason));
|
||||
}
|
||||
|
||||
JSC::JSObject* Bun::createInvalidThisError(JSC::JSGlobalObject* globalObject, const String& message)
|
||||
{
|
||||
return Bun::createError(globalObject, Bun::ErrorCode::ERR_INVALID_THIS, message);
|
||||
}
|
||||
|
||||
JSC::JSObject* Bun::createInvalidThisError(JSC::JSGlobalObject* globalObject, JSC::JSValue thisValue, const ASCIILiteral typeName)
|
||||
{
|
||||
if (thisValue.isEmpty() || thisValue.isUndefined()) {
|
||||
@@ -408,4 +413,9 @@ JSC::JSObject* Bun::createInvalidThisError(JSC::JSGlobalObject* globalObject, JS
|
||||
// Pathological case: the this value returns a string which is extremely long or causes an out of memory error.
|
||||
const auto& typeString = thisValue.isString() ? String("a string"_s) : JSC::errorDescriptionForValue(globalObject, thisValue);
|
||||
return Bun::createError(globalObject, Bun::ErrorCode::ERR_INVALID_THIS, makeString("Expected this to be instanceof "_s, typeName, ", but received "_s, typeString));
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue Bun::throwError(JSC::JSGlobalObject* globalObject, JSC::ThrowScope& scope, Bun::ErrorCode code, const WTF::String& message)
|
||||
{
|
||||
return JSC::JSValue::encode(scope.throwException(globalObject, createError(globalObject, code, message)));
|
||||
}
|
||||
@@ -46,12 +46,14 @@ private:
|
||||
void finishCreation(VM&);
|
||||
};
|
||||
|
||||
JSC::EncodedJSValue throwError(JSC::JSGlobalObject* globalObject, JSC::ThrowScope& scope, ErrorCode code, const WTF::String& message);
|
||||
JSC::JSObject* createError(Zig::GlobalObject* globalObject, ErrorCode code, const WTF::String& message);
|
||||
JSC::JSObject* createError(JSC::JSGlobalObject* globalObject, ErrorCode code, const WTF::String& message);
|
||||
JSC::JSObject* createError(Zig::GlobalObject* globalObject, ErrorCode code, JSC::JSValue message);
|
||||
JSC::JSObject* createError(VM& vm, Zig::GlobalObject* globalObject, ErrorCode code, JSValue message, JSValue options = jsUndefined());
|
||||
JSC::JSValue toJS(JSC::JSGlobalObject*, ErrorCode);
|
||||
JSObject* createInvalidThisError(JSGlobalObject* globalObject, JSValue thisValue, const ASCIILiteral typeName);
|
||||
JSObject* createInvalidThisError(JSGlobalObject* globalObject, const String& message);
|
||||
|
||||
JSC_DECLARE_HOST_FUNCTION(jsFunction_ERR_INVALID_ARG_TYPE);
|
||||
JSC_DECLARE_HOST_FUNCTION(jsFunction_ERR_OUT_OF_RANGE);
|
||||
|
||||
@@ -71,6 +71,8 @@ enum ExceptionCode {
|
||||
|
||||
// Used to indicate to the bindings that a JS exception was thrown below and it should be propagated.
|
||||
ExistingExceptionError,
|
||||
|
||||
InvalidThisError,
|
||||
};
|
||||
|
||||
} // namespace WebCore
|
||||
@@ -116,7 +118,8 @@ template<> struct EnumTraits<WebCore::ExceptionCode> {
|
||||
WebCore::ExceptionCode::TypeError,
|
||||
WebCore::ExceptionCode::JSSyntaxError,
|
||||
WebCore::ExceptionCode::StackOverflowError,
|
||||
WebCore::ExceptionCode::ExistingExceptionError>;
|
||||
WebCore::ExceptionCode::ExistingExceptionError,
|
||||
WebCore::ExceptionCode::InvalidThisError>;
|
||||
};
|
||||
|
||||
} // namespace WTF
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "ErrorCode.h"
|
||||
|
||||
#include "DOMException.h"
|
||||
#include "JSDOMException.h"
|
||||
#include "JSDOMExceptionHandling.h"
|
||||
@@ -173,6 +175,9 @@ JSValue createDOMException(JSGlobalObject* lexicalGlobalObject, ExceptionCode ec
|
||||
case ExceptionCode::OutOfMemoryError:
|
||||
return createOutOfMemoryError(lexicalGlobalObject);
|
||||
|
||||
case ExceptionCode::InvalidThisError:
|
||||
return Bun::createInvalidThisError(lexicalGlobalObject, message.isEmpty() ? "Expected this to be of a different type"_s : message);
|
||||
|
||||
default: {
|
||||
// FIXME: All callers to createDOMException need to pass in the correct global object.
|
||||
// For now, we're going to assume the lexicalGlobalObject. Which is wrong in cases like this:
|
||||
@@ -233,22 +238,22 @@ void throwSecurityError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScop
|
||||
|
||||
JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral functionInterfaceName, ASCIILiteral functionName, ASCIILiteral expectedValues)
|
||||
{
|
||||
return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, functionInterfaceName, functionName, "one of: "_s, expectedValues));
|
||||
return Bun::throwError(&lexicalGlobalObject, scope, Bun::ErrorCode::ERR_INVALID_ARG_TYPE, makeArgumentTypeErrorMessage(argumentIndex, argumentName, functionInterfaceName, functionName, "one of: "_s, expectedValues));
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral interfaceName, ASCIILiteral functionName)
|
||||
{
|
||||
return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, interfaceName, functionName, "a function"_s));
|
||||
return Bun::throwError(&lexicalGlobalObject, scope, Bun::ErrorCode::ERR_INVALID_ARG_TYPE, makeArgumentTypeErrorMessage(argumentIndex, argumentName, interfaceName, functionName, "a function"_s));
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue throwArgumentMustBeObjectError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral interfaceName, ASCIILiteral functionName)
|
||||
{
|
||||
return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, interfaceName, functionName, "an object"_s));
|
||||
return Bun::throwError(&lexicalGlobalObject, scope, Bun::ErrorCode::ERR_INVALID_ARG_TYPE, makeArgumentTypeErrorMessage(argumentIndex, argumentName, interfaceName, functionName, "an object"_s));
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue throwArgumentTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral functionInterfaceName, ASCIILiteral functionName, ASCIILiteral expectedType)
|
||||
{
|
||||
return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, functionInterfaceName, functionName, "an instance of "_s, expectedType));
|
||||
return Bun::throwError(&lexicalGlobalObject, scope, Bun::ErrorCode::ERR_INVALID_ARG_TYPE, makeArgumentTypeErrorMessage(argumentIndex, argumentName, functionInterfaceName, functionName, "an instance of "_s, expectedType));
|
||||
}
|
||||
|
||||
void throwAttributeTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral interfaceName, ASCIILiteral attributeName, ASCIILiteral expectedType)
|
||||
@@ -258,7 +263,7 @@ void throwAttributeTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::Thro
|
||||
|
||||
JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral memberName, ASCIILiteral dictionaryName, ASCIILiteral expectedType)
|
||||
{
|
||||
return throwVMTypeError(&lexicalGlobalObject, scope, makeString("Member "_s, dictionaryName, '.', memberName, " is required and must be an instance of "_s, expectedType));
|
||||
return Bun::throwError(&lexicalGlobalObject, scope, Bun::ErrorCode::ERR_INVALID_ARG_TYPE, makeString("Member "_s, dictionaryName, '.', memberName, " is required and must be an instance of "_s, expectedType));
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral interfaceName)
|
||||
@@ -268,7 +273,7 @@ JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::
|
||||
|
||||
void throwSequenceTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope)
|
||||
{
|
||||
throwTypeError(lexicalGlobalObject, scope, "Value is not a sequence"_s);
|
||||
Bun::throwError(&lexicalGlobalObject, scope, Bun::ErrorCode::ERR_INVALID_ARG_TYPE, "Value is not a sequence"_s);
|
||||
}
|
||||
|
||||
void throwNonFiniteTypeError(JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope)
|
||||
@@ -294,12 +299,12 @@ String makeUnsupportedIndexedSetterErrorMessage(ASCIILiteral interfaceName)
|
||||
|
||||
EncodedJSValue throwThisTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const char* interfaceName, const char* functionName)
|
||||
{
|
||||
return throwTypeError(lexicalGlobalObject, scope, makeThisTypeErrorMessage(interfaceName, functionName));
|
||||
return JSValue::encode(scope.throwException(&lexicalGlobalObject, Bun::createInvalidThisError(&lexicalGlobalObject, makeThisTypeErrorMessage(interfaceName, functionName))));
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise& promise, const char* interfaceName, const char* methodName)
|
||||
{
|
||||
promise.reject(ExceptionCode::TypeError, makeThisTypeErrorMessage(interfaceName, methodName));
|
||||
promise.reject(ExceptionCode::InvalidThisError, makeThisTypeErrorMessage(interfaceName, methodName));
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
namespace WebCore {
|
||||
|
||||
class DOMURL;
|
||||
class ScriptExecutionContext;
|
||||
|
||||
class URLSearchParams : public RefCounted<URLSearchParams> {
|
||||
public:
|
||||
@@ -66,6 +67,7 @@ public:
|
||||
size_t m_index { 0 };
|
||||
};
|
||||
Iterator createIterator() { return Iterator { *this }; }
|
||||
Iterator createIterator(const ScriptExecutionContext* context) { return Iterator { *this }; }
|
||||
|
||||
private:
|
||||
const Vector<KeyValuePair<String, String>>& pairs() const { return m_pairs; }
|
||||
|
||||
@@ -35,7 +35,11 @@
|
||||
#include <wtf/Vector.h>
|
||||
|
||||
namespace WebCore {
|
||||
|
||||
class ScriptExecutionContext;
|
||||
|
||||
DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(FetchHeaders);
|
||||
|
||||
class FetchHeaders : public RefCounted<FetchHeaders> {
|
||||
WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(FetchHeaders);
|
||||
|
||||
@@ -103,6 +107,11 @@ public:
|
||||
return Iterator(*this, lowerCaseKeys);
|
||||
}
|
||||
|
||||
Iterator createIterator(const ScriptExecutionContext* context)
|
||||
{
|
||||
return Iterator(*this, true);
|
||||
}
|
||||
|
||||
void setInternalHeaders(HTTPHeaderMap&& headers) { m_headers = WTFMove(headers); }
|
||||
const HTTPHeaderMap& internalHeaders() const { return m_headers; }
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
#include <JavaScriptCore/IteratorPrototype.h>
|
||||
#include <JavaScriptCore/PropertySlot.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include "ErrorCode.h"
|
||||
#include "JavaScriptCore/Interpreter.h"
|
||||
namespace WebCore {
|
||||
|
||||
void addValueIterableMethods(JSC::JSGlobalObject&, JSC::JSObject&);
|
||||
@@ -101,7 +102,9 @@ public:
|
||||
|
||||
static Prototype* createPrototype(JSC::VM& vm, JSC::JSGlobalObject& globalObject)
|
||||
{
|
||||
return Prototype::create(vm, &globalObject, Prototype::createStructure(vm, &globalObject, globalObject.iteratorPrototype()));
|
||||
auto* structure = Prototype::createStructure(vm, &globalObject, globalObject.iteratorPrototype());
|
||||
structure->setMayBePrototype(true);
|
||||
return Prototype::create(vm, &globalObject, structure);
|
||||
}
|
||||
|
||||
JSC::JSValue next(JSC::JSGlobalObject&);
|
||||
@@ -111,7 +114,7 @@ public:
|
||||
protected:
|
||||
JSDOMIteratorBase(JSC::Structure* structure, JSWrapper& iteratedObject, IterationKind kind)
|
||||
: Base(structure, *iteratedObject.globalObject())
|
||||
, m_iterator(iteratedObject.wrapped().createIterator())
|
||||
, m_iterator(iteratedObject.wrapped().createIterator(iteratedObject.globalObject()->scriptExecutionContext()))
|
||||
, m_kind(kind)
|
||||
{
|
||||
}
|
||||
@@ -211,10 +214,12 @@ template<typename JSIterator> JSC::JSValue iteratorForEach(JSC::JSGlobalObject&
|
||||
JSC::JSValue thisValue = callFrame.argument(1);
|
||||
|
||||
auto callData = JSC::getCallData(callback);
|
||||
if (callData.type == JSC::CallData::Type::None)
|
||||
return throwTypeError(&lexicalGlobalObject, scope, "Cannot call callback"_s);
|
||||
if (callData.type == JSC::CallData::Type::None) {
|
||||
Bun::throwError(&lexicalGlobalObject, scope, Bun::ErrorCode::ERR_INVALID_ARG_TYPE, "Cannot call callback on a non-function"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
auto iterator = thisObject.wrapped().createIterator();
|
||||
auto iterator = thisObject.wrapped().createIterator(JSC::jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject)->scriptExecutionContext());
|
||||
while (auto value = iterator.next()) {
|
||||
JSC::MarkedArgumentBuffer arguments;
|
||||
appendForEachArguments<JSIterator>(lexicalGlobalObject, *thisObject.globalObject(), arguments, value);
|
||||
@@ -256,8 +261,9 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMIteratorPrototype<JSWrapper, I
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto iterator = JSC::jsDynamicCast<JSDOMIteratorBase<JSWrapper, IteratorTraits>*>(callFrame->thisValue());
|
||||
if (!iterator)
|
||||
return JSC::JSValue::encode(throwTypeError(globalObject, scope, "Cannot call next() on a non-Iterator object"_s));
|
||||
if (!iterator) {
|
||||
return Bun::throwError(globalObject, scope, Bun::ErrorCode::ERR_INVALID_THIS, "Cannot call next() on a non-Iterator object"_s);
|
||||
}
|
||||
|
||||
return JSC::JSValue::encode(iterator->next(*globalObject));
|
||||
}
|
||||
@@ -268,8 +274,8 @@ void JSDOMIteratorPrototype<JSWrapper, IteratorTraits>::finishCreation(JSC::VM&
|
||||
Base::finishCreation(vm);
|
||||
ASSERT(inherits(info()));
|
||||
|
||||
JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, next, 0, 0, ImplementationVisibility::Public, JSC::NoIntrinsic);
|
||||
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, next, 0, 0, JSC::ImplementationVisibility::Public);
|
||||
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include <JavaScriptCore/JSONObject.h>
|
||||
#include <JavaScriptCore/JSPromiseConstructor.h>
|
||||
#include <JavaScriptCore/Strong.h>
|
||||
#include "ErrorCode.h"
|
||||
#include "JavaScriptCore/ErrorInstance.h"
|
||||
|
||||
namespace WebCore {
|
||||
using namespace JSC;
|
||||
@@ -241,7 +243,7 @@ JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::JSGlobalObject& lexi
|
||||
auto promiseConstructor = globalObject.promiseConstructor();
|
||||
auto rejectFunction = promiseConstructor->get(&lexicalGlobalObject, vm.propertyNames->builtinNames().rejectPrivateName());
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto* rejectionValue = static_cast<ErrorInstance*>(createTypeError(&lexicalGlobalObject, errorMessage));
|
||||
ErrorInstance* rejectionValue = static_cast<ErrorInstance*>(cause == RejectedPromiseWithTypeErrorCause::InvalidThis ? Bun::createInvalidThisError(&lexicalGlobalObject, errorMessage) : createTypeError(&lexicalGlobalObject, errorMessage));
|
||||
if (cause == RejectedPromiseWithTypeErrorCause::NativeGetter)
|
||||
rejectionValue->setNativeGetterTypeError();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user