dom/bindings/DOMJSProxyHandler.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     4  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef mozilla_dom_DOMJSProxyHandler_h
     7 #define mozilla_dom_DOMJSProxyHandler_h
     9 #include "mozilla/Attributes.h"
    10 #include "mozilla/Likely.h"
    12 #include "jsapi.h"
    13 #include "jsproxy.h"
    14 #include "nsString.h"
    16 #define DOM_PROXY_OBJECT_SLOT js::PROXY_PRIVATE_SLOT
    18 namespace mozilla {
    19 namespace dom {
    21 class DOMClass;
    23 enum {
    24   JSPROXYSLOT_EXPANDO = 0
    25 };
    27 template<typename T> struct Prefable;
    29 // This variable exists solely to provide a unique address for use as an identifier.
    30 extern const char HandlerFamily;
    31 inline const void* ProxyFamily() { return &HandlerFamily; }
    33 inline bool IsDOMProxy(JSObject *obj)
    34 {
    35     const js::Class* clasp = js::GetObjectClass(obj);
    36     return clasp->isProxy() &&
    37            js::GetProxyHandler(obj)->family() == ProxyFamily();
    38 }
    40 class BaseDOMProxyHandler : public js::BaseProxyHandler
    41 {
    42 public:
    43   BaseDOMProxyHandler(const void* aProxyFamily)
    44     : js::BaseProxyHandler(aProxyFamily)
    45   {}
    47   // Implementations of traps that can be implemented in terms of
    48   // fundamental traps.
    49   bool enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
    50                  JS::AutoIdVector& props) MOZ_OVERRIDE;
    51   bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
    52                              JS::Handle<jsid> id,
    53                              JS::MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
    54   bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
    55                                 JS::Handle<jsid> id,
    56                                 JS::MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
    58   bool watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
    59              JS::Handle<JSObject*> callable) MOZ_OVERRIDE;
    60   bool unwatch(JSContext* cx, JS::Handle<JSObject*> proxy,
    61                JS::Handle<jsid> id) MOZ_OVERRIDE;
    62   virtual bool getOwnPropertyNames(JSContext* cx, JS::Handle<JSObject*> proxy,
    63                                    JS::AutoIdVector &props) MOZ_OVERRIDE;
    64   // We override keys() and implement it directly instead of using the
    65   // default implementation, which would getOwnPropertyNames and then
    66   // filter out the non-enumerable ones.  This avoids doing
    67   // unnecessary work during enumeration.
    68   virtual bool keys(JSContext* cx, JS::Handle<JSObject*> proxy,
    69                     JS::AutoIdVector &props) MOZ_OVERRIDE;
    71 protected:
    72   // Hook for subclasses to implement shared getOwnPropertyNames()/keys()
    73   // functionality.  The "flags" argument is either JSITER_OWNONLY (for keys())
    74   // or JSITER_OWNONLY | JSITER_HIDDEN (for getOwnPropertyNames()).
    75   virtual bool ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy,
    76                             unsigned flags,
    77                             JS::AutoIdVector& props) = 0;
    79   // Hook for subclasses to allow set() to ignore named props while other things
    80   // that look at property descriptors see them.  This is intentionally not
    81   // named getOwnPropertyDescriptor to avoid subclasses that override it hiding
    82   // our public getOwnPropertyDescriptor.
    83   virtual bool getOwnPropDescriptor(JSContext* cx,
    84                                     JS::Handle<JSObject*> proxy,
    85                                     JS::Handle<jsid> id,
    86                                     bool ignoreNamedProps,
    87                                     JS::MutableHandle<JSPropertyDescriptor> desc) = 0;
    88 };
    90 class DOMProxyHandler : public BaseDOMProxyHandler
    91 {
    92 public:
    93   DOMProxyHandler()
    94     : BaseDOMProxyHandler(ProxyFamily())
    95   {
    96   }
    98   bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy) MOZ_OVERRIDE;
    99   bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
   100                       JS::MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE
   101   {
   102     bool unused;
   103     return defineProperty(cx, proxy, id, desc, &unused);
   104   }
   105   virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
   106                               JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined);
   107   bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
   108            JS::Handle<jsid> id, bool strict, JS::MutableHandle<JS::Value> vp) MOZ_OVERRIDE;
   109   bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
   110                JS::Handle<jsid> id, bool* bp) MOZ_OVERRIDE;
   111   bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) MOZ_OVERRIDE;
   112   bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible) MOZ_OVERRIDE;
   114   /*
   115    * If assigning to proxy[id] hits a named setter with OverrideBuiltins or
   116    * an indexed setter, call it and set *done to true on success. Otherwise, set
   117    * *done to false.
   118    */
   119   virtual bool setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
   120                          JS::MutableHandle<JS::Value> vp, bool *done);
   122   static JSObject* GetExpandoObject(JSObject* obj)
   123   {
   124     MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
   125     JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
   126     if (v.isObject()) {
   127       return &v.toObject();
   128     }
   130     if (v.isUndefined()) {
   131       return nullptr;
   132     }
   134     js::ExpandoAndGeneration* expandoAndGeneration =
   135       static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
   136     v = expandoAndGeneration->expando;
   137     return v.isUndefined() ? nullptr : &v.toObject();
   138   }
   139   /* GetAndClearExpandoObject does not DROP or clear the preserving wrapper flag. */
   140   static JSObject* GetAndClearExpandoObject(JSObject* obj);
   141   static JSObject* EnsureExpandoObject(JSContext* cx,
   142                                        JS::Handle<JSObject*> obj);
   143 };
   145 inline DOMProxyHandler*
   146 GetDOMProxyHandler(JSObject* obj)
   147 {
   148   MOZ_ASSERT(IsDOMProxy(obj));
   149   return static_cast<DOMProxyHandler*>(js::GetProxyHandler(obj));
   150 }
   152 extern jsid s_length_id;
   154 int32_t IdToInt32(JSContext* cx, JS::Handle<jsid> id);
   156 // XXXbz this should really return uint32_t, with the maximum value
   157 // meaning "not an index"...
   158 inline int32_t
   159 GetArrayIndexFromId(JSContext* cx, JS::Handle<jsid> id)
   160 {
   161   if (MOZ_LIKELY(JSID_IS_INT(id))) {
   162     return JSID_TO_INT(id);
   163   }
   164   if (MOZ_LIKELY(id == s_length_id)) {
   165     return -1;
   166   }
   167   if (MOZ_LIKELY(JSID_IS_ATOM(id))) {
   168     JSAtom* atom = JSID_TO_ATOM(id);
   169     jschar s = *js::GetAtomChars(atom);
   170     if (MOZ_LIKELY((unsigned)s >= 'a' && (unsigned)s <= 'z'))
   171       return -1;
   173     uint32_t i;
   174     JSLinearString* str = js::AtomToLinearString(JSID_TO_ATOM(id));
   175     return js::StringIsArrayIndex(str, &i) ? i : -1;
   176   }
   177   return IdToInt32(cx, id);
   178 }
   180 inline bool
   181 IsArrayIndex(int32_t index)
   182 {
   183   return index >= 0;
   184 }
   186 inline void
   187 FillPropertyDescriptor(JS::MutableHandle<JSPropertyDescriptor> desc,
   188                        JSObject* obj, bool readonly, bool enumerable = true)
   189 {
   190   desc.object().set(obj);
   191   desc.setAttributes((readonly ? JSPROP_READONLY : 0) |
   192                      (enumerable ? JSPROP_ENUMERATE : 0));
   193   desc.setGetter(nullptr);
   194   desc.setSetter(nullptr);
   195 }
   197 inline void
   198 FillPropertyDescriptor(JS::MutableHandle<JSPropertyDescriptor> desc,
   199                        JSObject* obj, JS::Value v,
   200                        bool readonly, bool enumerable = true)
   201 {
   202   desc.value().set(v);
   203   FillPropertyDescriptor(desc, obj, readonly, enumerable);
   204 }
   206 inline void
   207 FillPropertyDescriptor(JS::MutableHandle<JSPropertyDescriptor> desc,
   208                        JSObject* obj, unsigned attributes, JS::Value v)
   209 {
   210   desc.object().set(obj);
   211   desc.value().set(v);
   212   desc.setAttributes(attributes);
   213   desc.setGetter(nullptr);
   214   desc.setSetter(nullptr);
   215 }
   217 } // namespace dom
   218 } // namespace mozilla
   220 #endif /* mozilla_dom_DOMProxyHandler_h */

mercurial