mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
75be9ceb09
- Bug 1240094 - nsDocShell should initialize mUserContextId to nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID, r=smaug (a3a8358561) - Bug 1142768 - Return the original document URI from ServiceWorkerClient.url; r=bkelly (17892631ab) - Bug 1233613 - Make RegisterFrameCaptureListener fallible. r=mt (0a68d5f4ac) - Bug 1233613 - Locate parent document before getting presentation shell for canvas capture. r=mt (47a285deab) - Bug 866513 - Non-empty MediaStreamTrack labels. r=jib (1b1f364811) - Bug 1170958 - Don't create owned MediaStreamTracks in MetadataLoaded. r=roc (3f031298fb) - fix misspatch of Bug 1131802 part 2 (3a1e0d2799) - trivial fixes (bffbd65448) - Bug 1218454 - part 2a - fix bootlegging of nsContentUtils.h includes from nsILoadContext.h; r=bz (a587b686cd) - bit of Bug 1223078 - Release WrappedJS eagerly (1fcb1a490b) - Bug 1245767 followup - Throw an error when gczeal argument is out of range. r=jonco on IRC (32de34e6b7) - Bug 1241934 - Remove the unused validategc API; r=jonco (a80436895b) - Bug 961323 - Add a method for finding shortest retaining paths of `JS::ubi::Node` heap graphs; r=jimb (b2d3735d7d) - Bug 1240090 - Make owned copies of filenames in JS::ubi::ByFilename. r=jimb (049ab3c6ed) - Bug 1247412 - Add a reverse method to mozilla::Vector; r=Waldo (ad417ff38b) - Bug 1247413 - Give JS::ubi::BreadthFirst handlers a non-const reference; r=jimb (9baadfa50e) - bit of Bug 1246061 (51b6ef81dc) - Bug 1243198 - Use rvalue references for JS::ubi::ByFilename constructor; r=jimb (5b1dab61a5) - Bug 1216001 part 1 - Optimize nsRange::IsNodeSelected. r=bz (39aad5f0d4) - Bug 1216001 part 2 - Optimize nsRange::ExcludeNonSelectableNodes by counting ignorable whitespace text nodes next to an unselectable node as unselectable too. r=bz (c6589b508e) - Bug 1216001 part 3 - Cache the result of IsSelected() for the duration of painting. r=bz (aa5c000b4c) - Bug 1188364 - Supress GC while transplanting to prevent compacting GC observing intermediate state r=terrence (6963b58989) - Bug 1246318 - Make the proxy enumerate trap non-standard. r=efaust (f34d0a7c2a) - Bug 1254293. Fix dom::GetArrayIndexFromId to actually follow the spec for large indices (i.e. ones that don't fit in in int32_t). r=peterv (b71cffbbbd) - Bug 1256688 - Change BPH::has to follow [[HasProperty]] for ordinary objects. r=jorendorff (39b8de1a3d)
296 lines
8.2 KiB
C++
296 lines
8.2 KiB
C++
/* -*- 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 "mozilla/dom/DOMJSProxyHandler.h"
|
|
#include "xpcpublic.h"
|
|
#include "xpcprivate.h"
|
|
#include "XPCWrapper.h"
|
|
#include "WrapperFactory.h"
|
|
#include "nsDOMClassInfo.h"
|
|
#include "nsWrapperCacheInlines.h"
|
|
#include "mozilla/dom/BindingUtils.h"
|
|
|
|
#include "jsapi.h"
|
|
|
|
using namespace JS;
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
|
|
jsid s_length_id = JSID_VOID;
|
|
|
|
bool
|
|
DefineStaticJSVals(JSContext* cx)
|
|
{
|
|
return AtomizeAndPinJSString(cx, s_length_id, "length");
|
|
}
|
|
|
|
const char DOMProxyHandler::family = 0;
|
|
|
|
js::DOMProxyShadowsResult
|
|
DOMProxyShadows(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id)
|
|
{
|
|
JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
|
|
JS::Value v = js::GetProxyExtra(proxy, JSPROXYSLOT_EXPANDO);
|
|
bool isOverrideBuiltins = !v.isObject() && !v.isUndefined();
|
|
if (expando) {
|
|
bool hasOwn;
|
|
if (!JS_AlreadyHasOwnPropertyById(cx, expando, id, &hasOwn))
|
|
return js::ShadowCheckFailed;
|
|
|
|
if (hasOwn) {
|
|
return isOverrideBuiltins ?
|
|
js::ShadowsViaIndirectExpando : js::ShadowsViaDirectExpando;
|
|
}
|
|
}
|
|
|
|
if (!isOverrideBuiltins) {
|
|
// Our expando, if any, didn't shadow, so we're not shadowing at all.
|
|
return js::DoesntShadow;
|
|
}
|
|
|
|
bool hasOwn;
|
|
if (!GetProxyHandler(proxy)->hasOwn(cx, proxy, id, &hasOwn))
|
|
return js::ShadowCheckFailed;
|
|
|
|
return hasOwn ? js::Shadows : js::DoesntShadowUnique;
|
|
}
|
|
|
|
// Store the information for the specialized ICs.
|
|
struct SetDOMProxyInformation
|
|
{
|
|
SetDOMProxyInformation() {
|
|
js::SetDOMProxyInformation((const void*) &DOMProxyHandler::family,
|
|
JSPROXYSLOT_EXPANDO, DOMProxyShadows);
|
|
}
|
|
};
|
|
|
|
SetDOMProxyInformation gSetDOMProxyInformation;
|
|
|
|
// static
|
|
JSObject*
|
|
DOMProxyHandler::GetAndClearExpandoObject(JSObject* obj)
|
|
{
|
|
MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
|
|
JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
|
if (v.isUndefined()) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (v.isObject()) {
|
|
js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, UndefinedValue());
|
|
xpc::ObjectScope(obj)->RemoveDOMExpandoObject(obj);
|
|
} else {
|
|
js::ExpandoAndGeneration* expandoAndGeneration =
|
|
static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
|
|
v = expandoAndGeneration->expando;
|
|
if (v.isUndefined()) {
|
|
return nullptr;
|
|
}
|
|
expandoAndGeneration->expando = UndefinedValue();
|
|
}
|
|
|
|
|
|
return &v.toObject();
|
|
}
|
|
|
|
// static
|
|
JSObject*
|
|
DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj)
|
|
{
|
|
NS_ASSERTION(IsDOMProxy(obj), "expected a DOM proxy object");
|
|
JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
|
if (v.isObject()) {
|
|
return &v.toObject();
|
|
}
|
|
|
|
js::ExpandoAndGeneration* expandoAndGeneration;
|
|
if (!v.isUndefined()) {
|
|
expandoAndGeneration = static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
|
|
if (expandoAndGeneration->expando.isObject()) {
|
|
return &expandoAndGeneration->expando.toObject();
|
|
}
|
|
} else {
|
|
expandoAndGeneration = nullptr;
|
|
}
|
|
|
|
JS::Rooted<JSObject*> expando(cx,
|
|
JS_NewObjectWithGivenProto(cx, nullptr, nullptr));
|
|
if (!expando) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsISupports* native = UnwrapDOMObject<nsISupports>(obj);
|
|
nsWrapperCache* cache;
|
|
CallQueryInterface(native, &cache);
|
|
if (!cache) {
|
|
return expando;
|
|
}
|
|
|
|
if (expandoAndGeneration) {
|
|
cache->PreserveWrapper(native);
|
|
expandoAndGeneration->expando.setObject(*expando);
|
|
|
|
return expando;
|
|
}
|
|
|
|
if (!xpc::ObjectScope(obj)->RegisterDOMExpandoObject(obj)) {
|
|
return nullptr;
|
|
}
|
|
|
|
cache->SetPreservingWrapper(true);
|
|
js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(*expando));
|
|
|
|
return expando;
|
|
}
|
|
|
|
bool
|
|
DOMProxyHandler::preventExtensions(JSContext* cx, JS::Handle<JSObject*> proxy,
|
|
JS::ObjectOpResult& result) const
|
|
{
|
|
// always extensible per WebIDL
|
|
return result.failCantPreventExtensions();
|
|
}
|
|
|
|
bool
|
|
DOMProxyHandler::isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible) const
|
|
{
|
|
*extensible = true;
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
BaseDOMProxyHandler::getOwnPropertyDescriptor(JSContext* cx,
|
|
JS::Handle<JSObject*> proxy,
|
|
JS::Handle<jsid> id,
|
|
MutableHandle<PropertyDescriptor> desc) const
|
|
{
|
|
return getOwnPropDescriptor(cx, proxy, id, /* ignoreNamedProps = */ false,
|
|
desc);
|
|
}
|
|
|
|
bool
|
|
DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
|
Handle<PropertyDescriptor> desc,
|
|
JS::ObjectOpResult &result, bool *defined) const
|
|
{
|
|
if (desc.hasGetterObject() && desc.setter() == JS_StrictPropertyStub) {
|
|
return result.failGetterOnly();
|
|
}
|
|
|
|
if (xpc::WrapperFactory::IsXrayWrapper(proxy)) {
|
|
return result.succeed();
|
|
}
|
|
|
|
JS::Rooted<JSObject*> expando(cx, EnsureExpandoObject(cx, proxy));
|
|
if (!expando) {
|
|
return false;
|
|
}
|
|
|
|
if (!JS_DefinePropertyById(cx, expando, id, desc, result)) {
|
|
return false;
|
|
}
|
|
*defined = true;
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<jsid> id,
|
|
Handle<JS::Value> v, Handle<JS::Value> receiver,
|
|
ObjectOpResult &result) const
|
|
{
|
|
MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
|
|
"Should not have a XrayWrapper here");
|
|
bool done;
|
|
if (!setCustom(cx, proxy, id, v, &done)) {
|
|
return false;
|
|
}
|
|
if (done) {
|
|
return result.succeed();
|
|
}
|
|
|
|
// Make sure to ignore our named properties when checking for own
|
|
// property descriptors for a set.
|
|
JS::Rooted<PropertyDescriptor> ownDesc(cx);
|
|
if (!getOwnPropDescriptor(cx, proxy, id, /* ignoreNamedProps = */ true,
|
|
&ownDesc)) {
|
|
return false;
|
|
}
|
|
return js::SetPropertyIgnoringNamedGetter(cx, proxy, id, v, receiver, ownDesc, result);
|
|
}
|
|
|
|
bool
|
|
DOMProxyHandler::delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
|
|
JS::Handle<jsid> id, JS::ObjectOpResult &result) const
|
|
{
|
|
JS::Rooted<JSObject*> expando(cx);
|
|
if (!xpc::WrapperFactory::IsXrayWrapper(proxy) && (expando = GetExpandoObject(proxy))) {
|
|
return JS_DeletePropertyById(cx, expando, id, result);
|
|
}
|
|
|
|
return result.succeed();
|
|
}
|
|
|
|
bool
|
|
BaseDOMProxyHandler::watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
|
JS::Handle<JSObject*> callable) const
|
|
{
|
|
return js::WatchGuts(cx, proxy, id, callable);
|
|
}
|
|
|
|
bool
|
|
BaseDOMProxyHandler::unwatch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id) const
|
|
{
|
|
return js::UnwatchGuts(cx, proxy, id);
|
|
}
|
|
|
|
bool
|
|
BaseDOMProxyHandler::ownPropertyKeys(JSContext* cx,
|
|
JS::Handle<JSObject*> proxy,
|
|
JS::AutoIdVector& props) const
|
|
{
|
|
return ownPropNames(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, props);
|
|
}
|
|
|
|
bool
|
|
BaseDOMProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx,
|
|
JS::Handle<JSObject*> proxy,
|
|
JS::AutoIdVector& props) const
|
|
{
|
|
return ownPropNames(cx, proxy, JSITER_OWNONLY, props);
|
|
}
|
|
|
|
bool
|
|
DOMProxyHandler::setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
|
JS::Handle<JS::Value> v, bool *done) const
|
|
{
|
|
*done = false;
|
|
return true;
|
|
}
|
|
|
|
//static
|
|
JSObject *
|
|
DOMProxyHandler::GetExpandoObject(JSObject *obj)
|
|
{
|
|
MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
|
|
JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
|
if (v.isObject()) {
|
|
return &v.toObject();
|
|
}
|
|
|
|
if (v.isUndefined()) {
|
|
return nullptr;
|
|
}
|
|
|
|
js::ExpandoAndGeneration* expandoAndGeneration =
|
|
static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
|
|
v = expandoAndGeneration->expando;
|
|
return v.isUndefined() ? nullptr : &v.toObject();
|
|
}
|
|
|
|
} // namespace dom
|
|
} // namespace mozilla
|