summaryrefslogtreecommitdiffstats
path: root/js/src/proxy/ScriptedProxyHandler.h
blob: 3783467ff383872ce1be2b5967d9ae32f8106216 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* -*- 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/. */

#ifndef proxy_ScriptedProxyHandler_h
#define proxy_ScriptedProxyHandler_h

#include "js/Proxy.h"

namespace js {

/* Derived class for all scripted proxy handlers. */
class ScriptedProxyHandler : public BaseProxyHandler {
 public:
  enum class GetTrapValidationResult {
    OK,
    MustReportSameValue,
    MustReportUndefined,
    Exception,
  };

  constexpr ScriptedProxyHandler() : BaseProxyHandler(&family) {}

  /* Standard internal methods. */
  virtual bool getOwnPropertyDescriptor(
      JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
      JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc)
      const override;
  virtual bool defineProperty(JSContext* cx, JS::HandleObject proxy,
                              JS::HandleId id,
                              JS::Handle<JS::PropertyDescriptor> desc,
                              JS::ObjectOpResult& result) const override;
  virtual bool ownPropertyKeys(JSContext* cx, JS::HandleObject proxy,
                               JS::MutableHandleIdVector props) const override;
  virtual bool delete_(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
                       JS::ObjectOpResult& result) const override;

  virtual bool getPrototype(JSContext* cx, JS::HandleObject proxy,
                            JS::MutableHandleObject protop) const override;
  virtual bool setPrototype(JSContext* cx, JS::HandleObject proxy,
                            JS::HandleObject proto,
                            JS::ObjectOpResult& result) const override;
  /* Non-standard, but needed to correctly implement OrdinaryGetPrototypeOf. */
  virtual bool getPrototypeIfOrdinary(
      JSContext* cx, JS::HandleObject proxy, bool* isOrdinary,
      JS::MutableHandleObject protop) const override;
  /* Non-standard, but needed to handle revoked proxies. */
  virtual bool setImmutablePrototype(JSContext* cx, JS::HandleObject proxy,
                                     bool* succeeded) const override;

  virtual bool preventExtensions(JSContext* cx, JS::HandleObject proxy,
                                 JS::ObjectOpResult& result) const override;
  virtual bool isExtensible(JSContext* cx, JS::HandleObject proxy,
                            bool* extensible) const override;

  virtual bool has(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
                   bool* bp) const override;
  virtual bool get(JSContext* cx, JS::HandleObject proxy,
                   JS::HandleValue receiver, JS::HandleId id,
                   JS::MutableHandleValue vp) const override;
  virtual bool set(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
                   JS::HandleValue v, JS::HandleValue receiver,
                   JS::ObjectOpResult& result) const override;
  virtual bool call(JSContext* cx, JS::HandleObject proxy,
                    const JS::CallArgs& args) const override;
  virtual bool construct(JSContext* cx, JS::HandleObject proxy,
                         const JS::CallArgs& args) const override;

  /* SpiderMonkey extensions. */
  virtual bool hasOwn(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
                      bool* bp) const override {
    return BaseProxyHandler::hasOwn(cx, proxy, id, bp);
  }

  // A scripted proxy should not be treated as generic in most contexts.
  virtual bool nativeCall(JSContext* cx, JS::IsAcceptableThis test,
                          JS::NativeImpl impl,
                          const JS::CallArgs& args) const override;
  virtual bool getBuiltinClass(JSContext* cx, JS::HandleObject proxy,
                               ESClass* cls) const override;
  virtual bool isArray(JSContext* cx, JS::HandleObject proxy,
                       JS::IsArrayAnswer* answer) const override;
  virtual const char* className(JSContext* cx,
                                JS::HandleObject proxy) const override;
  virtual JSString* fun_toString(JSContext* cx, JS::HandleObject proxy,
                                 bool isToSource) const override;
  virtual RegExpShared* regexp_toShared(JSContext* cx,
                                        JS::HandleObject proxy) const override;
  virtual bool boxedValue_unbox(JSContext* cx, JS::HandleObject proxy,
                                JS::MutableHandleValue vp) const override;

  virtual bool isCallable(JSObject* obj) const override;
  virtual bool isConstructor(JSObject* obj) const override;

  virtual bool isScripted() const override { return true; }

  static GetTrapValidationResult checkGetTrapResult(JSContext* cx,
                                                    JS::HandleObject target,
                                                    JS::HandleId id,
                                                    JS::HandleValue trapResult);

  static void reportGetTrapValidationError(JSContext* cx, JS::HandleId id,
                                           GetTrapValidationResult validation);

  static const char family;
  static const ScriptedProxyHandler singleton;

  // The "proxy extra" slot index in which the handler is stored. Revocable
  // proxies need to set this at revocation time.
  static const int HANDLER_EXTRA = 0;
  static const int IS_CALLCONSTRUCT_EXTRA = 1;
  // Bitmasks for the "call/construct" slot
  static const int IS_CALLABLE = 1 << 0;
  static const int IS_CONSTRUCTOR = 1 << 1;
  // The "function extended" slot index in which the revocation object is
  // stored. Per spec, this is to be cleared during the first revocation.
  static const int REVOKE_SLOT = 0;

  static JSObject* handlerObject(const JSObject* proxy);
};

bool proxy(JSContext* cx, unsigned argc, JS::Value* vp);

bool proxy_revocable(JSContext* cx, unsigned argc, JS::Value* vp);

} /* namespace js */

#endif /* proxy_ScriptedProxyHandler_h */