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/JSMEnvironmentProxy.cpp | 260 ++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 js/xpconnect/loader/JSMEnvironmentProxy.cpp (limited to 'js/xpconnect/loader/JSMEnvironmentProxy.cpp') diff --git a/js/xpconnect/loader/JSMEnvironmentProxy.cpp b/js/xpconnect/loader/JSMEnvironmentProxy.cpp new file mode 100644 index 0000000000..6c4a532d44 --- /dev/null +++ b/js/xpconnect/loader/JSMEnvironmentProxy.cpp @@ -0,0 +1,260 @@ +/* -*- 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 "JSMEnvironmentProxy.h" + +#include "mozilla/Assertions.h" // MOZ_ASSERT +#include "mozilla/Maybe.h" // mozilla::Maybe + +#include // size_t + +#include "jsapi.h" // JS_HasExtensibleLexicalEnvironment, JS_ExtensibleLexicalEnvironment +#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_HasOwnPropertyById, 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, JS::UndefinedValue, JS_UNINITIALIZED_LEXICAL +#include "js/friend/ErrorMessages.h" // JSMSG_* + +namespace mozilla { +namespace loader { + +struct JSMEnvironmentProxyHandler : public js::BaseProxyHandler { + JSMEnvironmentProxyHandler() : 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 aReceiver, JS::Handle aId, + JS::MutableHandle aVp) const override; + bool ownPropertyKeys( + JSContext* aCx, JS::Handle aProxy, + JS::MutableHandleVector aProps) const override; + + private: + static JSObject* getGlobal(JSContext* aCx, JS::Handle aProxy) { + JS::Rooted globalObj(aCx, + &js::GetProxyPrivate(aProxy).toObject()); + return globalObj; + } + + public: + static const char gFamily; + static const JSMEnvironmentProxyHandler gHandler; +}; + +const JSMEnvironmentProxyHandler JSMEnvironmentProxyHandler::gHandler; +const char JSMEnvironmentProxyHandler::gFamily = 0; + +JSObject* ResolveModuleObjectPropertyById(JSContext* aCx, + JS::Handle aModObj, + JS::Handle aId) { + if (JS_HasExtensibleLexicalEnvironment(aModObj)) { + JS::Rooted lexical(aCx, + JS_ExtensibleLexicalEnvironment(aModObj)); + bool found; + if (!JS_HasOwnPropertyById(aCx, lexical, aId, &found)) { + return nullptr; + } + if (found) { + return lexical; + } + } + return aModObj; +} + +JSObject* ResolveModuleObjectProperty(JSContext* aCx, + JS::Handle aModObj, + const char* aName) { + if (JS_HasExtensibleLexicalEnvironment(aModObj)) { + JS::RootedObject lexical(aCx, JS_ExtensibleLexicalEnvironment(aModObj)); + bool found; + if (!JS_HasOwnProperty(aCx, lexical, aName, &found)) { + return nullptr; + } + if (found) { + return lexical; + } + } + return aModObj; +} + +bool JSMEnvironmentProxyHandler::getOwnPropertyDescriptor( + JSContext* aCx, JS::Handle aProxy, + JS::Handle aId, + JS::MutableHandle> aDesc) const { + JS::Rooted globalObj(aCx, getGlobal(aCx, aProxy)); + JS::Rooted holder( + aCx, ResolveModuleObjectPropertyById(aCx, globalObj, aId)); + if (!JS_GetOwnPropertyDescriptorById(aCx, holder, aId, aDesc)) { + return false; + } + + if (aDesc.get().isNothing()) { + return true; + } + + JS::PropertyDescriptor& desc = *aDesc.get(); + + if (desc.hasValue()) { + if (desc.value().isMagic(JS_UNINITIALIZED_LEXICAL)) { + desc.setValue(JS::UndefinedValue()); + } + } + + desc.setConfigurable(false); + desc.setEnumerable(true); + if (!desc.isAccessorDescriptor()) { + desc.setWritable(false); + } + + return true; +} + +bool JSMEnvironmentProxyHandler::has(JSContext* aCx, + JS::Handle aProxy, + JS::Handle aId, + bool* aBp) const { + JS::Rooted globalObj(aCx, getGlobal(aCx, aProxy)); + JS::Rooted holder( + aCx, ResolveModuleObjectPropertyById(aCx, globalObj, aId)); + return JS_HasPropertyById(aCx, holder, aId, aBp); +} + +bool JSMEnvironmentProxyHandler::get(JSContext* aCx, + JS::Handle aProxy, + JS::Handle aReceiver, + JS::Handle aId, + JS::MutableHandle aVp) const { + JS::Rooted globalObj(aCx, getGlobal(aCx, aProxy)); + JS::Rooted holder( + aCx, ResolveModuleObjectPropertyById(aCx, globalObj, aId)); + if (!JS_GetPropertyById(aCx, holder, aId, aVp)) { + return false; + } + + if (aVp.isMagic(JS_UNINITIALIZED_LEXICAL)) { + aVp.setUndefined(); + } + + return true; +} + +bool JSMEnvironmentProxyHandler::ownPropertyKeys( + JSContext* aCx, JS::Handle aProxy, + JS::MutableHandleVector aProps) const { + JS::Rooted globalObj(aCx, getGlobal(aCx, aProxy)); + JS::Rooted globalIds(aCx, JS::IdVector(aCx)); + if (!JS_Enumerate(aCx, globalObj, &globalIds)) { + return false; + } + + for (size_t i = 0; i < globalIds.length(); i++) { + if (!aProps.append(globalIds[i])) { + JS_ReportOutOfMemory(aCx); + return false; + } + } + + JS::RootedObject lexicalEnv(aCx, JS_ExtensibleLexicalEnvironment(globalObj)); + JS::Rooted lexicalIds(aCx, JS::IdVector(aCx)); + if (!JS_Enumerate(aCx, lexicalEnv, &lexicalIds)) { + return false; + } + + for (size_t i = 0; i < lexicalIds.length(); i++) { + if (!aProps.append(lexicalIds[i])) { + JS_ReportOutOfMemory(aCx); + return false; + } + } + + return true; +} + +JSObject* CreateJSMEnvironmentProxy(JSContext* aCx, + JS::Handle aGlobalObj) { + js::ProxyOptions options; + options.setLazyProto(true); + + JS::Rooted globalVal(aCx, JS::ObjectValue(*aGlobalObj)); + return NewProxyObject(aCx, &JSMEnvironmentProxyHandler::gHandler, globalVal, + nullptr, options); +} + +} // namespace loader +} // namespace mozilla -- cgit v1.2.3