mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-09-26 23:54:56 +00:00
125 lines
3.5 KiB
C
125 lines
3.5 KiB
C
|
/* -*- 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/. */
|
||
|
|
||
|
#ifndef jscompartmentinlines_h
|
||
|
#define jscompartmentinlines_h
|
||
|
|
||
|
#include "jscompartment.h"
|
||
|
|
||
|
#include "gc/Barrier.h"
|
||
|
|
||
|
#include "jscntxtinlines.h"
|
||
|
|
||
|
inline void
|
||
|
JSCompartment::initGlobal(js::GlobalObject& global)
|
||
|
{
|
||
|
MOZ_ASSERT(global.compartment() == this);
|
||
|
MOZ_ASSERT(!global_);
|
||
|
global_.set(&global);
|
||
|
}
|
||
|
|
||
|
js::GlobalObject*
|
||
|
JSCompartment::maybeGlobal() const
|
||
|
{
|
||
|
MOZ_ASSERT_IF(global_, global_->compartment() == this);
|
||
|
return global_;
|
||
|
}
|
||
|
|
||
|
js::GlobalObject*
|
||
|
JSCompartment::unsafeUnbarrieredMaybeGlobal() const
|
||
|
{
|
||
|
return *global_.unsafeGet();
|
||
|
}
|
||
|
|
||
|
js::AutoCompartment::AutoCompartment(ExclusiveContext* cx, JSObject* target)
|
||
|
: cx_(cx),
|
||
|
origin_(cx->compartment_)
|
||
|
{
|
||
|
cx_->enterCompartment(target->compartment());
|
||
|
}
|
||
|
|
||
|
js::AutoCompartment::AutoCompartment(ExclusiveContext* cx, JSCompartment* target)
|
||
|
: cx_(cx),
|
||
|
origin_(cx_->compartment_)
|
||
|
{
|
||
|
cx_->enterCompartment(target);
|
||
|
}
|
||
|
|
||
|
js::AutoCompartment::~AutoCompartment()
|
||
|
{
|
||
|
cx_->leaveCompartment(origin_);
|
||
|
}
|
||
|
|
||
|
inline bool
|
||
|
JSCompartment::wrap(JSContext* cx, JS::MutableHandleValue vp, JS::HandleObject existing)
|
||
|
{
|
||
|
MOZ_ASSERT_IF(existing, vp.isObject());
|
||
|
|
||
|
/* Only GC things have to be wrapped or copied. */
|
||
|
if (!vp.isMarkable())
|
||
|
return true;
|
||
|
|
||
|
/*
|
||
|
* Symbols are GC things, but never need to be wrapped or copied because
|
||
|
* they are always allocated in the atoms compartment.
|
||
|
*/
|
||
|
if (vp.isSymbol())
|
||
|
return true;
|
||
|
|
||
|
/* Handle strings. */
|
||
|
if (vp.isString()) {
|
||
|
JS::RootedString str(cx, vp.toString());
|
||
|
if (!wrap(cx, &str))
|
||
|
return false;
|
||
|
vp.setString(str);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
MOZ_ASSERT(vp.isObject());
|
||
|
|
||
|
/*
|
||
|
* All that's left are objects.
|
||
|
*
|
||
|
* Object wrapping isn't the fastest thing in the world, in part because
|
||
|
* we have to unwrap and invoke the prewrap hook to find the identity
|
||
|
* object before we even start checking the cache. Neither of these
|
||
|
* operations are needed in the common case, where we're just wrapping
|
||
|
* a plain JS object from the wrappee's side of the membrane to the
|
||
|
* wrapper's side.
|
||
|
*
|
||
|
* To optimize this, we note that the cache should only ever contain
|
||
|
* identity objects - that is to say, objects that serve as the
|
||
|
* canonical representation for a unique object identity observable by
|
||
|
* script. Unwrap and prewrap are both steps that we take to get to the
|
||
|
* identity of an incoming objects, and as such, they shuld never map
|
||
|
* one identity object to another object. This means that we can safely
|
||
|
* check the cache immediately, and only risk false negatives. Do this
|
||
|
* in opt builds, and do both in debug builds so that we can assert
|
||
|
* that we get the same answer.
|
||
|
*/
|
||
|
#ifdef DEBUG
|
||
|
JS::RootedObject cacheResult(cx);
|
||
|
#endif
|
||
|
JS::RootedValue v(cx, vp);
|
||
|
if (js::WrapperMap::Ptr p = crossCompartmentWrappers.lookup(js::CrossCompartmentKey(v))) {
|
||
|
#ifdef DEBUG
|
||
|
cacheResult = &p->value().get().toObject();
|
||
|
#else
|
||
|
vp.set(p->value());
|
||
|
return true;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
JS::RootedObject obj(cx, &vp.toObject());
|
||
|
if (!wrap(cx, &obj, existing))
|
||
|
return false;
|
||
|
vp.setObject(*obj);
|
||
|
MOZ_ASSERT_IF(cacheResult, obj == cacheResult);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
#endif /* jscompartmentinlines_h */
|