diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /js/src/vm/ProxyObject.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'js/src/vm/ProxyObject.cpp')
-rw-r--r-- | js/src/vm/ProxyObject.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/js/src/vm/ProxyObject.cpp b/js/src/vm/ProxyObject.cpp new file mode 100644 index 000000000..49ed5a624 --- /dev/null +++ b/js/src/vm/ProxyObject.cpp @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * 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 "vm/ProxyObject.h" + +#include "jscompartment.h" + +#include "proxy/DeadObjectProxy.h" +#include "proxy/ScriptedProxyHandler.h" + +#include "jsobjinlines.h" + +using namespace js; + +/* static */ ProxyObject* +ProxyObject::New(JSContext* cx, const BaseProxyHandler* handler, HandleValue priv, TaggedProto proto_, + const ProxyOptions& options) +{ + Rooted<TaggedProto> proto(cx, proto_); + + const Class* clasp = options.clasp(); + + MOZ_ASSERT(isValidProxyClass(clasp)); + MOZ_ASSERT(clasp->shouldDelayMetadataBuilder()); + MOZ_ASSERT_IF(proto.isObject(), cx->compartment() == proto.toObject()->compartment()); + MOZ_ASSERT(clasp->hasFinalize()); + + /* + * Eagerly mark properties unknown for proxies, so we don't try to track + * their properties and so that we don't need to walk the compartment if + * their prototype changes later. But don't do this for DOM proxies, + * because we want to be able to keep track of them in typesets in useful + * ways. + */ + if (proto.isObject() && !options.singleton() && !clasp->isDOMClass()) { + RootedObject protoObj(cx, proto.toObject()); + if (!JSObject::setNewGroupUnknown(cx, clasp, protoObj)) + return nullptr; + } + + // Ensure that the wrapper has the same lifetime assumptions as the + // wrappee. Prefer to allocate in the nursery, when possible. + NewObjectKind newKind = NurseryAllocatedProxy; + if (options.singleton()) { + MOZ_ASSERT(priv.isGCThing() && priv.toGCThing()->isTenured()); + newKind = SingletonObject; + } else if ((priv.isGCThing() && priv.toGCThing()->isTenured()) || + !handler->canNurseryAllocate() || + !handler->finalizeInBackground(priv)) + { + newKind = TenuredObject; + } + + gc::AllocKind allocKind = gc::GetGCObjectKind(clasp); + if (handler->finalizeInBackground(priv)) + allocKind = GetBackgroundAllocKind(allocKind); + + AutoSetNewObjectMetadata metadata(cx); + // Note: this will initialize the object's |data| to strange values, but we + // will immediately overwrite those below. + RootedObject obj(cx, NewObjectWithGivenTaggedProto(cx, clasp, proto, allocKind, + newKind)); + if (!obj) + return nullptr; + + Rooted<ProxyObject*> proxy(cx, &obj->as<ProxyObject>()); + new (proxy->data.values) detail::ProxyValueArray; + proxy->data.handler = handler; + proxy->setCrossCompartmentPrivate(priv); + + /* Don't track types of properties of non-DOM and non-singleton proxies. */ + if (newKind != SingletonObject && !clasp->isDOMClass()) + MarkObjectGroupUnknownProperties(cx, proxy->group()); + + return proxy; +} + +gc::AllocKind +ProxyObject::allocKindForTenure() const +{ + gc::AllocKind allocKind = gc::GetGCObjectKind(group()->clasp()); + if (data.handler->finalizeInBackground(const_cast<ProxyObject*>(this)->private_())) + allocKind = GetBackgroundAllocKind(allocKind); + return allocKind; +} + +/* static */ size_t +ProxyObject::objectMovedDuringMinorGC(TenuringTracer* trc, JSObject* dst, JSObject* src) +{ + ProxyObject& psrc = src->as<ProxyObject>(); + ProxyObject& pdst = dst->as<ProxyObject>(); + + // We're about to sweep the nursery heap, so migrate the inline + // ProxyValueArray to the malloc heap if they were nursery allocated. + if (trc->runtime()->gc.nursery.isInside(psrc.data.values)) + pdst.data.values = js_new<detail::ProxyValueArray>(*psrc.data.values); + else + trc->runtime()->gc.nursery.removeMallocedBuffer(psrc.data.values); + return sizeof(detail::ProxyValueArray); +} + +void +ProxyObject::setCrossCompartmentPrivate(const Value& priv) +{ + *slotOfPrivate() = priv; +} + +void +ProxyObject::setSameCompartmentPrivate(const Value& priv) +{ + MOZ_ASSERT(IsObjectValueInCompartment(priv, compartment())); + *slotOfPrivate() = priv; +} + +void +ProxyObject::nuke() +{ + // When nuking scripted proxies, isCallable and isConstructor values for + // the proxy needs to be preserved. Do this before clearing the target. + uint32_t callable = handler()->isCallable(this) + ? ScriptedProxyHandler::IS_CALLABLE : 0; + uint32_t constructor = handler()->isConstructor(this) + ? ScriptedProxyHandler::IS_CONSTRUCTOR : 0; + setExtra(ScriptedProxyHandler::IS_CALLCONSTRUCT_EXTRA, + PrivateUint32Value(callable | constructor)); + + // Clear the target reference. + setSameCompartmentPrivate(NullValue()); + + // Update the handler to make this a DeadObjectProxy. + setHandler(&DeadObjectProxy::singleton); + + // The proxy's extra slots are not cleared and will continue to be + // traced. This avoids the possibility of triggering write barriers while + // nuking proxies in dead compartments which could otherwise cause those + // compartments to be kept alive. Note that these are slots cannot hold + // cross compartment pointers, so this cannot cause the target compartment + // to leak. +} + +JS_FRIEND_API(void) +js::SetValueInProxy(Value* slot, const Value& value) +{ + // Slots in proxies are not GCPtrValues, so do a cast whenever assigning + // values to them which might trigger a barrier. + *reinterpret_cast<GCPtrValue*>(slot) = value; +} |