aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-27 02:42:02 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-27 02:45:30 -0700
commit309350e74cf0bf854c0148b627f6df8b5282ad2f (patch)
treee698660375ef137b1b16b06ba5c474fed18ce65b
parent0132b7164e956d56bf74dd8c45ad4cf90769961b (diff)
downloadbun-309350e74cf0bf854c0148b627f6df8b5282ad2f.tar.gz
bun-309350e74cf0bf854c0148b627f6df8b5282ad2f.tar.zst
bun-309350e74cf0bf854c0148b627f6df8b5282ad2f.zip
[bun.js] begin the webkit-ing
-rw-r--r--src/javascript/jsc/bindings/BunBuiltinNames.h11
-rw-r--r--src/javascript/jsc/bindings/BunClientData.cpp28
-rw-r--r--src/javascript/jsc/bindings/BunClientData.h56
-rw-r--r--src/javascript/jsc/bindings/BunGCOutputConstraint.cpp60
-rw-r--r--src/javascript/jsc/bindings/BunGCOutputConstraint.h24
-rw-r--r--src/javascript/jsc/bindings/DOMException.cpp116
-rw-r--r--src/javascript/jsc/bindings/DOMException.h73
-rw-r--r--src/javascript/jsc/bindings/DOMFormData.cpp180
-rw-r--r--src/javascript/jsc/bindings/DOMFormData.h89
-rw-r--r--src/javascript/jsc/bindings/DOMURL.cpp119
-rw-r--r--src/javascript/jsc/bindings/DOMURL.h71
-rw-r--r--src/javascript/jsc/bindings/Exception.h67
-rw-r--r--src/javascript/jsc/bindings/ExceptionCode.h122
-rw-r--r--src/javascript/jsc/bindings/ExceptionOr.h239
-rw-r--r--src/javascript/jsc/bindings/IDLTypes.h403
-rw-r--r--src/javascript/jsc/bindings/JSDOMExceptionHandling.cpp260
-rw-r--r--src/javascript/jsc/bindings/JSDOMExceptionHandling.h103
-rw-r--r--src/javascript/jsc/bindings/JSDOMURL.cpp321
-rw-r--r--src/javascript/jsc/bindings/JSDOMURL.h52
-rw-r--r--src/javascript/jsc/bindings/JSDOMWrapper.cpp61
-rw-r--r--src/javascript/jsc/bindings/JSDOMWrapper.h100
-rw-r--r--src/javascript/jsc/bindings/MarkingConstraint.cpp0
-rw-r--r--src/javascript/jsc/bindings/NodeConstants.h52
-rw-r--r--src/javascript/jsc/bindings/StringAdaptors.h46
-rw-r--r--src/javascript/jsc/bindings/URLDecomposition.cpp257
-rw-r--r--src/javascript/jsc/bindings/URLDecomposition.h75
-rw-r--r--src/javascript/jsc/bindings/URLSearchParams.cpp164
-rw-r--r--src/javascript/jsc/bindings/URLSearchParams.h77
-rw-r--r--src/javascript/jsc/bindings/ZigGlobalObject.cpp10
-rw-r--r--src/javascript/jsc/bindings/root.h2
30 files changed, 3196 insertions, 42 deletions
diff --git a/src/javascript/jsc/bindings/BunBuiltinNames.h b/src/javascript/jsc/bindings/BunBuiltinNames.h
index 708a37381..58c039cef 100644
--- a/src/javascript/jsc/bindings/BunBuiltinNames.h
+++ b/src/javascript/jsc/bindings/BunBuiltinNames.h
@@ -41,6 +41,10 @@ using namespace JSC;
macro(filePath) \
macro(format) \
macro(get) \
+ macro(hash) \
+ macro(host) \
+ macro(hostname) \
+ macro(href) \
macro(isAbsolute) \
macro(isPaused) \
macro(isWindows) \
@@ -51,9 +55,12 @@ using namespace JSC;
macro(on) \
macro(once) \
macro(options) \
+ macro(origin) \
macro(parse) \
+ macro(password) \
macro(patch) \
macro(path) \
+ macro(pathname) \
macro(pause) \
macro(pid) \
macro(pipe) \
@@ -62,12 +69,15 @@ using namespace JSC;
macro(ppid) \
macro(prependEventListener) \
macro(process) \
+ macro(protocol) \
macro(put) \
macro(read) \
macro(relative) \
macro(removeEventListener) \
macro(resolve) \
macro(resume) \
+ macro(search) \
+ macro(searchParams) \
macro(sep) \
macro(syscall) \
macro(title) \
@@ -77,6 +87,7 @@ using namespace JSC;
macro(unpipe) \
macro(unshift) \
macro(url) \
+ macro(username) \
macro(version) \
macro(versions) \
macro(write) \
diff --git a/src/javascript/jsc/bindings/BunClientData.cpp b/src/javascript/jsc/bindings/BunClientData.cpp
index 21db7cb7f..0bda7dd69 100644
--- a/src/javascript/jsc/bindings/BunClientData.cpp
+++ b/src/javascript/jsc/bindings/BunClientData.cpp
@@ -2,6 +2,7 @@
#include "BunClientData.h"
#include "root.h"
+#include "JSDOMURL.h"
#include <JavaScriptCore/FastMallocAlignedMemoryAllocator.h>
#include <JavaScriptCore/HeapInlines.h>
#include <JavaScriptCore/IsoHeapCellType.h>
@@ -15,10 +16,35 @@
namespace Bun {
using namespace JSC;
+using namespace WebCore;
+
+class ExtendedDOMClientIsoSubspaces;
+class ExtendedDOMIsoSubspaces;
+
+#define CLIENT_ISO_SUBSPACE_INIT(subspace) subspace(m_heapData->subspace)
+JSHeapData::JSHeapData(Heap& heap)
+ : m_domNamespaceObjectSpace ISO_SUBSPACE_INIT(heap, heap.cellHeapCellType, JSDOMObject)
+
+{
+}
JSVMClientData::JSVMClientData(VM& vm)
: m_builtinNames(vm)
+ , m_heapData(JSHeapData::ensureHeapData(vm.heap))
+{
+}
+
+JSHeapData* JSHeapData::ensureHeapData(Heap& heap)
{
+ if (!Options::useGlobalGC())
+ return new JSHeapData(heap);
+
+ static JSHeapData* singleton = nullptr;
+ static std::once_flag onceFlag;
+ std::call_once(onceFlag, [&] {
+ singleton = new JSHeapData(heap);
+ });
+ return singleton;
}
JSVMClientData::~JSVMClientData() {}
@@ -28,7 +54,7 @@ void JSVMClientData::create(VM* vm)
JSVMClientData* clientData = new JSVMClientData(*vm);
vm->clientData = clientData; // ~VM deletes this pointer.
- // vm->heap.addMarkingConstraint(makeUnique<BunGCOutputConstraint>(*vm, *clientData));
+ // vm->heap.addMarkingConstraint(makeUnique<BunGCOutputConstraint>(*vm, *clientData));
// vm->m_typedArrayController = adoptRef(new WebCoreTypedArrayController(
// type == WorkerThreadType::DedicatedWorker || type == WorkerThreadType::Worklet));
diff --git a/src/javascript/jsc/bindings/BunClientData.h b/src/javascript/jsc/bindings/BunClientData.h
index 6e3747bb1..fc48148cd 100644
--- a/src/javascript/jsc/bindings/BunClientData.h
+++ b/src/javascript/jsc/bindings/BunClientData.h
@@ -3,12 +3,49 @@
#include "BunBuiltinNames.h"
#include "root.h"
#include <JavaScriptCore/BuiltinUtils.h>
+#include <JavaScriptCore/IsoSubspacePerVM.h>
+#include <JavaScriptCore/JSDestructibleObjectHeapCellType.h>
#include <wtf/HashSet.h>
#include <wtf/RefPtr.h>
namespace Bun {
using namespace JSC;
+enum class UseCustomHeapCellType { Yes,
+ No };
+
+class JSHeapData {
+ WTF_MAKE_NONCOPYABLE(JSHeapData);
+ WTF_MAKE_FAST_ALLOCATED;
+ friend class JSVMClientData;
+
+public:
+ JSHeapData(JSC::Heap&);
+
+ static JSHeapData* ensureHeapData(JSC::Heap&);
+
+ Lock& lock() { return m_lock; }
+ // ExtendedDOMIsoSubspaces& subspaces() { return *m_subspaces.get(); }
+
+ Vector<JSC::IsoSubspace*>& outputConstraintSpaces() { return m_outputConstraintSpaces; }
+
+ template<typename Func>
+ void forEachOutputConstraintSpace(const Func& func)
+ {
+ for (auto* space : m_outputConstraintSpaces)
+ func(*space);
+ }
+
+ JSC::IsoSubspace m_domNamespaceObjectSpace;
+
+private:
+ Lock m_lock;
+
+private:
+ // std::unique_ptr<ExtendedDOMIsoSubspaces> m_subspaces;
+ Vector<JSC::IsoSubspace*> m_outputConstraintSpaces;
+};
+
class JSVMClientData : public JSC::VM::ClientData {
WTF_MAKE_NONCOPYABLE(JSVMClientData);
WTF_MAKE_FAST_ALLOCATED;
@@ -20,20 +57,35 @@ public:
static void create(JSC::VM*);
+ JSHeapData& heapData() { return *m_heapData; }
BunBuiltinNames& builtinNames() { return m_builtinNames; }
+ // ExtendedDOMClientIsoSubspaces& clientSubspaces() { return *m_clientSubspaces.get(); }
// Vector<JSC::IsoSubspace *> &outputConstraintSpaces() { return m_outputConstraintSpaces; }
- // template <typename Func> void forEachOutputConstraintSpace(const Func &func) {
- // for (auto *space : m_outputConstraintSpaces) func(*space);
+ // template<typename Func> void forEachOutputConstraintSpace(const Func& func)
+ // {
+ // for (auto* space : m_outputConstraintSpaces)
+ // func(*space);
// }
private:
BunBuiltinNames m_builtinNames;
+ JSHeapData* m_heapData;
+
// Vector<JSC::IsoSubspace *> m_outputConstraintSpaces;
};
+template<typename T, UseCustomHeapCellType useCustomHeapCellType, typename GetClient, typename SetClient, typename GetServer, typename SetServer>
+ALWAYS_INLINE JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm, GetClient getClient, SetClient setClient, GetServer getServer, SetServer setServer, JSC::HeapCellType& (*getCustomHeapCellType)(JSHeapData&) = nullptr)
+{
+ static NeverDestroyed<JSC::IsoSubspacePerVM> perVM([](JSC::Heap& heap) {
+ return ISO_SUBSPACE_PARAMETERS(heap.destructibleObjectHeapCellType, T);
+ });
+ return &perVM.get().clientIsoSubspaceforVM(vm);
+}
+
static JSVMClientData* clientData(JSC::VM& vm)
{
return static_cast<Bun::JSVMClientData*>(vm.clientData);
diff --git a/src/javascript/jsc/bindings/BunGCOutputConstraint.cpp b/src/javascript/jsc/bindings/BunGCOutputConstraint.cpp
index bc99ef2e2..53f4bbb90 100644
--- a/src/javascript/jsc/bindings/BunGCOutputConstraint.cpp
+++ b/src/javascript/jsc/bindings/BunGCOutputConstraint.cpp
@@ -14,34 +14,40 @@
// using namespace JSC;
-// BunGCOutputConstraint::BunGCOutputConstraint(VM &vm, Bun::JSVMClientData &clientData)
-// : MarkingConstraint("Domo", "DOM Output", ConstraintVolatility::SeldomGreyed,
-// ConstraintConcurrency::Concurrent, ConstraintParallelism::Parallel),
-// m_vm(vm),
-// m_clientData(clientData),
-// m_lastExecutionVersion(vm.heap.mutatorExecutionVersion()) {}
-
-// template <typename Visitor> void BunGCOutputConstraint::executeImplImpl(Visitor &visitor) {
-// Heap &heap = m_vm.heap;
-
-// if (heap.mutatorExecutionVersion() == m_lastExecutionVersion) return;
-
-// m_lastExecutionVersion = heap.mutatorExecutionVersion();
-
-// m_clientData.forEachOutputConstraintSpace([&](Subspace &subspace) {
-// auto func = [](Visitor &visitor, HeapCell *heapCell, HeapCell::Kind) {
-// SetRootMarkReasonScope rootScope(visitor, RootMarkReason::DOMGCOutput);
-// JSCell *cell = static_cast<JSCell *>(heapCell);
-// cell->methodTable(visitor.vm())->visitOutputConstraints(cell, visitor);
-// };
-
-// RefPtr<SharedTask<void(Visitor &)>> task =
-// subspace.template forEachMarkedCellInParallel<Visitor>(func);
-// visitor.addParallelConstraintTask(task);
-// });
+// BunGCOutputConstraint::BunGCOutputConstraint(VM& vm, Bun::JSVMClientData& clientData)
+// : MarkingConstraint("Domo", "DOM Output", ConstraintVolatility::SeldomGreyed,
+// ConstraintConcurrency::Concurrent, ConstraintParallelism::Parallel)
+// , m_vm(vm)
+// , m_clientData(clientData)
+// , m_lastExecutionVersion(vm.heap.mutatorExecutionVersion())
+// {
// }
-// void BunGCOutputConstraint::executeImpl(AbstractSlotVisitor &visitor) { executeImplImpl(visitor);
-// } void BunGCOutputConstraint::executeImpl(SlotVisitor &visitor) { executeImplImpl(visitor); }
+// template<typename Visitor> void BunGCOutputConstraint::executeImplImpl(Visitor& visitor)
+// {
+// Heap& heap = m_vm.heap;
+
+// if (heap.mutatorExecutionVersion() == m_lastExecutionVersion)
+// return;
+
+// m_lastExecutionVersion = heap.mutatorExecutionVersion();
+
+// m_clientData.forEachOutputConstraintSpace([&](Subspace& subspace) {
+// auto func = [](Visitor& visitor, HeapCell* heapCell, HeapCell::Kind) {
+// SetRootMarkReasonScope rootScope(visitor, RootMarkReason::DOMGCOutput);
+// JSCell* cell = static_cast<JSCell*>(heapCell);
+// cell->methodTable(visitor.vm())->visitOutputConstraints(cell, visitor);
+// };
+
+// RefPtr<SharedTask<void(Visitor&)>> task = subspace.template forEachMarkedCellInParallel<Visitor>(func);
+// visitor.addParallelConstraintTask(task);
+// });
+// }
+
+// void BunGCOutputConstraint::executeImpl(AbstractSlotVisitor& visitor)
+// {
+// executeImplImpl(visitor);
+// }
+// void BunGCOutputConstraint::executeImpl(SlotVisitor& visitor) { executeImplImpl(visitor); }
// } // namespace Bun
diff --git a/src/javascript/jsc/bindings/BunGCOutputConstraint.h b/src/javascript/jsc/bindings/BunGCOutputConstraint.h
index 521b0da8c..003f110b4 100644
--- a/src/javascript/jsc/bindings/BunGCOutputConstraint.h
+++ b/src/javascript/jsc/bindings/BunGCOutputConstraint.h
@@ -13,22 +13,22 @@
// class JSVMClientData;
// class BunGCOutputConstraint : public JSC::MarkingConstraint {
-// WTF_MAKE_FAST_ALLOCATED;
+// WTF_MAKE_FAST_ALLOCATED;
-// public:
-// BunGCOutputConstraint(JSC::VM &, Bun::JSVMClientData &);
-// ~BunGCOutputConstraint(){};
+// public:
+// BunGCOutputConstraint(JSC::VM&, Bun::JSVMClientData&);
+// ~BunGCOutputConstraint() {};
-// protected:
-// void executeImpl(JSC::AbstractSlotVisitor &) override;
-// void executeImpl(JSC::SlotVisitor &) override;
+// protected:
+// void executeImpl(JSC::AbstractSlotVisitor&) override;
+// void executeImpl(JSC::SlotVisitor&) override;
-// private:
-// template <typename Visitor> void executeImplImpl(Visitor &);
+// private:
+// template<typename Visitor> void executeImplImpl(Visitor&);
-// JSC::VM &m_vm;
-// JSVMClientData &m_clientData;
-// uint64_t m_lastExecutionVersion;
+// JSC::VM& m_vm;
+// JSVMClientData& m_clientData;
+// uint64_t m_lastExecutionVersion;
// };
// } // namespace Bun
diff --git a/src/javascript/jsc/bindings/DOMException.cpp b/src/javascript/jsc/bindings/DOMException.cpp
new file mode 100644
index 000000000..232fb83fe
--- /dev/null
+++ b/src/javascript/jsc/bindings/DOMException.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "DOMException.h"
+
+#include "Exception.h"
+
+namespace WebCore {
+
+// This array needs to be kept in sync with the ExceptionCode enumeration.
+// http://heycam.github.io/webidl/#idl-DOMException-error-names
+static const DOMException::Description descriptions[] = {
+ { "IndexSizeError"_s, "The index is not in the allowed range."_s, 1 },
+ { "HierarchyRequestError"_s, "The operation would yield an incorrect node tree."_s, 3 },
+ { "WrongDocumentError"_s, "The object is in the wrong document."_s, 4 },
+ { "InvalidCharacterError"_s, "The string contains invalid characters."_s, 5 },
+ { "NoModificationAllowedError"_s, "The object can not be modified."_s, 7 },
+ { "NotFoundError"_s, "The object can not be found here."_s, 8 },
+ { "NotSupportedError"_s, "The operation is not supported."_s, 9 },
+ { "InUseAttributeError"_s, "The attribute is in use."_s, 10 },
+ { "InvalidStateError"_s, "The object is in an invalid state."_s, 11 },
+ { "SyntaxError"_s, "The string did not match the expected pattern."_s, 12 },
+ { "InvalidModificationError"_s, " The object can not be modified in this way."_s, 13 },
+ { "NamespaceError"_s, "The operation is not allowed by Namespaces in XML."_s, 14 },
+ { "InvalidAccessError"_s, "The object does not support the operation or argument."_s, 15 },
+ { "TypeMismatchError"_s, "The type of an object was incompatible with the expected type of the parameter associated to the object."_s, 17 },
+ { "SecurityError"_s, "The operation is insecure."_s, 18 },
+ { "NetworkError"_s, " A network error occurred."_s, 19 },
+ { "AbortError"_s, "The operation was aborted."_s, 20 },
+ { "URLMismatchError"_s, "The given URL does not match another URL."_s, 21 },
+ { "QuotaExceededError"_s, "The quota has been exceeded."_s, 22 },
+ { "TimeoutError"_s, "The operation timed out."_s, 23 },
+ { "InvalidNodeTypeError"_s, "The supplied node is incorrect or has an incorrect ancestor for this operation."_s, 24 },
+ { "DataCloneError"_s, "The object can not be cloned."_s, 25 },
+ { "EncodingError"_s, "The encoding operation (either encoded or decoding) failed."_s, 0 },
+ { "NotReadableError"_s, "The I/O read operation failed."_s, 0 },
+ { "UnknownError"_s, "The operation failed for an unknown transient reason (e.g. out of memory)."_s, 0 },
+ { "ConstraintError"_s, "A mutation operation in a transaction failed because a constraint was not satisfied."_s, 0 },
+ { "DataError"_s, "Provided data is inadequate."_s, 0 },
+ { "TransactionInactiveError"_s, "A request was placed against a transaction which is currently not active, or which is finished."_s, 0 },
+ { "ReadOnlyError"_s, "The mutating operation was attempted in a \"readonly\" transaction."_s, 0 },
+ { "VersionError"_s, "An attempt was made to open a database using a lower version than the existing version."_s, 0 },
+ { "OperationError"_s, "The operation failed for an operation-specific reason."_s, 0 },
+ { "NotAllowedError"_s, "The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission."_s, 0 }
+};
+static_assert(!IndexSizeError, "This table needs to be kept in sync with DOMException names in ExceptionCode enumeration");
+static_assert(NotAllowedError == WTF_ARRAY_LENGTH(descriptions) - 1, "This table needs to be kept in sync with DOMException names in ExceptionCode enumeration");
+
+auto DOMException::description(ExceptionCode ec) -> const Description&
+{
+ if (ec < WTF_ARRAY_LENGTH(descriptions))
+ return descriptions[ec];
+
+ static const Description emptyDescription { ASCIILiteral::null(), ASCIILiteral::null(), 0 };
+ return emptyDescription;
+}
+
+static DOMException::LegacyCode legacyCodeFromName(const String& name)
+{
+ for (auto& description : descriptions) {
+ if (description.name == name)
+ return description.legacyCode;
+ }
+ return 0;
+}
+
+Ref<DOMException> DOMException::create(ExceptionCode ec, const String& message)
+{
+ auto& description = DOMException::description(ec);
+ return adoptRef(*new DOMException(description.legacyCode, description.name, !message.isEmpty() ? message : description.message));
+}
+
+Ref<DOMException> DOMException::create(const String& message, const String& name)
+{
+ return adoptRef(*new DOMException(legacyCodeFromName(name), name, message));
+}
+
+Ref<DOMException> DOMException::create(const Exception& exception)
+{
+ auto& description = DOMException::description(exception.code());
+ return adoptRef(*new DOMException(description.legacyCode, description.name, exception.message().isEmpty() ? description.message : exception.message()));
+}
+
+DOMException::DOMException(LegacyCode legacyCode, const String& name, const String& message)
+ : m_legacyCode(legacyCode)
+ , m_name(name)
+ , m_message(message)
+{
+}
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/DOMException.h b/src/javascript/jsc/bindings/DOMException.h
new file mode 100644
index 000000000..b764393c1
--- /dev/null
+++ b/src/javascript/jsc/bindings/DOMException.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "root.h"
+
+#include "ExceptionCode.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Exception;
+
+class DOMException : public RefCounted<DOMException> {
+public:
+ static Ref<DOMException> create(ExceptionCode, const String& message = emptyString());
+ static Ref<DOMException> create(const Exception&);
+
+ // For DOM bindings.
+ static Ref<DOMException> create(const String& message, const String& name);
+
+ using LegacyCode = uint8_t;
+ LegacyCode legacyCode() const { return m_legacyCode; }
+
+ String name() const { return m_name; }
+ String message() const { return m_message; }
+
+ struct Description {
+ const ASCIILiteral name;
+ const ASCIILiteral message;
+ LegacyCode legacyCode;
+ };
+
+ WEBCORE_EXPORT static const Description& description(ExceptionCode);
+
+ static ASCIILiteral name(ExceptionCode ec) { return description(ec).name; }
+ static ASCIILiteral message(ExceptionCode ec) { return description(ec).message; }
+
+protected:
+ DOMException(LegacyCode, const String& name, const String& message);
+
+private:
+ LegacyCode m_legacyCode;
+ String m_name;
+ String m_message;
+};
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/DOMFormData.cpp b/src/javascript/jsc/bindings/DOMFormData.cpp
new file mode 100644
index 000000000..54c629f37
--- /dev/null
+++ b/src/javascript/jsc/bindings/DOMFormData.cpp
@@ -0,0 +1,180 @@
+// /*
+// * Copyright (C) 2010 Google Inc. All rights reserved.
+// *
+// * Redistribution and use in source and binary forms, with or without
+// * modification, are permitted provided that the following conditions are
+// * met:
+// *
+// * * Redistributions of source code must retain the above copyright
+// * notice, this list of conditions and the following disclaimer.
+// * * Redistributions in binary form must reproduce the above
+// * copyright notice, this list of conditions and the following disclaimer
+// * in the documentation and/or other materials provided with the
+// * distribution.
+// * * Neither the name of Google Inc. nor the names of its
+// * contributors may be used to endorse or promote products derived from
+// * this software without specific prior written permission.
+// *
+// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// */
+
+// #include "config.h"
+// #include "DOMFormData.h"
+
+// #include "Document.h"
+// #include "HTMLFormControlElement.h"
+// #include "HTMLFormElement.h"
+
+// namespace WebCore {
+
+// DOMFormData::DOMFormData(const PAL::TextEncoding& encoding)
+// : m_encoding(encoding)
+// {
+// }
+
+// ExceptionOr<Ref<DOMFormData>> DOMFormData::create(HTMLFormElement* form)
+// {
+// auto formData = adoptRef(*new DOMFormData);
+// if (!form)
+// return formData;
+
+// auto result = form->constructEntryList(WTFMove(formData), nullptr);
+
+// if (!result)
+// return Exception { InvalidStateError, "Already constructing Form entry list."_s };
+
+// return result.releaseNonNull();
+// }
+
+// Ref<DOMFormData> DOMFormData::create(const PAL::TextEncoding& encoding)
+// {
+// return adoptRef(*new DOMFormData(encoding));
+// }
+
+// Ref<DOMFormData> DOMFormData::clone() const
+// {
+// auto newFormData = adoptRef(*new DOMFormData(this->encoding()));
+// newFormData->m_items = m_items;
+
+// return newFormData;
+// }
+
+// // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry
+// static auto createStringEntry(const String& name, const String& value) -> DOMFormData::Item
+// {
+// return {
+// replaceUnpairedSurrogatesWithReplacementCharacter(String(name)),
+// replaceUnpairedSurrogatesWithReplacementCharacter(String(value)),
+// };
+// }
+
+// void DOMFormData::append(const String& name, const String& value)
+// {
+// m_items.append(createStringEntry(name, value));
+// }
+
+// void DOMFormData::append(const String& name, Blob& blob, const String& filename)
+// {
+// m_items.append(createFileEntry(name, blob, filename));
+// }
+
+// void DOMFormData::remove(const String& name)
+// {
+// m_items.removeAllMatching([&name](const auto& item) {
+// return item.name == name;
+// });
+// }
+
+// auto DOMFormData::get(const String& name) -> std::optional<FormDataEntryValue>
+// {
+// for (auto& item : m_items) {
+// if (item.name == name)
+// return item.data;
+// }
+
+// return std::nullopt;
+// }
+
+// auto DOMFormData::getAll(const String& name) -> Vector<FormDataEntryValue>
+// {
+// Vector<FormDataEntryValue> result;
+
+// for (auto& item : m_items) {
+// if (item.name == name)
+// result.append(item.data);
+// }
+
+// return result;
+// }
+
+// bool DOMFormData::has(const String& name)
+// {
+// for (auto& item : m_items) {
+// if (item.name == name)
+// return true;
+// }
+
+// return false;
+// }
+
+// void DOMFormData::set(const String& name, const String& value)
+// {
+// set(name, { name, value });
+// }
+
+// void DOMFormData::set(const String& name, Blob& blob, const String& filename)
+// {
+// set(name, createFileEntry(name, blob, filename));
+// }
+
+// void DOMFormData::set(const String& name, Item&& item)
+// {
+// std::optional<size_t> initialMatchLocation;
+
+// // Find location of the first item with a matching name.
+// for (size_t i = 0; i < m_items.size(); ++i) {
+// if (name == m_items[i].name) {
+// initialMatchLocation = i;
+// break;
+// }
+// }
+
+// if (initialMatchLocation) {
+// m_items[*initialMatchLocation] = WTFMove(item);
+
+// m_items.removeAllMatching([&name](const auto& item) {
+// return item.name == name;
+// },
+// *initialMatchLocation + 1);
+// return;
+// }
+
+// m_items.append(WTFMove(item));
+// }
+
+// DOMFormData::Iterator::Iterator(DOMFormData& target)
+// : m_target(target)
+// {
+// }
+
+// std::optional<KeyValuePair<String, DOMFormData::FormDataEntryValue>> DOMFormData::Iterator::next()
+// {
+// auto& items = m_target->items();
+// if (m_index >= items.size())
+// return std::nullopt;
+
+// auto& item = items[m_index++];
+// return makeKeyValuePair(item.name, item.data);
+// }
+
+// } // namespace WebCore
diff --git a/src/javascript/jsc/bindings/DOMFormData.h b/src/javascript/jsc/bindings/DOMFormData.h
new file mode 100644
index 000000000..9592afdbe
--- /dev/null
+++ b/src/javascript/jsc/bindings/DOMFormData.h
@@ -0,0 +1,89 @@
+// /*
+// * Copyright (C) 2010 Google Inc. All rights reserved.
+// *
+// * Redistribution and use in source and binary forms, with or without
+// * modification, are permitted provided that the following conditions are
+// * met:
+// *
+// * * Redistributions of source code must retain the above copyright
+// * notice, this list of conditions and the following disclaimer.
+// * * Redistributions in binary form must reproduce the above
+// * copyright notice, this list of conditions and the following disclaimer
+// * in the documentation and/or other materials provided with the
+// * distribution.
+// * * Neither the name of Google Inc. nor the names of its
+// * contributors may be used to endorse or promote products derived from
+// * this software without specific prior written permission.
+// *
+// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// */
+
+// #pragma once
+
+// #include "File.h"
+// #include <pal/text/TextEncoding.h>
+// #include <variant>
+// #include <wtf/RefCounted.h>
+// #include <wtf/text/WTFString.h>
+
+// namespace WebCore {
+
+// template<typename> class ExceptionOr;
+// class HTMLFormElement;
+
+// class DOMFormData : public RefCounted<DOMFormData> {
+// public:
+// using FormDataEntryValue = std::variant<RefPtr<File>, String>;
+
+// struct Item {
+// String name;
+// FormDataEntryValue data;
+// };
+
+// static ExceptionOr<Ref<DOMFormData>> create(HTMLFormElement*);
+// static Ref<DOMFormData> create(const PAL::TextEncoding&);
+
+// const Vector<Item>& items() const { return m_items; }
+// const PAL::TextEncoding& encoding() const { return m_encoding; }
+
+// void append(const String& name, const String& value);
+// void append(const String& name, Blob&, const String& filename = { });
+// void remove(const String& name);
+// std::optional<FormDataEntryValue> get(const String& name);
+// Vector<FormDataEntryValue> getAll(const String& name);
+// bool has(const String& name);
+// void set(const String& name, const String& value);
+// void set(const String& name, Blob&, const String& filename = { });
+// Ref<DOMFormData> clone() const;
+
+// class Iterator {
+// public:
+// explicit Iterator(DOMFormData&);
+// std::optional<KeyValuePair<String, FormDataEntryValue>> next();
+
+// private:
+// Ref<DOMFormData> m_target;
+// size_t m_index { 0 };
+// };
+// Iterator createIterator() { return Iterator { *this }; }
+
+// private:
+// explicit DOMFormData(const PAL::TextEncoding& = PAL::UTF8Encoding());
+
+// void set(const String& name, Item&&);
+
+// PAL::TextEncoding m_encoding;
+// Vector<Item> m_items;
+// };
+
+// } // namespace WebCore
diff --git a/src/javascript/jsc/bindings/DOMURL.cpp b/src/javascript/jsc/bindings/DOMURL.cpp
new file mode 100644
index 000000000..8b437b5b7
--- /dev/null
+++ b/src/javascript/jsc/bindings/DOMURL.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Simon Hausmann <hausmann@kde.org>
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2014 Apple Inc. All rights reserved.
+ * (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Motorola Mobility Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "DOMURL.h"
+
+// #include "ActiveDOMObject.h"
+// #include "Blob.h"
+// #include "BlobURL.h"
+// #include "MemoryCache.h"
+// #include "PublicURLManager.h"
+// #include "ResourceRequest.h"
+#include "URLSearchParams.h"
+// #include <wtf/MainThread.h>
+
+namespace WebCore {
+
+inline DOMURL::DOMURL(URL&& completeURL, const URL& baseURL)
+ : m_baseURL(baseURL)
+ , m_url(WTFMove(completeURL))
+{
+}
+
+ExceptionOr<Ref<DOMURL>> DOMURL::create(const String& url, const URL& base)
+{
+ ASSERT(base.isValid() || base.isNull());
+ URL completeURL { base, url };
+ if (!completeURL.isValid())
+ return Exception { TypeError };
+ return adoptRef(*new DOMURL(WTFMove(completeURL), base));
+}
+
+ExceptionOr<Ref<DOMURL>> DOMURL::create(const String& url, const String& base)
+{
+ URL baseURL { URL {}, base };
+ if (!base.isNull() && !baseURL.isValid())
+ return Exception { TypeError };
+ return create(url, baseURL);
+}
+
+ExceptionOr<Ref<DOMURL>> DOMURL::create(const String& url, const DOMURL& base)
+{
+ return create(url, base.href());
+}
+
+DOMURL::~DOMURL() = default;
+
+ExceptionOr<void> DOMURL::setHref(const String& url)
+{
+ URL completeURL { URL {}, url };
+ if (!completeURL.isValid())
+ return Exception { TypeError };
+ m_url = WTFMove(completeURL);
+ if (m_searchParams)
+ m_searchParams->updateFromAssociatedURL();
+ return {};
+}
+
+void DOMURL::setQuery(const String& query)
+{
+ m_url.setQuery(query);
+}
+
+// String DOMURL::createObjectURL(Blob& blob)
+// {
+// return createPublicURL(scriptExecutionContext, blob);
+// }
+
+// String DOMURL::createPublicURL(URLRegistrable& registrable)
+// {
+// URL publicURL = BlobURL::createPublicURL(scriptExecutionContext.securityOrigin());
+// if (publicURL.isEmpty())
+// return String();
+
+// scriptExecutionContext.publicURLManager().registerURL(publicURL, registrable);
+
+// return publicURL.string();
+// }
+
+URLSearchParams& DOMURL::searchParams()
+{
+ if (!m_searchParams)
+ m_searchParams = URLSearchParams::create(search(), this);
+ return *m_searchParams;
+}
+
+// void DOMURL::revokeObjectURL(const String& urlString)
+// {
+// // URL url(URL(), urlString);
+// // ResourceRequest request(url);
+// // request.setDomainForCachePartition(scriptExecutionContext.domainForCachePartition());
+
+// // MemoryCache::removeRequestFromSessionCaches(scriptExecutionContext, request);
+
+// // scriptExecutionContext.publicURLManager().revoke(url);
+// }
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/DOMURL.h b/src/javascript/jsc/bindings/DOMURL.h
new file mode 100644
index 000000000..aa7c1eddf
--- /dev/null
+++ b/src/javascript/jsc/bindings/DOMURL.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Motorola Mobility Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "root.h"
+
+#include "ExceptionOr.h"
+#include "URLDecomposition.h"
+#include <wtf/URL.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class URLSearchParams;
+
+class DOMURL final : public RefCounted<DOMURL>, public CanMakeWeakPtr<DOMURL>, public URLDecomposition {
+public:
+ static ExceptionOr<Ref<DOMURL>> create(const String& url, const String& base);
+ static ExceptionOr<Ref<DOMURL>> create(const String& url, const DOMURL& base);
+ ~DOMURL();
+
+ const URL& href() const { return m_url; }
+ ExceptionOr<void> setHref(const String&);
+ void setQuery(const String&);
+
+ URLSearchParams& searchParams();
+
+ const String& toJSON() const { return m_url.string(); }
+
+ // static String createObjectURL(ScriptExecutionContext&, Blob&);
+ // static void revokeObjectURL(ScriptExecutionContext&, const String&);
+
+ // static String createPublicURL(ScriptExecutionContext&, URLRegistrable&);
+
+private:
+ static ExceptionOr<Ref<DOMURL>> create(const String& url, const URL& base);
+ DOMURL(URL&& completeURL, const URL& baseURL);
+
+ URL fullURL() const final { return m_url; }
+ void setFullURL(const URL& fullURL) final { setHref(fullURL.string()); }
+
+ URL m_baseURL;
+ URL m_url;
+ RefPtr<URLSearchParams> m_searchParams;
+};
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/Exception.h b/src/javascript/jsc/bindings/Exception.h
new file mode 100644
index 000000000..e14b1e01a
--- /dev/null
+++ b/src/javascript/jsc/bindings/Exception.h
@@ -0,0 +1,67 @@
+/*
+
+Copyright (C) 2016 Apple Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#pragma once
+
+#include "root.h"
+
+#include "ExceptionCode.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Exception {
+public:
+ explicit Exception(ExceptionCode, String = {});
+
+ ExceptionCode code() const { return m_code; }
+ const String& message() const { return m_message; }
+ String&& releaseMessage() { return WTFMove(m_message); }
+
+ Exception isolatedCopy() const
+ {
+ return Exception { m_code, m_message.isolatedCopy() };
+ }
+
+private:
+ ExceptionCode m_code;
+ String m_message;
+};
+
+Exception isolatedCopy(Exception&&);
+
+inline Exception::Exception(ExceptionCode code, String message)
+ : m_code { code }
+ , m_message { WTFMove(message) }
+{
+}
+
+inline Exception isolatedCopy(Exception&& value)
+{
+ return Exception { value.code(), value.releaseMessage().isolatedCopy() };
+}
+
+}
diff --git a/src/javascript/jsc/bindings/ExceptionCode.h b/src/javascript/jsc/bindings/ExceptionCode.h
new file mode 100644
index 000000000..d63691db1
--- /dev/null
+++ b/src/javascript/jsc/bindings/ExceptionCode.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "root.h"
+
+#include <wtf/EnumTraits.h>
+
+namespace WebCore {
+
+enum ExceptionCode {
+ // DOMException error names (https://webidl.spec.whatwg.org/#idl-DOMException-error-names).
+ // Those need to be kept in sync with the array in DOMException.cpp.
+ IndexSizeError, // Deprecated. Use RangeError instead.
+ HierarchyRequestError,
+ WrongDocumentError,
+ InvalidCharacterError,
+ NoModificationAllowedError,
+ NotFoundError,
+ NotSupportedError,
+ InUseAttributeError,
+ InvalidStateError,
+ SyntaxError,
+ InvalidModificationError,
+ NamespaceError,
+ InvalidAccessError, // Deprecated. use NotAllowedError instead.
+ TypeMismatchError, // Deprecated. Use TypeError instead.
+ SecurityError,
+ NetworkError,
+ AbortError,
+ URLMismatchError,
+ QuotaExceededError,
+ TimeoutError,
+ InvalidNodeTypeError,
+ DataCloneError,
+ EncodingError,
+ NotReadableError,
+ UnknownError,
+ ConstraintError,
+ DataError,
+ TransactionInactiveError,
+ ReadonlyError,
+ VersionError,
+ OperationError,
+ NotAllowedError,
+
+ // Simple exceptions (https://webidl.spec.whatwg.org/#idl-exceptions).
+ RangeError,
+ TypeError,
+ JSSyntaxError, // Different from DOM SYNTAX_ERR.
+
+ // Non-standard error.
+ StackOverflowError,
+ OutOfMemoryError,
+
+ // Used to indicate to the bindings that a JS exception was thrown below and it should be propagated.
+ ExistingExceptionError,
+};
+
+} // namespace WebCore
+
+namespace WTF {
+
+template<> struct EnumTraits<WebCore::ExceptionCode> {
+ using values = EnumValues<
+ WebCore::ExceptionCode,
+ WebCore::ExceptionCode::IndexSizeError,
+ WebCore::ExceptionCode::HierarchyRequestError,
+ WebCore::ExceptionCode::WrongDocumentError,
+ WebCore::ExceptionCode::InvalidCharacterError,
+ WebCore::ExceptionCode::NoModificationAllowedError,
+ WebCore::ExceptionCode::NotFoundError,
+ WebCore::ExceptionCode::NotSupportedError,
+ WebCore::ExceptionCode::InUseAttributeError,
+ WebCore::ExceptionCode::InvalidStateError,
+ WebCore::ExceptionCode::SyntaxError,
+ WebCore::ExceptionCode::InvalidModificationError,
+ WebCore::ExceptionCode::NamespaceError,
+ WebCore::ExceptionCode::InvalidAccessError,
+ WebCore::ExceptionCode::TypeMismatchError,
+ WebCore::ExceptionCode::SecurityError,
+ WebCore::ExceptionCode::NetworkError,
+ WebCore::ExceptionCode::AbortError,
+ WebCore::ExceptionCode::URLMismatchError,
+ WebCore::ExceptionCode::QuotaExceededError,
+ WebCore::ExceptionCode::TimeoutError,
+ WebCore::ExceptionCode::InvalidNodeTypeError,
+ WebCore::ExceptionCode::DataCloneError,
+ WebCore::ExceptionCode::EncodingError,
+ WebCore::ExceptionCode::NotReadableError,
+ WebCore::ExceptionCode::UnknownError,
+ WebCore::ExceptionCode::ConstraintError,
+ WebCore::ExceptionCode::DataError,
+ WebCore::ExceptionCode::TransactionInactiveError,
+ WebCore::ExceptionCode::ReadonlyError,
+ WebCore::ExceptionCode::VersionError,
+ WebCore::ExceptionCode::OperationError,
+ WebCore::ExceptionCode::NotAllowedError,
+ WebCore::ExceptionCode::RangeError,
+ WebCore::ExceptionCode::TypeError,
+ WebCore::ExceptionCode::JSSyntaxError,
+ WebCore::ExceptionCode::StackOverflowError,
+ WebCore::ExceptionCode::ExistingExceptionError>;
+};
+
+} // namespace WTF
diff --git a/src/javascript/jsc/bindings/ExceptionOr.h b/src/javascript/jsc/bindings/ExceptionOr.h
new file mode 100644
index 000000000..6ffd93fe1
--- /dev/null
+++ b/src/javascript/jsc/bindings/ExceptionOr.h
@@ -0,0 +1,239 @@
+/*
+
+Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#pragma once
+
+#include "root.h"
+
+#include "Exception.h"
+#include <wtf/CrossThreadCopier.h>
+#include <wtf/Expected.h>
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+template<typename T> class ExceptionOr {
+public:
+ using ReturnType = T;
+
+ ExceptionOr(Exception&&);
+ ExceptionOr(ReturnType&&);
+ template<typename OtherType> ExceptionOr(const OtherType&, typename std::enable_if<std::is_scalar<OtherType>::value && std::is_convertible<OtherType, ReturnType>::value>::type* = nullptr);
+
+ bool hasException() const;
+ const Exception& exception() const;
+ Exception releaseException();
+ const ReturnType& returnValue() const;
+ ReturnType releaseReturnValue();
+
+private:
+ Expected<ReturnType, Exception> m_value;
+#if ASSERT_ENABLED
+ bool m_wasReleased { false };
+#endif
+};
+
+template<typename T> class ExceptionOr<T&> {
+public:
+ using ReturnType = T&;
+ using ReturnReferenceType = T;
+
+ ExceptionOr(Exception&&);
+ ExceptionOr(ReturnReferenceType&);
+
+ bool hasException() const;
+ const Exception& exception() const;
+ Exception releaseException();
+ const ReturnReferenceType& returnValue() const;
+ ReturnReferenceType& releaseReturnValue();
+
+private:
+ ExceptionOr<ReturnReferenceType*> m_value;
+};
+
+template<> class ExceptionOr<void> {
+public:
+ using ReturnType = void;
+
+ ExceptionOr(Exception&&);
+ ExceptionOr() = default;
+
+ bool hasException() const;
+ const Exception& exception() const;
+ Exception releaseException();
+
+private:
+ Expected<void, Exception> m_value;
+#if ASSERT_ENABLED
+ bool m_wasReleased { false };
+#endif
+};
+
+ExceptionOr<void> isolatedCopy(ExceptionOr<void>&&);
+
+template<typename ReturnType> inline ExceptionOr<ReturnType>::ExceptionOr(Exception&& exception)
+ : m_value(makeUnexpected(WTFMove(exception)))
+{
+}
+
+template<typename ReturnType> inline ExceptionOr<ReturnType>::ExceptionOr(ReturnType&& returnValue)
+ : m_value(WTFMove(returnValue))
+{
+}
+
+template<typename ReturnType> template<typename OtherType> inline ExceptionOr<ReturnType>::ExceptionOr(const OtherType& returnValue, typename std::enable_if<std::is_scalar<OtherType>::value && std::is_convertible<OtherType, ReturnType>::value>::type*)
+ : m_value(static_cast<ReturnType>(returnValue))
+{
+}
+
+template<typename ReturnType> inline bool ExceptionOr<ReturnType>::hasException() const
+{
+ return !m_value.has_value();
+}
+
+template<typename ReturnType> inline const Exception& ExceptionOr<ReturnType>::exception() const
+{
+ ASSERT(!m_wasReleased);
+ return m_value.error();
+}
+
+template<typename ReturnType> inline Exception ExceptionOr<ReturnType>::releaseException()
+{
+ ASSERT(!std::exchange(m_wasReleased, true));
+ return WTFMove(m_value.error());
+}
+
+template<typename ReturnType> inline const ReturnType& ExceptionOr<ReturnType>::returnValue() const
+{
+ ASSERT(!m_wasReleased);
+ return m_value.value();
+}
+
+template<typename ReturnType> inline ReturnType ExceptionOr<ReturnType>::releaseReturnValue()
+{
+ ASSERT(!std::exchange(m_wasReleased, true));
+ return WTFMove(m_value.value());
+}
+
+template<typename ReturnReferenceType> inline ExceptionOr<ReturnReferenceType&>::ExceptionOr(Exception&& exception)
+ : m_value(WTFMove(exception))
+{
+}
+
+template<typename ReturnReferenceType> inline ExceptionOr<ReturnReferenceType&>::ExceptionOr(ReturnReferenceType& returnValue)
+ : m_value(&returnValue)
+{
+}
+
+template<typename ReturnReferenceType> inline bool ExceptionOr<ReturnReferenceType&>::hasException() const
+{
+ return m_value.hasException();
+}
+
+template<typename ReturnReferenceType> inline const Exception& ExceptionOr<ReturnReferenceType&>::exception() const
+{
+ return m_value.exception();
+}
+
+template<typename ReturnReferenceType> inline Exception ExceptionOr<ReturnReferenceType&>::releaseException()
+{
+ return m_value.releaseException();
+}
+
+template<typename ReturnReferenceType> inline const ReturnReferenceType& ExceptionOr<ReturnReferenceType&>::returnValue() const
+{
+ return *m_value.returnValue();
+}
+
+template<typename ReturnReferenceType> inline ReturnReferenceType& ExceptionOr<ReturnReferenceType&>::releaseReturnValue()
+{
+ return *m_value.releaseReturnValue();
+}
+
+inline ExceptionOr<void>::ExceptionOr(Exception&& exception)
+ : m_value(makeUnexpected(WTFMove(exception)))
+{
+}
+
+inline bool ExceptionOr<void>::hasException() const
+{
+ return !m_value.has_value();
+}
+
+inline const Exception& ExceptionOr<void>::exception() const
+{
+ ASSERT(!m_wasReleased);
+ return m_value.error();
+}
+
+inline Exception ExceptionOr<void>::releaseException()
+{
+ ASSERT(!std::exchange(m_wasReleased, true));
+ return WTFMove(m_value.error());
+}
+
+inline ExceptionOr<void> isolatedCopy(ExceptionOr<void>&& value)
+{
+ if (value.hasException())
+ return isolatedCopy(value.releaseException());
+ return {};
+}
+
+template<typename T> inline constexpr bool IsExceptionOr = WTF::IsTemplate<std::decay_t<T>, ExceptionOr>::value;
+
+template<typename T, bool isExceptionOr = IsExceptionOr<T>> struct TypeOrExceptionOrUnderlyingTypeImpl;
+template<typename T> struct TypeOrExceptionOrUnderlyingTypeImpl<T, true> {
+ using Type = typename T::ReturnType;
+};
+template<typename T> struct TypeOrExceptionOrUnderlyingTypeImpl<T, false> {
+ using Type = T;
+};
+template<typename T> using TypeOrExceptionOrUnderlyingType = typename TypeOrExceptionOrUnderlyingTypeImpl<T>::Type;
+
+}
+
+namespace WTF {
+template<typename T> struct CrossThreadCopierBase<false, false, WebCore::ExceptionOr<T>> {
+ typedef WebCore::ExceptionOr<T> Type;
+ static Type copy(const Type& source)
+ {
+ if (source.hasException())
+ return crossThreadCopy(source.exception());
+ return crossThreadCopy(source.returnValue());
+ }
+};
+
+template<> struct CrossThreadCopierBase<false, false, WebCore::ExceptionOr<void>> {
+ typedef WebCore::ExceptionOr<void> Type;
+ static Type copy(const Type& source)
+ {
+ if (source.hasException())
+ return crossThreadCopy(source.exception());
+ return {};
+ }
+};
+
+}
diff --git a/src/javascript/jsc/bindings/IDLTypes.h b/src/javascript/jsc/bindings/IDLTypes.h
new file mode 100644
index 000000000..b597fb280
--- /dev/null
+++ b/src/javascript/jsc/bindings/IDLTypes.h
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "StringAdaptors.h"
+#include <JavaScriptCore/HandleTypes.h>
+#include <JavaScriptCore/Strong.h>
+#include <variant>
+#include <wtf/Brigand.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/URL.h>
+#include <wtf/WallTime.h>
+
+#if ENABLE(WEBGL)
+#include "WebGLAny.h"
+#endif
+
+namespace JSC {
+class ArrayBuffer;
+class ArrayBufferView;
+class DataView;
+class JSValue;
+class JSObject;
+}
+
+namespace WebCore {
+
+class IDBKey;
+class IDBKeyData;
+class IDBValue;
+class JSWindowProxy;
+class DOMPromise;
+class ScheduledAction;
+
+#if ENABLE(WEBGL)
+class WebGLExtension;
+#endif
+
+template<typename T>
+struct IDLType {
+ using ImplementationType = T;
+ using StorageType = T;
+ using SequenceStorageType = T;
+
+ using ParameterType = T;
+ using NullableParameterType = std::optional<ImplementationType>;
+
+ using InnerParameterType = T;
+ using NullableInnerParameterType = std::optional<ImplementationType>;
+
+ using NullableType = std::optional<ImplementationType>;
+ static NullableType nullValue() { return std::nullopt; }
+ static bool isNullValue(const NullableType& value) { return !value; }
+ static ImplementationType extractValueFromNullable(const NullableType& value) { return value.value(); }
+};
+
+// IDLUnsupportedType is a special type that serves as a base class for currently unsupported types.
+struct IDLUnsupportedType : IDLType<void> {
+};
+
+// IDLNull is a special type for use as a subtype in an IDLUnion that is nullable.
+struct IDLNull : IDLType<std::nullptr_t> {
+};
+
+struct IDLAny : IDLType<JSC::Strong<JSC::Unknown>> {
+ using SequenceStorageType = JSC::JSValue;
+ using ParameterType = JSC::JSValue;
+ using NullableParameterType = JSC::JSValue;
+
+ using NullableType = JSC::Strong<JSC::Unknown>;
+ static inline std::nullptr_t nullValue() { return nullptr; }
+ template<typename U> static inline bool isNullValue(U&& value) { return !value; }
+ template<typename U> static inline U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); }
+};
+
+struct IDLUndefined : IDLType<void> {
+};
+
+struct IDLBoolean : IDLType<bool> {
+};
+
+template<typename NumericType> struct IDLNumber : IDLType<NumericType> {
+};
+
+template<typename IntegerType> struct IDLInteger : IDLNumber<IntegerType> {
+};
+struct IDLByte : IDLInteger<int8_t> {
+};
+struct IDLOctet : IDLInteger<uint8_t> {
+};
+struct IDLShort : IDLInteger<int16_t> {
+};
+struct IDLUnsignedShort : IDLInteger<uint16_t> {
+};
+struct IDLLong : IDLInteger<int32_t> {
+};
+struct IDLUnsignedLong : IDLInteger<uint32_t> {
+};
+struct IDLLongLong : IDLInteger<int64_t> {
+};
+struct IDLUnsignedLongLong : IDLInteger<uint64_t> {
+};
+
+template<typename T> struct IDLClampAdaptor : IDLInteger<typename T::ImplementationType> {
+ using InnerType = T;
+};
+
+template<typename T> struct IDLEnforceRangeAdaptor : IDLInteger<typename T::ImplementationType> {
+ using InnerType = T;
+};
+
+template<typename FloatingPointType> struct IDLFloatingPoint : IDLNumber<FloatingPointType> {
+};
+struct IDLFloat : IDLFloatingPoint<float> {
+};
+struct IDLUnrestrictedFloat : IDLFloatingPoint<float> {
+};
+struct IDLDouble : IDLFloatingPoint<double> {
+};
+struct IDLUnrestrictedDouble : IDLFloatingPoint<double> {
+};
+
+template<typename StringType> struct IDLString : IDLType<StringType> {
+ using ParameterType = const StringType&;
+ using NullableParameterType = const StringType&;
+
+ using NullableType = StringType;
+ static StringType nullValue() { return StringType(); }
+ static bool isNullValue(const StringType& value) { return value.isNull(); }
+ static bool isNullValue(const UncachedString& value) { return value.string.isNull(); }
+ static bool isNullValue(const OwnedString& value) { return value.string.isNull(); }
+ static bool isNullValue(const URL& value) { return value.isNull(); }
+ template<typename U> static U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); }
+};
+struct IDLDOMString : IDLString<String> {
+};
+struct IDLByteString : IDLString<String> {
+};
+struct IDLUSVString : IDLString<String> {
+};
+
+template<typename T> struct IDLLegacyNullToEmptyStringAdaptor : IDLString<String> {
+ using InnerType = T;
+};
+
+template<typename T> struct IDLAtomStringAdaptor : IDLString<AtomString> {
+ using InnerType = T;
+};
+
+template<typename T> struct IDLRequiresExistingAtomStringAdaptor : IDLString<AtomString> {
+ using InnerType = T;
+};
+
+template<typename T> struct IDLAllowSharedAdaptor : T {
+ using InnerType = T;
+};
+
+struct IDLObject : IDLType<JSC::Strong<JSC::JSObject>> {
+ using NullableType = JSC::Strong<JSC::JSObject>;
+
+ static inline NullableType nullValue() { return {}; }
+ template<typename U> static inline bool isNullValue(U&& value) { return !value; }
+ template<typename U> static inline U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); }
+};
+
+template<typename T> struct IDLWrapper : IDLType<RefPtr<T>> {
+ using RawType = T;
+
+ using StorageType = Ref<T>;
+
+ using ParameterType = T&;
+ using NullableParameterType = T*;
+
+ using InnerParameterType = Ref<T>;
+ using NullableInnerParameterType = RefPtr<T>;
+
+ using NullableType = RefPtr<T>;
+ static inline std::nullptr_t nullValue() { return nullptr; }
+ template<typename U> static inline bool isNullValue(U&& value) { return !value; }
+ template<typename U> static inline U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); }
+};
+
+template<typename T> struct IDLInterface : IDLWrapper<T> {
+};
+template<typename T> struct IDLCallbackInterface : IDLWrapper<T> {
+};
+template<typename T> struct IDLCallbackFunction : IDLWrapper<T> {
+};
+
+template<typename T> struct IDLDictionary : IDLType<T> {
+ using ParameterType = const T&;
+ using NullableParameterType = const T&;
+};
+
+template<typename T> struct IDLEnumeration : IDLType<T> {
+};
+
+template<typename T> struct IDLNullable : IDLType<typename T::NullableType> {
+ using InnerType = T;
+
+ using ParameterType = typename T::NullableParameterType;
+ using NullableParameterType = typename T::NullableParameterType;
+
+ using InnerParameterType = typename T::NullableInnerParameterType;
+ using NullableInnerParameterType = typename T::NullableInnerParameterType;
+
+ using NullableType = typename T::NullableType;
+ static inline auto nullValue() -> decltype(T::nullValue()) { return T::nullValue(); }
+ template<typename U> static inline bool isNullValue(U&& value) { return T::isNullValue(std::forward<U>(value)); }
+ template<typename U> static inline auto extractValueFromNullable(U&& value) -> decltype(T::extractValueFromNullable(std::forward<U>(value))) { return T::extractValueFromNullable(std::forward<U>(value)); }
+};
+
+template<typename T> struct IDLSequence : IDLType<Vector<typename T::ImplementationType>> {
+ using InnerType = T;
+
+ using ParameterType = const Vector<typename T::InnerParameterType>&;
+ using NullableParameterType = const std::optional<Vector<typename T::InnerParameterType>>&;
+};
+
+template<typename T> struct IDLFrozenArray : IDLType<Vector<typename T::ImplementationType>> {
+ using InnerType = T;
+
+ using ParameterType = const Vector<typename T::ImplementationType>&;
+ using NullableParameterType = const std::optional<Vector<typename T::ImplementationType>>&;
+};
+
+template<typename K, typename V> struct IDLRecord : IDLType<Vector<KeyValuePair<typename K::ImplementationType, typename V::ImplementationType>>> {
+ using KeyType = K;
+ using ValueType = V;
+
+ using ParameterType = const Vector<KeyValuePair<typename K::ImplementationType, typename V::ImplementationType>>&;
+ using NullableParameterType = const std::optional<Vector<KeyValuePair<typename K::ImplementationType, typename V::ImplementationType>>>&;
+};
+
+template<typename T> struct IDLPromise : IDLWrapper<DOMPromise> {
+ using InnerType = T;
+};
+
+struct IDLError : IDLUnsupportedType {
+};
+struct IDLDOMException : IDLUnsupportedType {
+};
+
+template<typename... Ts>
+struct IDLUnion : IDLType<std::variant<typename Ts::ImplementationType...>> {
+ using TypeList = brigand::list<Ts...>;
+
+ using ParameterType = const std::variant<typename Ts::ImplementationType...>&;
+ using NullableParameterType = const std::optional<std::variant<typename Ts::ImplementationType...>>&;
+};
+
+template<typename T> struct IDLBufferSource : IDLWrapper<T> {
+};
+
+struct IDLArrayBuffer : IDLBufferSource<JSC::ArrayBuffer> {
+};
+// NOTE: WebIDL defines ArrayBufferView as an IDL union of all the TypedArray types.
+// and DataView. For convience in our implementation, we give it a distinct
+// type that maps to the shared based class of all those classes.
+struct IDLArrayBufferView : IDLBufferSource<JSC::ArrayBufferView> {
+};
+struct IDLDataView : IDLBufferSource<JSC::DataView> {
+};
+
+template<typename T> struct IDLTypedArray : IDLBufferSource<T> {
+};
+// NOTE: The specific typed array types are IDLTypedArray specialized on the typed array
+// implementation type, e.g. IDLFloat64Array is IDLTypedArray<JSC::Float64Array>
+
+// Non-WebIDL extensions
+
+struct IDLDate : IDLType<WallTime> {
+ using NullableType = WallTime;
+ static WallTime nullValue() { return WallTime::nan(); }
+ static bool isNullValue(WallTime value) { return std::isnan(value); }
+ static WallTime extractValueFromNullable(WallTime value) { return value; }
+};
+
+struct IDLJSON : IDLType<String> {
+ using ParameterType = const String&;
+ using NullableParameterType = const String&;
+
+ using NullableType = String;
+ static String nullValue() { return String(); }
+ static bool isNullValue(const String& value) { return value.isNull(); }
+ template<typename U> static U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); }
+};
+
+struct IDLScheduledAction : IDLType<std::unique_ptr<ScheduledAction>> {
+};
+template<typename T> struct IDLSerializedScriptValue : IDLWrapper<T> {
+};
+template<typename T> struct IDLEventListener : IDLWrapper<T> {
+};
+
+struct IDLIDBKey : IDLWrapper<IDBKey> {
+};
+struct IDLIDBKeyData : IDLWrapper<IDBKeyData> {
+};
+struct IDLIDBValue : IDLWrapper<IDBValue> {
+};
+
+#if ENABLE(WEBGL)
+struct IDLWebGLAny : IDLType<WebGLAny> {
+};
+struct IDLWebGLExtension : IDLWrapper<WebGLExtension> {
+};
+#endif
+
+// Helper predicates
+
+template<typename T>
+struct IsIDLInterface : public std::integral_constant<bool, WTF::IsTemplate<T, IDLInterface>::value> {
+};
+
+template<typename T>
+struct IsIDLDictionary : public std::integral_constant<bool, WTF::IsTemplate<T, IDLDictionary>::value> {
+};
+
+template<typename T>
+struct IsIDLEnumeration : public std::integral_constant<bool, WTF::IsTemplate<T, IDLEnumeration>::value> {
+};
+
+template<typename T>
+struct IsIDLSequence : public std::integral_constant<bool, WTF::IsTemplate<T, IDLSequence>::value> {
+};
+
+template<typename T>
+struct IsIDLFrozenArray : public std::integral_constant<bool, WTF::IsTemplate<T, IDLFrozenArray>::value> {
+};
+
+template<typename T>
+struct IsIDLRecord : public std::integral_constant<bool, WTF::IsTemplate<T, IDLRecord>::value> {
+};
+
+template<typename T>
+struct IsIDLString : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLString, T>::value> {
+};
+
+template<typename T>
+struct IsIDLStringOrEnumeration : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLString, T>::value || WTF::IsTemplate<T, IDLEnumeration>::value> {
+};
+
+template<typename T>
+struct IsIDLNumber : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLNumber, T>::value> {
+};
+
+template<typename T>
+struct IsIDLInteger : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLInteger, T>::value> {
+};
+
+template<typename T>
+struct IsIDLFloatingPoint : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLFloatingPoint, T>::value> {
+};
+
+template<typename T>
+struct IsIDLTypedArray : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLTypedArray, T>::value> {
+};
+
+template<typename T>
+struct IsIDLTypedArrayAllowShared : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLTypedArray, T>::value && WTF::IsBaseOfTemplate<IDLAllowSharedAdaptor, T>::value> {
+};
+
+template<typename T>
+struct IsIDLArrayBuffer : public std::integral_constant<bool, std::is_base_of<IDLArrayBuffer, T>::value> {
+};
+
+template<typename T>
+struct IsIDLArrayBufferView : public std::integral_constant<bool, std::is_base_of<IDLArrayBufferView, T>::value> {
+};
+
+template<typename T>
+struct IsIDLArrayBufferAllowShared : public std::integral_constant<bool, std::is_base_of<IDLAllowSharedAdaptor<IDLArrayBuffer>, T>::value> {
+};
+
+template<typename T>
+struct IsIDLArrayBufferViewAllowShared : public std::integral_constant<bool, std::is_base_of<IDLAllowSharedAdaptor<IDLArrayBufferView>, T>::value> {
+};
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/JSDOMExceptionHandling.cpp b/src/javascript/jsc/bindings/JSDOMExceptionHandling.cpp
new file mode 100644
index 000000000..84f387bef
--- /dev/null
+++ b/src/javascript/jsc/bindings/JSDOMExceptionHandling.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004-2021 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "root.h"
+
+#include "DOMException.h"
+#include "JSDOMException.h"
+#include "JSDOMExceptionHandling.h"
+
+#include <JavaScriptCore/ErrorHandlingScope.h>
+#include <JavaScriptCore/Exception.h>
+#include <JavaScriptCore/ExceptionHelpers.h>
+#include <JavaScriptCore/ScriptCallStack.h>
+#include <JavaScriptCore/ScriptCallStackFactory.h>
+
+namespace WebCore {
+using namespace JSC;
+
+String retrieveErrorMessageWithoutName(JSGlobalObject& lexicalGlobalObject, VM& vm, JSValue exception, CatchScope& catchScope)
+{
+ // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions
+ // If this is a custom exception object, call toString on it to try and get a nice string representation for the exception.
+ String errorMessage;
+ if (auto* error = jsDynamicCast<ErrorInstance*>(vm, exception))
+ errorMessage = error->sanitizedMessageString(&lexicalGlobalObject);
+ else if (auto* error = jsDynamicCast<JSDOMException*>(vm, exception))
+ errorMessage = error->wrapped().message();
+ else
+ errorMessage = exception.toWTFString(&lexicalGlobalObject);
+
+ // We need to clear any new exception that may be thrown in the toString() call above.
+ // reportException() is not supposed to be making new exceptions.
+ catchScope.clearException();
+ vm.clearLastException();
+ return errorMessage;
+}
+
+String retrieveErrorMessage(JSGlobalObject& lexicalGlobalObject, VM& vm, JSValue exception, CatchScope& catchScope)
+{
+ // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions
+ // If this is a custom exception object, call toString on it to try and get a nice string representation for the exception.
+ String errorMessage;
+ if (auto* error = jsDynamicCast<ErrorInstance*>(vm, exception))
+ errorMessage = error->sanitizedToString(&lexicalGlobalObject);
+ else
+ errorMessage = exception.toWTFString(&lexicalGlobalObject);
+
+ // We need to clear any new exception that may be thrown in the toString() call above.
+ // reportException() is not supposed to be making new exceptions.
+ catchScope.clearException();
+ vm.clearLastException();
+ return errorMessage;
+}
+
+void reportCurrentException(JSGlobalObject* lexicalGlobalObject)
+{
+ VM& vm = lexicalGlobalObject->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto* exception = scope.exception();
+ scope.clearException();
+ reportException(lexicalGlobalObject, exception);
+}
+
+JSValue createDOMException(JSGlobalObject* lexicalGlobalObject, ExceptionCode ec, const String& message)
+{
+ VM& vm = lexicalGlobalObject->vm();
+ if (UNLIKELY(vm.hasPendingTerminationException()))
+ return jsUndefined();
+
+ switch (ec) {
+ case ExistingExceptionError:
+ return jsUndefined();
+
+ // FIXME: Handle other WebIDL exception types.
+ case TypeError:
+ if (message.isEmpty())
+ return createTypeError(lexicalGlobalObject);
+ return createTypeError(lexicalGlobalObject, message);
+
+ case RangeError:
+ if (message.isEmpty())
+ return createRangeError(lexicalGlobalObject, "Bad value"_s);
+ return createRangeError(lexicalGlobalObject, message);
+
+ case JSSyntaxError:
+ if (message.isEmpty())
+ return createSyntaxError(lexicalGlobalObject);
+ return createSyntaxError(lexicalGlobalObject, message);
+
+ case StackOverflowError:
+ return createStackOverflowError(lexicalGlobalObject);
+
+ case OutOfMemoryError:
+ return createOutOfMemoryError(lexicalGlobalObject);
+
+ 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:
+ // frames[0].document.createElement(null, null); // throws an exception which should have the subframe's prototypes.
+ // https://bugs.webkit.org/show_bug.cgi?id=222229
+ JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(lexicalGlobalObject);
+ JSValue errorObject = toJS(lexicalGlobalObject, globalObject, DOMException::create(ec, message));
+
+ ASSERT(errorObject);
+ addErrorInfo(lexicalGlobalObject, asObject(errorObject), true);
+ return errorObject;
+ }
+ }
+ return {};
+}
+
+JSValue createDOMException(JSGlobalObject& lexicalGlobalObject, Exception&& exception)
+{
+ return createDOMException(&lexicalGlobalObject, exception.code(), exception.releaseMessage());
+}
+
+void propagateExceptionSlowPath(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& throwScope, Exception&& exception)
+{
+ throwScope.assertNoExceptionExceptTermination();
+ throwException(&lexicalGlobalObject, throwScope, createDOMException(lexicalGlobalObject, WTFMove(exception)));
+}
+
+static EncodedJSValue throwTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const String& errorMessage)
+{
+ return throwVMTypeError(&lexicalGlobalObject, scope, errorMessage);
+}
+
+template<typename... StringTypes> static String makeArgumentTypeErrorMessage(unsigned argumentIndex, const char* argumentName, const char* interfaceName, const char* functionName, StringTypes... strings)
+{
+ return makeString(
+ "Argument ", argumentIndex + 1, " ('", argumentName, "') to ",
+ functionName ? std::make_tuple(interfaceName, ".", functionName) : std::make_tuple("the ", interfaceName, " constructor"),
+ " must be ", strings...);
+}
+
+void throwNotSupportedError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral message)
+{
+ scope.assertNoExceptionExceptTermination();
+ throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, NotSupportedError, message));
+}
+
+void throwInvalidStateError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral message)
+{
+ scope.assertNoExceptionExceptTermination();
+ throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, InvalidStateError, message));
+}
+
+void throwSecurityError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const String& message)
+{
+ scope.assertNoExceptionExceptTermination();
+ throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, SecurityError, message));
+}
+
+JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues)
+{
+ return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, functionInterfaceName, functionName, "one of: ", expectedValues));
+}
+
+JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* interfaceName, const char* functionName)
+{
+ return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, interfaceName, functionName, "a function"));
+}
+
+JSC::EncodedJSValue throwArgumentMustBeObjectError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* interfaceName, const char* functionName)
+{
+ return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, interfaceName, functionName, "an object"));
+}
+
+JSC::EncodedJSValue throwArgumentTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType)
+{
+ return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, functionInterfaceName, functionName, "an instance of ", expectedType));
+}
+
+void throwAttributeTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const char* interfaceName, const char* attributeName, const char* expectedType)
+{
+ throwTypeError(lexicalGlobalObject, scope, makeString("The ", interfaceName, '.', attributeName, " attribute must be an instance of ", expectedType));
+}
+
+JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const char* memberName, const char* dictionaryName, const char* expectedType)
+{
+ return throwVMTypeError(&lexicalGlobalObject, scope, makeString("Member ", dictionaryName, '.', memberName, " is required and must be an instance of ", expectedType));
+}
+
+JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const char* interfaceName)
+{
+ return throwVMError(&lexicalGlobalObject, scope, createReferenceError(&lexicalGlobalObject, makeString(interfaceName, " constructor associated execution context is unavailable")));
+}
+
+void throwSequenceTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope)
+{
+ throwTypeError(lexicalGlobalObject, scope, "Value is not a sequence"_s);
+}
+
+void throwNonFiniteTypeError(JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope)
+{
+ throwTypeError(&lexicalGlobalObject, scope, "The provided value is non-finite"_s);
+}
+
+JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::JSGlobalObject& lexicalGlobalObject, const JSC::ClassInfo* classInfo, JSC::PropertyName attributeName)
+{
+ return createRejectedPromiseWithTypeError(lexicalGlobalObject, JSC::makeDOMAttributeGetterTypeErrorMessage(classInfo->className, String(attributeName.uid())), RejectedPromiseWithTypeErrorCause::NativeGetter);
+}
+
+String makeThisTypeErrorMessage(const char* interfaceName, const char* functionName)
+{
+ return makeString("Can only call ", interfaceName, '.', functionName, " on instances of ", interfaceName);
+}
+
+String makeUnsupportedIndexedSetterErrorMessage(const char* interfaceName)
+{
+ return makeString("Failed to set an indexed property on ", interfaceName, ": Indexed property setter is not supported.");
+}
+
+EncodedJSValue throwThisTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const char* interfaceName, const char* functionName)
+{
+ return throwTypeError(lexicalGlobalObject, scope, makeThisTypeErrorMessage(interfaceName, functionName));
+}
+
+JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise& promise, const char* interfaceName, const char* methodName)
+{
+ promise.reject(TypeError, makeThisTypeErrorMessage(interfaceName, methodName));
+ return JSValue::encode(jsUndefined());
+}
+
+JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::JSGlobalObject& lexicalGlobalObject, const char* interfaceName, const char* methodName)
+{
+ return createRejectedPromiseWithTypeError(lexicalGlobalObject, makeThisTypeErrorMessage(interfaceName, methodName), RejectedPromiseWithTypeErrorCause::InvalidThis);
+}
+
+void throwDOMSyntaxError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral message)
+{
+ scope.assertNoExceptionExceptTermination();
+ throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, SyntaxError, message));
+}
+
+void throwDataCloneError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope)
+{
+ scope.assertNoExceptionExceptTermination();
+ throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, DataCloneError));
+}
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/JSDOMExceptionHandling.h b/src/javascript/jsc/bindings/JSDOMExceptionHandling.h
new file mode 100644
index 000000000..275dc4032
--- /dev/null
+++ b/src/javascript/jsc/bindings/JSDOMExceptionHandling.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2009 Google, Inc. All rights reserved.
+ * Copyright (C) 2012 Ericsson AB. All rights reserved.
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "ExceptionDetails.h"
+#include "ExceptionOr.h"
+#include <JavaScriptCore/ThrowScope.h>
+
+namespace JSC {
+class CatchScope;
+}
+
+namespace WebCore {
+
+class CachedScript;
+class DeferredPromise;
+class JSDOMGlobalObject;
+
+void throwAttributeTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName, const char* expectedType);
+
+void throwDataCloneError(JSC::JSGlobalObject&, JSC::ThrowScope&);
+void throwDOMSyntaxError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral); // Not the same as a JavaScript syntax error.
+void throwInvalidStateError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral);
+WEBCORE_EXPORT void throwNonFiniteTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&);
+void throwNotSupportedError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral);
+void throwSecurityError(JSC::JSGlobalObject&, JSC::ThrowScope&, const String& message);
+WEBCORE_EXPORT void throwSequenceTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&);
+
+WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues);
+WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName);
+WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeObjectError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName);
+WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType);
+WEBCORE_EXPORT JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, const char* memberName, const char* dictionaryName, const char* expectedType);
+JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::JSGlobalObject&, JSC::ThrowScope&, const char* interfaceName);
+
+String makeThisTypeErrorMessage(const char* interfaceName, const char* attributeName);
+String makeUnsupportedIndexedSetterErrorMessage(const char* interfaceName);
+
+WEBCORE_EXPORT JSC::EncodedJSValue throwThisTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, const char* interfaceName, const char* functionName);
+
+WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::JSGlobalObject&, const JSC::ClassInfo*, JSC::PropertyName attributeName);
+WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise&, const char* interfaceName, const char* operationName);
+WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::JSGlobalObject&, const char* interfaceName, const char* operationName);
+
+String retrieveErrorMessageWithoutName(JSC::JSGlobalObject&, JSC::VM&, JSC::JSValue exception, JSC::CatchScope&);
+String retrieveErrorMessage(JSC::JSGlobalObject&, JSC::VM&, JSC::JSValue exception, JSC::CatchScope&);
+// WEBCORE_EXPORT void reportException(JSC::JSGlobalObject*, JSC::JSValue exception, CachedScript* = nullptr, bool = false);
+// WEBCORE_EXPORT void reportException(JSC::JSGlobalObject*, JSC::Exception*, CachedScript* = nullptr, bool = false, ExceptionDetails* = nullptr);
+void reportCurrentException(JSC::JSGlobalObject*);
+
+JSC::JSValue createDOMException(JSC::JSGlobalObject&, Exception&&);
+JSC::JSValue createDOMException(JSC::JSGlobalObject*, ExceptionCode, const String& = emptyString());
+
+// Convert a DOM implementation exception into a JavaScript exception in the execution lexicalGlobalObject.
+WEBCORE_EXPORT void propagateExceptionSlowPath(JSC::JSGlobalObject&, JSC::ThrowScope&, Exception&&);
+
+ALWAYS_INLINE void propagateException(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& throwScope, Exception&& exception)
+{
+ if (throwScope.exception())
+ return;
+ propagateExceptionSlowPath(lexicalGlobalObject, throwScope, WTFMove(exception));
+}
+
+inline void propagateException(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& throwScope, ExceptionOr<void>&& value)
+{
+ if (UNLIKELY(value.hasException()))
+ propagateException(lexicalGlobalObject, throwScope, value.releaseException());
+}
+
+template<typename Functor> void invokeFunctorPropagatingExceptionIfNecessary(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& throwScope, Functor&& functor)
+{
+ using ReturnType = std::invoke_result_t<Functor>;
+
+ if constexpr (IsExceptionOr<ReturnType>) {
+ auto result = functor();
+ if (UNLIKELY(result.hasException()))
+ propagateException(lexicalGlobalObject, throwScope, result.releaseException());
+ } else
+ functor();
+}
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/JSDOMURL.cpp b/src/javascript/jsc/bindings/JSDOMURL.cpp
new file mode 100644
index 000000000..05a77957e
--- /dev/null
+++ b/src/javascript/jsc/bindings/JSDOMURL.cpp
@@ -0,0 +1,321 @@
+#include "root.h"
+
+#include "JSDOMURL.h"
+#include <JavaScriptCore/JSMicrotask.h>
+#include <JavaScriptCore/ObjectConstructor.h>
+
+namespace WebCore {
+using namespace JSC;
+using namespace Bun;
+using JSGlobalObject = JSC::JSGlobalObject;
+using JSValue = JSC::JSValue;
+using JSString = JSC::JSString;
+using JSModuleLoader = JSC::JSModuleLoader;
+using JSModuleRecord = JSC::JSModuleRecord;
+using Identifier = JSC::Identifier;
+using SourceOrigin = JSC::SourceOrigin;
+using JSObject = JSC::JSObject;
+using JSNonFinalObject = JSC::JSNonFinalObject;
+namespace JSCastingHelpers = JSC::JSCastingHelpers;
+
+JSC_DEFINE_CUSTOM_GETTER(DOMURL__href_get, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ RETURN_IF_EXCEPTION(throwScope, {});
+
+ return JSValue::encode(JSC::jsStringWithCache(vm, impl.href().string()));
+}
+
+JSC_DEFINE_CUSTOM_GETTER(DOMURL__protocol_get, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ RETURN_IF_EXCEPTION(throwScope, {});
+
+ return JSValue::encode(JSC::jsStringWithCache(vm, impl.protocol()));
+}
+JSC_DEFINE_CUSTOM_GETTER(DOMURL__username_get, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ RETURN_IF_EXCEPTION(throwScope, {});
+ return JSValue::encode(JSC::jsStringWithCache(vm, impl.username()));
+}
+JSC_DEFINE_CUSTOM_GETTER(DOMURL__password_get, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ RETURN_IF_EXCEPTION(throwScope, {});
+ return JSValue::encode(JSC::jsStringWithCache(vm, impl.password()));
+}
+JSC_DEFINE_CUSTOM_GETTER(DOMURL__host_get, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ RETURN_IF_EXCEPTION(throwScope, {});
+ return JSValue::encode(JSC::jsStringWithCache(vm, impl.host()));
+}
+JSC_DEFINE_CUSTOM_GETTER(DOMURL__hostname_get, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ RETURN_IF_EXCEPTION(throwScope, {});
+ return JSValue::encode(JSC::jsStringWithCache(vm, impl.hostname()));
+}
+JSC_DEFINE_CUSTOM_GETTER(DOMURL__port_get, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ RETURN_IF_EXCEPTION(throwScope, {});
+ return JSValue::encode(JSC::jsStringWithCache(vm, impl.port()));
+}
+JSC_DEFINE_CUSTOM_GETTER(DOMURL__pathname_get, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ RETURN_IF_EXCEPTION(throwScope, {});
+ return JSValue::encode(JSC::jsStringWithCache(vm, impl.pathname()));
+}
+JSC_DEFINE_CUSTOM_GETTER(DOMURL__hash_get, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ RETURN_IF_EXCEPTION(throwScope, {});
+ return JSValue::encode(JSC::jsStringWithCache(vm, impl.hash()));
+}
+
+JSC_DEFINE_CUSTOM_GETTER(DOMURL__search_get, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ RETURN_IF_EXCEPTION(throwScope, {});
+ return JSValue::encode(JSC::jsStringWithCache(vm, impl.search()));
+}
+
+JSC_DEFINE_CUSTOM_SETTER(DOMURL__protocol_set,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] {
+ return impl.setProtocol(JSC::JSValue::decode(value).toWTFString(lexicalGlobalObject));
+ });
+
+ return true;
+}
+JSC_DEFINE_CUSTOM_SETTER(DOMURL__username_set,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+
+ invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] {
+ return impl.setUsername(JSC::JSValue::decode(value).toWTFString(lexicalGlobalObject));
+ });
+
+ return true;
+}
+
+JSC_DEFINE_CUSTOM_SETTER(DOMURL__href_set,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+
+ invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] {
+ return impl.setHref(JSC::JSValue::decode(value).toWTFString(lexicalGlobalObject));
+ });
+
+ return true;
+}
+
+JSC_DEFINE_CUSTOM_SETTER(DOMURL__password_set,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] {
+ return impl.setPassword(JSC::JSValue::decode(value).toWTFString(lexicalGlobalObject));
+ });
+
+ return true;
+}
+JSC_DEFINE_CUSTOM_SETTER(DOMURL__host_set,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] {
+ return impl.setHost(JSC::JSValue::decode(value).toWTFString(lexicalGlobalObject));
+ });
+
+ return true;
+}
+JSC_DEFINE_CUSTOM_SETTER(DOMURL__hostname_set,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] {
+ return impl.setHostname(JSC::JSValue::decode(value).toWTFString(lexicalGlobalObject));
+ });
+
+ return true;
+}
+JSC_DEFINE_CUSTOM_SETTER(DOMURL__port_set,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] {
+ return impl.setPort(JSC::JSValue::decode(value).toWTFString(lexicalGlobalObject));
+ });
+
+ return true;
+}
+JSC_DEFINE_CUSTOM_SETTER(DOMURL__pathname_set,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] {
+ return impl.setPathname(JSC::JSValue::decode(value).toWTFString(lexicalGlobalObject));
+ });
+
+ return true;
+}
+JSC_DEFINE_CUSTOM_SETTER(DOMURL__hash_set,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] {
+ return impl.setHash(JSC::JSValue::decode(value).toWTFString(lexicalGlobalObject));
+ });
+
+ return true;
+}
+
+JSC_DEFINE_CUSTOM_SETTER(DOMURL__search_set,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ auto* thisObject = JSC::jsDynamicCast<JSDOMURL*>(lexicalGlobalObject->vm(), JSC::JSValue::decode(thisValue));
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject->wrapped();
+ invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] {
+ return impl.setSearch(JSC::JSValue::decode(value).toWTFString(lexicalGlobalObject));
+ });
+
+ return true;
+}
+
+void JSDOMURL::finishCreation(JSC::VM& vm)
+{
+ Base::finishCreation(vm);
+ auto clientData = Bun::clientData(vm);
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().protocolPublicName(),
+ JSC::CustomGetterSetter::create(vm, DOMURL__protocol_get, DOMURL__protocol_set),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().usernamePublicName(),
+ JSC::CustomGetterSetter::create(vm, DOMURL__username_get, DOMURL__username_set),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().hrefPublicName(),
+ JSC::CustomGetterSetter::create(vm, DOMURL__href_get, DOMURL__href_set),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().passwordPublicName(),
+ JSC::CustomGetterSetter::create(vm, DOMURL__password_get, DOMURL__password_set),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().hostPublicName(),
+ JSC::CustomGetterSetter::create(vm, DOMURL__host_get, DOMURL__host_set),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().hostnamePublicName(),
+ JSC::CustomGetterSetter::create(vm, DOMURL__hostname_get, DOMURL__hostname_set),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().portPublicName(),
+ JSC::CustomGetterSetter::create(vm, DOMURL__port_get, DOMURL__port_set),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().pathnamePublicName(),
+ JSC::CustomGetterSetter::create(vm, DOMURL__pathname_get, DOMURL__pathname_set),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().hashPublicName(),
+ JSC::CustomGetterSetter::create(vm, DOMURL__hash_get, DOMURL__hash_set),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().searchPublicName(),
+ JSC::CustomGetterSetter::create(vm, DOMURL__search_get, DOMURL__search_set),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+}
+
+JSC::GCClient::IsoSubspace* JSDOMURL::subspaceForImpl(JSC::VM& vm)
+{
+ return Bun::subspaceForImpl<JSDOMURL, UseCustomHeapCellType::No>(
+ vm,
+ // this is a placeholder
+ [](auto& spaces) { return spaces.m_clientSubspaceForExposedToWorkerAndWindow.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForExposedToWorkerAndWindow = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForExposedToWorkerAndWindow.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForExposedToWorkerAndWindow = WTFMove(space); });
+}
+
+const ClassInfo JSDOMURL::s_info = { "JSDOMURL", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDOMURL) };
+
+}
diff --git a/src/javascript/jsc/bindings/JSDOMURL.h b/src/javascript/jsc/bindings/JSDOMURL.h
new file mode 100644
index 000000000..edbb280c4
--- /dev/null
+++ b/src/javascript/jsc/bindings/JSDOMURL.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include "BunBuiltinNames.h"
+#include "BunClientData.h"
+#include "DOMURL.h"
+#include "JSDOMWrapper.h"
+#include "root.h"
+
+namespace WebCore {
+
+using namespace WebCore;
+using namespace JSC;
+
+class JSDOMURL : public JSDOMWrapper<DOMURL> {
+ using Base = JSDOMWrapper<DOMURL>;
+
+public:
+ JSDOMURL(JSC::Structure* structure, JSC::JSGlobalObject& global, DOMURL& domURL)
+ : Base(structure, global, domURL)
+ {
+ }
+
+ DECLARE_INFO;
+
+ static constexpr unsigned StructureFlags = Base::StructureFlags;
+
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return subspaceForImpl(vm);
+ }
+ static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm);
+
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject,
+ JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype,
+ JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+ static JSDOMURL* create(JSC::Structure* structure, JSC::JSGlobalObject* global, Ref<DOMURL> domURL)
+ {
+ JSDOMURL* accessor = new (NotNull, JSC::allocateCell<JSDOMURL>(global->vm())) JSDOMURL(structure, *global, WTFMove(domURL));
+ accessor->finishCreation(global->vm());
+ return accessor;
+ }
+
+ void finishCreation(JSC::VM& vm);
+};
+
+} // namespace Zig \ No newline at end of file
diff --git a/src/javascript/jsc/bindings/JSDOMWrapper.cpp b/src/javascript/jsc/bindings/JSDOMWrapper.cpp
new file mode 100644
index 000000000..5fbb4238e
--- /dev/null
+++ b/src/javascript/jsc/bindings/JSDOMWrapper.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "JSDOMWrapper.h"
+#include "root.h"
+
+#include "BunBuiltinNames.h"
+
+// #include "DOMWindow.h"
+// #include "DOMWrapperWorld.h"
+// #include "JSDOMWindow.h"
+// #include "JSRemoteDOMWindow.h"
+// #include "SerializedScriptValue.h"
+// #include <JavaScriptCore/Error.h>
+
+namespace WebCore {
+
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSDOMObject);
+
+JSDOMObject::JSDOMObject(JSC::Structure* structure, JSC::JSGlobalObject& globalObject)
+ : Base(globalObject.vm(), structure)
+{
+ // ASSERT(scriptExecutionContext() || globalObject.classInfo(globalObject.vm()) == JSRemoteDOMWindow::info());
+}
+
+// JSC::JSValue cloneAcrossWorlds(JSC::JSGlobalObject& lexicalGlobalObject, const JSDOMObject& owner, JSC::JSValue value)
+// {
+// if (isWorldCompatible(lexicalGlobalObject, value))
+// return value;
+// // FIXME: Is it best to handle errors by returning null rather than throwing an exception?
+// auto serializedValue = SerializedScriptValue::create(lexicalGlobalObject, value, SerializationErrorMode::NonThrowing);
+// if (!serializedValue)
+// return JSC::jsNull();
+// // FIXME: Why is owner->globalObject() better than lexicalGlobalObject.lexicalGlobalObject() here?
+// // Unlike this, isWorldCompatible uses lexicalGlobalObject.lexicalGlobalObject(); should the two match?
+// return serializedValue->deserialize(lexicalGlobalObject, owner.globalObject());
+// }
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/JSDOMWrapper.h b/src/javascript/jsc/bindings/JSDOMWrapper.h
new file mode 100644
index 000000000..ad374ec2d
--- /dev/null
+++ b/src/javascript/jsc/bindings/JSDOMWrapper.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2009 Google, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+#include "root.h"
+
+#include "NodeConstants.h"
+#include "ZigGlobalObject.h"
+#include <JavaScriptCore/JSDestructibleObject.h>
+#include <wtf/SignedPtr.h>
+
+namespace WebCore {
+using namespace Zig;
+using JSDOMGlobalObject = Zig::GlobalObject;
+
+class ScriptExecutionContext;
+
+// JSC allows us to extend JSType. If the highest 3 bits are set, we can add any Object types and they are
+// recognized as OtherObj in JSC. And we encode Node type into JSType if the given JSType is subclass of Node.
+// offset | 7 | 6 | 5 | 4 3 2 1 0 |
+// value | 1 | 1 | 1 | Non-node DOM types |
+// If the given JSType is a subclass of Node, the format is the following.
+// offset | 7 | 6 | 5 | 4 | 3 2 1 0 |
+// value | 1 | 1 | 1 | 1 | NodeType |
+
+static const uint8_t JSDOMWrapperType = 0b11101110;
+static const uint8_t JSEventType = 0b11101111;
+static const uint8_t JSNodeType = 0b11110000;
+static const uint8_t JSNodeTypeMask = 0b00001111;
+static const uint8_t JSTextNodeType = JSNodeType | NodeConstants::TEXT_NODE;
+static const uint8_t JSProcessingInstructionNodeType = JSNodeType | NodeConstants::PROCESSING_INSTRUCTION_NODE;
+static const uint8_t JSDocumentTypeNodeType = JSNodeType | NodeConstants::DOCUMENT_TYPE_NODE;
+static const uint8_t JSDocumentFragmentNodeType = JSNodeType | NodeConstants::DOCUMENT_FRAGMENT_NODE;
+static const uint8_t JSDocumentWrapperType = JSNodeType | NodeConstants::DOCUMENT_NODE;
+static const uint8_t JSCommentNodeType = JSNodeType | NodeConstants::COMMENT_NODE;
+static const uint8_t JSCDATASectionNodeType = JSNodeType | NodeConstants::CDATA_SECTION_NODE;
+static const uint8_t JSAttrNodeType = JSNodeType | NodeConstants::ATTRIBUTE_NODE;
+static const uint8_t JSElementType = 0b11110000 | NodeConstants::ELEMENT_NODE;
+
+static_assert(JSDOMWrapperType > JSC::LastJSCObjectType, "JSC::JSType offers the highest bit.");
+static_assert(NodeConstants::LastNodeType <= JSNodeTypeMask, "NodeType should be represented in 4bit.");
+
+class JSDOMObject : public JSC::JSDestructibleObject {
+public:
+ typedef JSC::JSDestructibleObject Base;
+
+ template<typename, JSC::SubspaceAccess>
+ static void subspaceFor(JSC::VM&) { RELEASE_ASSERT_NOT_REACHED(); }
+
+ JSDOMGlobalObject* globalObject() const { return JSC::jsCast<JSDOMGlobalObject*>(JSC::JSNonFinalObject::globalObject()); }
+ // ScriptExecutionContext* scriptExecutionContext() const { return globalObject()->scriptExecutionContext(); }
+
+protected:
+ WEBCORE_EXPORT JSDOMObject(JSC::Structure*, JSC::JSGlobalObject&);
+};
+
+template<typename ImplementationClass, typename PtrTraits = RawPtrTraits<ImplementationClass>>
+class JSDOMWrapper : public JSDOMObject {
+public:
+ using Base = JSDOMObject;
+ using DOMWrapped = ImplementationClass;
+
+ ImplementationClass& wrapped() const { return m_wrapped; }
+ static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSDOMWrapper, m_wrapped); }
+ constexpr static bool hasCustomPtrTraits() { return !std::is_same_v<PtrTraits, RawPtrTraits<ImplementationClass>>; };
+
+protected:
+ JSDOMWrapper(JSC::Structure* structure, JSC::JSGlobalObject& globalObject, Ref<ImplementationClass>&& impl)
+ : Base(structure, globalObject)
+ , m_wrapped(WTFMove(impl))
+ {
+ }
+
+private:
+ Ref<ImplementationClass, PtrTraits> m_wrapped;
+};
+
+template<typename ImplementationClass> struct JSDOMWrapperConverterTraits;
+
+JSC::JSValue cloneAcrossWorlds(JSC::JSGlobalObject&, const JSDOMObject& owner, JSC::JSValue);
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/MarkingConstraint.cpp b/src/javascript/jsc/bindings/MarkingConstraint.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/javascript/jsc/bindings/MarkingConstraint.cpp
diff --git a/src/javascript/jsc/bindings/NodeConstants.h b/src/javascript/jsc/bindings/NodeConstants.h
new file mode 100644
index 000000000..ebbdc7812
--- /dev/null
+++ b/src/javascript/jsc/bindings/NodeConstants.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace WebCore {
+
+struct NodeConstants {
+ enum NodeType {
+ ELEMENT_NODE = 1,
+ ATTRIBUTE_NODE = 2,
+ TEXT_NODE = 3,
+ CDATA_SECTION_NODE = 4,
+ PROCESSING_INSTRUCTION_NODE = 7,
+ COMMENT_NODE = 8,
+ DOCUMENT_NODE = 9,
+ DOCUMENT_TYPE_NODE = 10,
+ DOCUMENT_FRAGMENT_NODE = 11,
+ };
+
+ enum DeprecatedNodeType {
+ ENTITY_REFERENCE_NODE = 5,
+ ENTITY_NODE = 6,
+ NOTATION_NODE = 12,
+ };
+
+ static const uint8_t LastNodeType = NOTATION_NODE;
+};
+
+} // namespace WebCore::NodeType
diff --git a/src/javascript/jsc/bindings/StringAdaptors.h b/src/javascript/jsc/bindings/StringAdaptors.h
new file mode 100644
index 000000000..cceaa3a3b
--- /dev/null
+++ b/src/javascript/jsc/bindings/StringAdaptors.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// This exists to communicate to the bindings that this string is not a good candidate
+// for caching.
+// Forces the use of the jsString() converter (rather than the normal jsStringWithCache()).
+struct UncachedString {
+ String string;
+};
+
+// This exists to communicate to the bindings that this string is owned by another
+// object and therefore that collecting the JSString wrapper is unlikely to save memory.
+// Forces the use of the jsOwnedString() converter (rather than the normal jsStringWithCache()).
+struct OwnedString {
+ String string;
+};
+
+}
diff --git a/src/javascript/jsc/bindings/URLDecomposition.cpp b/src/javascript/jsc/bindings/URLDecomposition.cpp
new file mode 100644
index 000000000..2be72c0c6
--- /dev/null
+++ b/src/javascript/jsc/bindings/URLDecomposition.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "URLDecomposition.h"
+
+#include <wtf/text/StringToIntegerConversion.h>
+
+namespace WebCore {
+
+String URLDecomposition::origin() const
+{
+ return fullURL().hostAndPort();
+}
+
+String URLDecomposition::protocol() const
+{
+ auto fullURL = this->fullURL();
+ if (WTF::protocolIsJavaScript(fullURL.string()))
+ return "javascript:"_s;
+ return makeString(fullURL.protocol(), ':');
+}
+
+void URLDecomposition::setProtocol(StringView value)
+{
+ URL copy = fullURL();
+ copy.setProtocol(value);
+ setFullURL(copy);
+}
+
+String URLDecomposition::username() const
+{
+ return fullURL().encodedUser().toString();
+}
+
+void URLDecomposition::setUsername(StringView user)
+{
+ auto fullURL = this->fullURL();
+ if (fullURL.host().isEmpty() || fullURL.cannotBeABaseURL() || fullURL.protocolIs("file"))
+ return;
+ fullURL.setUser(user);
+ setFullURL(fullURL);
+}
+
+String URLDecomposition::password() const
+{
+ return fullURL().encodedPassword().toString();
+}
+
+void URLDecomposition::setPassword(StringView password)
+{
+ auto fullURL = this->fullURL();
+ if (fullURL.host().isEmpty() || fullURL.cannotBeABaseURL() || fullURL.protocolIs("file"))
+ return;
+ fullURL.setPassword(password);
+ setFullURL(fullURL);
+}
+
+String URLDecomposition::host() const
+{
+ return fullURL().hostAndPort();
+}
+
+static unsigned countASCIIDigits(StringView string)
+{
+ unsigned length = string.length();
+ for (unsigned count = 0; count < length; ++count) {
+ if (!isASCIIDigit(string[count]))
+ return count;
+ }
+ return length;
+}
+
+void URLDecomposition::setHost(StringView value)
+{
+ auto fullURL = this->fullURL();
+ if (value.isEmpty() && !fullURL.protocolIs("file") && fullURL.hasSpecialScheme())
+ return;
+
+ size_t separator = value.reverseFind(':');
+ if (!separator)
+ return;
+
+ if (fullURL.cannotBeABaseURL() || !fullURL.canSetHostOrPort())
+ return;
+
+ // No port if no colon or rightmost colon is within the IPv6 section.
+ size_t ipv6Separator = value.reverseFind(']');
+ if (separator == notFound || (ipv6Separator != notFound && ipv6Separator > separator))
+ fullURL.setHost(value);
+ else {
+ // Multiple colons are acceptable only in case of IPv6.
+ if (value.find(':') != separator && ipv6Separator == notFound)
+ return;
+ unsigned portLength = countASCIIDigits(value.substring(separator + 1));
+ if (!portLength) {
+ fullURL.setHost(value.substring(0, separator));
+ } else {
+ auto portNumber = parseInteger<uint16_t>(value.substring(separator + 1, portLength));
+ if (portNumber && WTF::isDefaultPortForProtocol(*portNumber, fullURL.protocol()))
+ fullURL.setHostAndPort(value.substring(0, separator));
+ else
+ fullURL.setHostAndPort(value.substring(0, separator + 1 + portLength));
+ }
+ }
+ if (fullURL.isValid())
+ setFullURL(fullURL);
+}
+
+String URLDecomposition::hostname() const
+{
+ return fullURL().host().toString();
+}
+
+static StringView removeAllLeadingSolidusCharacters(StringView string)
+{
+ unsigned i;
+ unsigned length = string.length();
+ for (i = 0; i < length; ++i) {
+ if (string[i] != '/')
+ break;
+ }
+ return string.substring(i);
+}
+
+void URLDecomposition::setHostname(StringView value)
+{
+ auto fullURL = this->fullURL();
+ auto host = removeAllLeadingSolidusCharacters(value);
+ if (host.isEmpty() && !fullURL.protocolIs("file") && fullURL.hasSpecialScheme())
+ return;
+ if (fullURL.cannotBeABaseURL() || !fullURL.canSetHostOrPort())
+ return;
+ fullURL.setHost(host);
+ if (fullURL.isValid())
+ setFullURL(fullURL);
+}
+
+String URLDecomposition::port() const
+{
+ auto port = fullURL().port();
+ if (!port)
+ return emptyString();
+ return String::number(*port);
+}
+
+// Outer optional is whether we could parse at all. Inner optional is "no port specified".
+static std::optional<std::optional<uint16_t>> parsePort(StringView string, StringView protocol)
+{
+ // https://url.spec.whatwg.org/#port-state with state override given.
+ uint32_t port { 0 };
+ bool foundDigit = false;
+ for (size_t i = 0; i < string.length(); ++i) {
+ auto c = string[i];
+ // https://infra.spec.whatwg.org/#ascii-tab-or-newline
+ if (c == 0x0009 || c == 0x000A || c == 0x000D)
+ continue;
+ if (isASCIIDigit(c)) {
+ port = port * 10 + c - '0';
+ foundDigit = true;
+ if (port > std::numeric_limits<uint16_t>::max())
+ return std::nullopt;
+ continue;
+ }
+ if (!foundDigit)
+ return std::nullopt;
+ break;
+ }
+ if (!foundDigit || WTF::isDefaultPortForProtocol(static_cast<uint16_t>(port), protocol))
+ return std::optional<uint16_t> { std::nullopt };
+ return { { static_cast<uint16_t>(port) } };
+}
+
+void URLDecomposition::setPort(StringView value)
+{
+ auto fullURL = this->fullURL();
+ if (fullURL.host().isEmpty() || fullURL.cannotBeABaseURL() || fullURL.protocolIs("file") || !fullURL.canSetHostOrPort())
+ return;
+ auto port = parsePort(value, fullURL.protocol());
+ if (!port)
+ return;
+ fullURL.setPort(*port);
+ setFullURL(fullURL);
+}
+
+String URLDecomposition::pathname() const
+{
+ return fullURL().path().toString();
+}
+
+void URLDecomposition::setPathname(StringView value)
+{
+ auto fullURL = this->fullURL();
+ if (fullURL.cannotBeABaseURL() || !fullURL.canSetPathname())
+ return;
+ fullURL.setPath(value);
+ setFullURL(fullURL);
+}
+
+String URLDecomposition::search() const
+{
+ auto fullURL = this->fullURL();
+ return fullURL.query().isEmpty() ? emptyString() : fullURL.queryWithLeadingQuestionMark().toString();
+}
+
+void URLDecomposition::setSearch(const String& value)
+{
+ auto fullURL = this->fullURL();
+ if (value.isEmpty()) {
+ // If the given value is the empty string, set url's query to null.
+ fullURL.setQuery({});
+ } else {
+ String newSearch = value;
+ // Make sure that '#' in the query does not leak to the hash.
+ fullURL.setQuery(newSearch.replaceWithLiteral('#', "%23"));
+ }
+ setFullURL(fullURL);
+}
+
+String URLDecomposition::hash() const
+{
+ auto fullURL = this->fullURL();
+ return fullURL.fragmentIdentifier().isEmpty() ? emptyString() : fullURL.fragmentIdentifierWithLeadingNumberSign().toString();
+}
+
+void URLDecomposition::setHash(StringView value)
+{
+ auto fullURL = this->fullURL();
+ if (value.isEmpty())
+ fullURL.removeFragmentIdentifier();
+ else
+ fullURL.setFragmentIdentifier(value.startsWith('#') ? value.substring(1) : value);
+ setFullURL(fullURL);
+}
+
+}
diff --git a/src/javascript/jsc/bindings/URLDecomposition.h b/src/javascript/jsc/bindings/URLDecomposition.h
new file mode 100644
index 000000000..bf9473dcb
--- /dev/null
+++ b/src/javascript/jsc/bindings/URLDecomposition.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "root.h"
+
+#include <wtf/URL.h>
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class URLDecomposition {
+public:
+ String origin() const;
+
+ WEBCORE_EXPORT String protocol() const;
+ void setProtocol(StringView);
+
+ String username() const;
+ void setUsername(StringView);
+
+ String password() const;
+ void setPassword(StringView);
+
+ WEBCORE_EXPORT String host() const;
+ void setHost(StringView);
+
+ WEBCORE_EXPORT String hostname() const;
+ void setHostname(StringView);
+
+ WEBCORE_EXPORT String port() const;
+ void setPort(StringView);
+
+ WEBCORE_EXPORT String pathname() const;
+ void setPathname(StringView);
+
+ WEBCORE_EXPORT String search() const;
+ void setSearch(const String&);
+
+ WEBCORE_EXPORT String hash() const;
+ void setHash(StringView);
+
+protected:
+ virtual ~URLDecomposition() = default;
+
+private:
+ virtual URL fullURL() const = 0;
+ virtual void setFullURL(const URL&) = 0;
+};
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/URLSearchParams.cpp b/src/javascript/jsc/bindings/URLSearchParams.cpp
new file mode 100644
index 000000000..11d86bceb
--- /dev/null
+++ b/src/javascript/jsc/bindings/URLSearchParams.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "URLSearchParams.h"
+
+#include "DOMURL.h"
+#include <wtf/URLParser.h>
+
+namespace WebCore {
+
+URLSearchParams::URLSearchParams(const String& init, DOMURL* associatedURL)
+ : m_associatedURL(associatedURL)
+ , m_pairs(init.startsWith('?') ? WTF::URLParser::parseURLEncodedForm(StringView(init).substring(1)) : WTF::URLParser::parseURLEncodedForm(init))
+{
+}
+
+URLSearchParams::URLSearchParams(const Vector<KeyValuePair<String, String>>& pairs)
+ : m_pairs(pairs)
+{
+}
+
+ExceptionOr<Ref<URLSearchParams>> URLSearchParams::create(std::variant<Vector<Vector<String>>, Vector<KeyValuePair<String, String>>, String>&& variant)
+{
+ auto visitor = WTF::makeVisitor([&](const Vector<Vector<String>>& vector) -> ExceptionOr<Ref<URLSearchParams>> {
+ Vector<KeyValuePair<String, String>> pairs;
+ for (const auto& pair : vector) {
+ if (pair.size() != 2)
+ return Exception { TypeError };
+ pairs.append({pair[0], pair[1]});
+ }
+ return adoptRef(*new URLSearchParams(WTFMove(pairs))); }, [&](const Vector<KeyValuePair<String, String>>& pairs) -> ExceptionOr<Ref<URLSearchParams>> { return adoptRef(*new URLSearchParams(pairs)); }, [&](const String& string) -> ExceptionOr<Ref<URLSearchParams>> { return adoptRef(*new URLSearchParams(string, nullptr)); });
+ return std::visit(visitor, variant);
+}
+
+String URLSearchParams::get(const String& name) const
+{
+ for (const auto& pair : m_pairs) {
+ if (pair.key == name)
+ return pair.value;
+ }
+ return String();
+}
+
+bool URLSearchParams::has(const String& name) const
+{
+ for (const auto& pair : m_pairs) {
+ if (pair.key == name)
+ return true;
+ }
+ return false;
+}
+
+void URLSearchParams::sort()
+{
+ std::stable_sort(m_pairs.begin(), m_pairs.end(), [](const auto& a, const auto& b) {
+ return WTF::codePointCompareLessThan(a.key, b.key);
+ });
+ updateURL();
+}
+
+void URLSearchParams::set(const String& name, const String& value)
+{
+ for (auto& pair : m_pairs) {
+ if (pair.key != name)
+ continue;
+ if (pair.value != value)
+ pair.value = value;
+ bool skippedFirstMatch = false;
+ m_pairs.removeAllMatching([&](const auto& pair) {
+ if (pair.key == name) {
+ if (skippedFirstMatch)
+ return true;
+ skippedFirstMatch = true;
+ }
+ return false;
+ });
+ updateURL();
+ return;
+ }
+ m_pairs.append({ name, value });
+ updateURL();
+}
+
+void URLSearchParams::append(const String& name, const String& value)
+{
+ m_pairs.append({ name, value });
+ updateURL();
+}
+
+Vector<String> URLSearchParams::getAll(const String& name) const
+{
+ Vector<String> values;
+ values.reserveInitialCapacity(m_pairs.size());
+ for (const auto& pair : m_pairs) {
+ if (pair.key == name)
+ values.uncheckedAppend(pair.value);
+ }
+ values.shrinkToFit();
+ return values;
+}
+
+void URLSearchParams::remove(const String& name)
+{
+ m_pairs.removeAllMatching([&](const auto& pair) {
+ return pair.key == name;
+ });
+ updateURL();
+}
+
+String URLSearchParams::toString() const
+{
+ return WTF::URLParser::serialize(m_pairs);
+}
+
+void URLSearchParams::updateURL()
+{
+ if (m_associatedURL)
+ m_associatedURL->setQuery(WTF::URLParser::serialize(m_pairs));
+}
+
+void URLSearchParams::updateFromAssociatedURL()
+{
+ ASSERT(m_associatedURL);
+ String search = m_associatedURL->search();
+ m_pairs = search.startsWith('?') ? WTF::URLParser::parseURLEncodedForm(StringView(search).substring(1)) : WTF::URLParser::parseURLEncodedForm(search);
+}
+
+std::optional<KeyValuePair<String, String>> URLSearchParams::Iterator::next()
+{
+ auto& pairs = m_target->pairs();
+ if (m_index >= pairs.size())
+ return std::nullopt;
+
+ auto& pair = pairs[m_index++];
+ return KeyValuePair<String, String> { pair.key, pair.value };
+}
+
+URLSearchParams::Iterator::Iterator(URLSearchParams& params)
+ : m_target(params)
+{
+}
+
+}
diff --git a/src/javascript/jsc/bindings/URLSearchParams.h b/src/javascript/jsc/bindings/URLSearchParams.h
new file mode 100644
index 000000000..a3c6c3171
--- /dev/null
+++ b/src/javascript/jsc/bindings/URLSearchParams.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "root.h"
+
+#include "ExceptionOr.h"
+#include <variant>
+#include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class DOMURL;
+
+class URLSearchParams : public RefCounted<URLSearchParams> {
+public:
+ static ExceptionOr<Ref<URLSearchParams>> create(std::variant<Vector<Vector<String>>, Vector<KeyValuePair<String, String>>, String>&&);
+ static Ref<URLSearchParams> create(const String& string, DOMURL* associatedURL)
+ {
+ return adoptRef(*new URLSearchParams(string, associatedURL));
+ }
+
+ void append(const String& name, const String& value);
+ void remove(const String& name);
+ String get(const String& name) const;
+ Vector<String> getAll(const String& name) const;
+ bool has(const String& name) const;
+ void set(const String& name, const String& value);
+ String toString() const;
+ void updateFromAssociatedURL();
+ void sort();
+
+ class Iterator {
+ public:
+ explicit Iterator(URLSearchParams&);
+ std::optional<KeyValuePair<String, String>> next();
+
+ private:
+ Ref<URLSearchParams> m_target;
+ size_t m_index { 0 };
+ };
+ Iterator createIterator() { return Iterator { *this }; }
+
+private:
+ const Vector<KeyValuePair<String, String>>& pairs() const { return m_pairs; }
+ URLSearchParams(const String&, DOMURL*);
+ URLSearchParams(const Vector<KeyValuePair<String, String>>&);
+ void updateURL();
+
+ WeakPtr<DOMURL> m_associatedURL;
+ Vector<KeyValuePair<String, String>> m_pairs;
+};
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
index ad1c23da5..fd43fcaeb 100644
--- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp
+++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
@@ -75,6 +75,8 @@
#include "ZigSourceProvider.h"
+#include "JSDOMURL.h"
+
using JSGlobalObject = JSC::JSGlobalObject;
using Exception = JSC::Exception;
using JSValue = JSC::JSValue;
@@ -699,6 +701,14 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count)
JSC::CustomGetterSetter::create(vm(), property_lazyProcessGetter, property_lazyProcessSetter),
PropertyAttribute::DontDelete | JSC::PropertyAttribute::CustomAccessor | 0);
+ auto domURL = WebCore::DOMURL::create("https://example.com/"_s, WTF::String());
+ auto url = WebCore::JSDOMURL::create(
+ WebCore::JSDOMURL::createStructure(vm(), this, objectPrototype()),
+ this,
+ domURL.returnValue().get());
+
+ this->putDirect(vm(), clientData->builtinNames().urlPublicName(), JSC::JSValue(url), JSC::PropertyAttribute::DontDelete | 0);
+
extraStaticGlobals.releaseBuffer();
}
diff --git a/src/javascript/jsc/bindings/root.h b/src/javascript/jsc/bindings/root.h
index 4577ab0fd..0d120977e 100644
--- a/src/javascript/jsc/bindings/root.h
+++ b/src/javascript/jsc/bindings/root.h
@@ -40,8 +40,10 @@
#if defined(BUILDING_JavaScriptCore) || defined(STATICALLY_LINKED_WITH_JavaScriptCore)
#define JS_EXPORT_PRIVATE WTF_EXPORT_DECLARATION
+#define WEBCORE_EXPORT WTF_EXPORT_DECLARATION
#else
#define JS_EXPORT_PRIVATE WTF_IMPORT_DECLARATION
+#define WEBCORE_EXPORT WTF_IMPORT_DECLARATION
#endif
#endif