From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- js/xpconnect/loader/ModuleEnvironmentProxy.cpp | 238 +++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 js/xpconnect/loader/ModuleEnvironmentProxy.cpp (limited to 'js/xpconnect/loader/ModuleEnvironmentProxy.cpp') diff --git a/js/xpconnect/loader/ModuleEnvironmentProxy.cpp b/js/xpconnect/loader/ModuleEnvironmentProxy.cpp new file mode 100644 index 0000000000..d513bc6194 --- /dev/null +++ b/js/xpconnect/loader/ModuleEnvironmentProxy.cpp @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "ModuleEnvironmentProxy.h" + +#include "mozilla/Assertions.h" // MOZ_ASSERT +#include "mozilla/Maybe.h" // mozilla::Maybe + +#include // size_t + +#include "js/Class.h" // JS::ObjectOpResult +#include "js/ErrorReport.h" // JS_ReportOutOfMemory +#include "js/GCVector.h" // JS::RootedVector +#include "js/Id.h" // JS::PropertyKey +#include "js/PropertyAndElement.h" // JS::IdVector, JS_HasPropertyById, JS_GetPropertyById, JS_Enumerate +#include "js/PropertyDescriptor.h" // JS::PropertyDescriptor, JS_GetOwnPropertyDescriptorById +#include "js/PropertyDescriptor.h" // JS::PropertyDescriptor, JS_GetOwnPropertyDescriptorById +#include "js/Proxy.h" // js::ProxyOptions, js::NewProxyObject, js::GetProxyPrivate +#include "js/RootingAPI.h" // JS::Rooted, JS::Handle, JS::MutableHandle +#include "js/TypeDecls.h" // JSContext, JSObject, JS::MutableHandleVector +#include "js/Value.h" // JS::Value +#include "js/friend/ErrorMessages.h" // JSMSG_* +#include "js/String.h" +#include "js/Modules.h" + +namespace mozilla { +namespace loader { + +struct ModuleEnvironmentProxyHandler : public js::BaseProxyHandler { + ModuleEnvironmentProxyHandler() : js::BaseProxyHandler(&gFamily, false) {} + + bool defineProperty(JSContext* aCx, JS::Handle aProxy, + JS::Handle aId, + JS::Handle aDesc, + JS::ObjectOpResult& aResult) const override { + return aResult.fail(JSMSG_CANT_DEFINE_PROP_OBJECT_NOT_EXTENSIBLE); + } + + bool getPrototype(JSContext* aCx, JS::Handle aProxy, + JS::MutableHandle aProtop) const override { + aProtop.set(nullptr); + return true; + } + + bool setPrototype(JSContext* aCx, JS::Handle aProxy, + JS::Handle aProto, + JS::ObjectOpResult& aResult) const override { + if (!aProto) { + return aResult.succeed(); + } + return aResult.failCantSetProto(); + } + + bool getPrototypeIfOrdinary( + JSContext* aCx, JS::Handle aProxy, bool* aIsOrdinary, + JS::MutableHandle aProtop) const override { + *aIsOrdinary = false; + return true; + } + + bool setImmutablePrototype(JSContext* aCx, JS::Handle aProxy, + bool* aSucceeded) const override { + *aSucceeded = true; + return true; + } + + bool preventExtensions(JSContext* aCx, JS::Handle aProxy, + JS::ObjectOpResult& aResult) const override { + aResult.succeed(); + return true; + } + + bool isExtensible(JSContext* aCx, JS::Handle aProxy, + bool* aExtensible) const override { + *aExtensible = false; + return true; + } + + bool set(JSContext* aCx, JS::Handle aProxy, + JS::Handle aId, JS::Handle aValue, + JS::Handle aReceiver, + JS::ObjectOpResult& aResult) const override { + return aResult.failReadOnly(); + } + + bool delete_(JSContext* aCx, JS::Handle aProxy, + JS::Handle aId, + JS::ObjectOpResult& aResult) const override { + return aResult.failCantDelete(); + } + + bool getOwnPropertyDescriptor( + JSContext* aCx, JS::Handle aProxy, + JS::Handle aId, + JS::MutableHandle> aDesc) + const override; + bool has(JSContext* aCx, JS::Handle aProxy, + JS::Handle aId, bool* aBp) const override; + bool get(JSContext* aCx, JS::Handle aProxy, + JS::Handle receiver, JS::Handle aId, + JS::MutableHandle aVp) const override; + bool ownPropertyKeys( + JSContext* aCx, JS::Handle aProxy, + JS::MutableHandleVector aProps) const override; + + private: + static JSObject* getEnvironment(JS::Handle aProxy) { + return &js::GetProxyPrivate(aProxy).toObject(); + } + + static bool equalsNamespace(JSContext* aCx, JS::Handle aId, + bool* aMatch) { + if (!aId.isString()) { + *aMatch = false; + return true; + } + return JS_StringEqualsLiteral(aCx, aId.toString(), "*namespace*", aMatch); + } + + public: + static const char gFamily; + static const ModuleEnvironmentProxyHandler gHandler; +}; + +const ModuleEnvironmentProxyHandler ModuleEnvironmentProxyHandler::gHandler; +const char ModuleEnvironmentProxyHandler::gFamily = 0; + +bool ModuleEnvironmentProxyHandler::getOwnPropertyDescriptor( + JSContext* aCx, JS::Handle aProxy, + JS::Handle aId, + JS::MutableHandle> aDesc) const { + bool isNamespace; + if (!equalsNamespace(aCx, aId, &isNamespace)) { + return false; + } + if (isNamespace) { + aDesc.reset(); + return true; + } + + JS::Rooted envObj(aCx, getEnvironment(aProxy)); + if (!JS_GetOwnPropertyDescriptorById(aCx, envObj, aId, aDesc)) { + return false; + } + + if (aDesc.get().isNothing()) { + return true; + } + + JS::PropertyDescriptor& desc = *aDesc.get(); + + desc.setConfigurable(false); + desc.setWritable(false); + desc.setEnumerable(true); + + return true; +} + +bool ModuleEnvironmentProxyHandler::has(JSContext* aCx, + JS::Handle aProxy, + JS::Handle aId, + bool* aBp) const { + bool isNamespace; + if (!equalsNamespace(aCx, aId, &isNamespace)) { + return false; + } + if (isNamespace) { + *aBp = false; + return true; + } + + JS::Rooted envObj(aCx, getEnvironment(aProxy)); + return JS_HasOwnPropertyById(aCx, envObj, aId, aBp); +} + +bool ModuleEnvironmentProxyHandler::get( + JSContext* aCx, JS::Handle aProxy, + JS::Handle aReceiver, JS::Handle aId, + JS::MutableHandle aVp) const { + bool isNamespace; + if (!equalsNamespace(aCx, aId, &isNamespace)) { + return false; + } + if (isNamespace) { + aVp.setUndefined(); + return true; + } + + JS::Rooted envObj(aCx, getEnvironment(aProxy)); + return JS_GetPropertyById(aCx, envObj, aId, aVp); +} + +bool ModuleEnvironmentProxyHandler::ownPropertyKeys( + JSContext* aCx, JS::Handle aProxy, + JS::MutableHandleVector aProps) const { + JS::Rooted envObj(aCx, getEnvironment(aProxy)); + JS::Rooted ids(aCx, JS::IdVector(aCx)); + if (!JS_Enumerate(aCx, envObj, &ids)) { + return false; + } + + for (size_t i = 0; i < ids.length(); i++) { + bool isNamespace; + if (!equalsNamespace(aCx, ids[i], &isNamespace)) { + return false; + } + if (isNamespace) { + continue; + } + if (!aProps.append(ids[i])) { + JS_ReportOutOfMemory(aCx); + return false; + } + } + + return true; +} + +JSObject* CreateModuleEnvironmentProxy(JSContext* aCx, + JS::Handle aModuleObj) { + js::ProxyOptions options; + options.setLazyProto(true); + + JS::Rooted envObj(aCx, JS::GetModuleEnvironment(aCx, aModuleObj)); + if (!envObj) { + return nullptr; + } + + JS::Rooted envVal(aCx, JS::ObjectValue(*envObj)); + return NewProxyObject(aCx, &ModuleEnvironmentProxyHandler::gHandler, envVal, + nullptr, options); +} + +} // namespace loader +} // namespace mozilla -- cgit v1.2.3