e358b37154494e2ba97262d9306f07357c244849
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSProxy.cpp
1 /*
2  * Copyright (C) 2011-2012, 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JSProxy.h"
28
29 #include "JSGlobalObject.h"
30 #include "JSCInlines.h"
31 #include "PrototypeMapInlines.h"
32
33 namespace JSC {
34
35 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSProxy);
36
37 const ClassInfo JSProxy::s_info = { "JSProxy", &Base::s_info, 0, CREATE_METHOD_TABLE(JSProxy) };
38
39 void JSProxy::visitChildren(JSCell* cell, SlotVisitor& visitor)
40 {
41     JSProxy* thisObject = jsCast<JSProxy*>(cell);
42     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
43     Base::visitChildren(thisObject, visitor);
44     visitor.append(&thisObject->m_target);
45 }
46
47 void JSProxy::setTarget(VM& vm, JSGlobalObject* globalObject)
48 {
49     ASSERT_ARG(globalObject, globalObject);
50     m_target.set(vm, this, globalObject);
51     setPrototypeDirect(vm, globalObject->getPrototypeDirect());
52
53     PrototypeMap& prototypeMap = vm.prototypeMap;
54     if (!prototypeMap.isPrototype(this))
55         return;
56
57     // This is slow but constant time. We think it's very rare for a proxy
58     // to be a prototype, and reasonably rare to retarget a proxy,
59     // so slow constant time is OK.
60     for (size_t i = 0; i <= JSFinalObject::maxInlineCapacity(); ++i)
61         prototypeMap.clearEmptyObjectStructureForPrototype(this, i);
62 }
63
64 String JSProxy::className(const JSObject* object)
65 {
66     const JSProxy* thisObject = jsCast<const JSProxy*>(object);
67     return thisObject->target()->methodTable()->className(thisObject->target());
68 }
69
70 bool JSProxy::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
71 {
72     JSProxy* thisObject = jsCast<JSProxy*>(object);
73     return thisObject->target()->methodTable(exec->vm())->getOwnPropertySlot(thisObject->target(), exec, propertyName, slot);
74 }
75
76 bool JSProxy::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot& slot)
77 {
78     JSProxy* thisObject = jsCast<JSProxy*>(object);
79     return thisObject->target()->methodTable(exec->vm())->getOwnPropertySlotByIndex(thisObject->target(), exec, propertyName, slot);
80 }
81
82 bool JSProxy::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
83 {
84     JSProxy* thisObject = jsCast<JSProxy*>(cell);
85     return thisObject->target()->methodTable(exec->vm())->put(thisObject->target(), exec, propertyName, value, slot);
86 }
87
88 bool JSProxy::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
89 {
90     JSProxy* thisObject = jsCast<JSProxy*>(cell);
91     return thisObject->target()->methodTable(exec->vm())->putByIndex(thisObject->target(), exec, propertyName, value, shouldThrow);
92 }
93
94 bool JSProxy::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
95 {
96     JSProxy* thisObject = jsCast<JSProxy*>(object);
97     return thisObject->target()->methodTable(exec->vm())->defineOwnProperty(thisObject->target(), exec, propertyName, descriptor, shouldThrow);
98 }
99
100 bool JSProxy::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
101 {
102     JSProxy* thisObject = jsCast<JSProxy*>(cell);
103     return thisObject->target()->methodTable(exec->vm())->deleteProperty(thisObject->target(), exec, propertyName);
104 }
105
106 bool JSProxy::preventExtensions(JSObject* object, ExecState* exec)
107 {
108     JSProxy* thisObject = jsCast<JSProxy*>(object);
109     return thisObject->target()->methodTable(exec->vm())->preventExtensions(thisObject->target(), exec);
110 }
111
112 bool JSProxy::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName)
113 {
114     JSProxy* thisObject = jsCast<JSProxy*>(cell);
115     return thisObject->target()->methodTable(exec->vm())->deletePropertyByIndex(thisObject->target(), exec, propertyName);
116 }
117
118 void JSProxy::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
119 {
120     JSProxy* thisObject = jsCast<JSProxy*>(object);
121     thisObject->target()->methodTable(exec->vm())->getPropertyNames(thisObject->target(), exec, propertyNames, mode);
122 }
123
124 uint32_t JSProxy::getEnumerableLength(ExecState* exec, JSObject* object)
125 {
126     JSProxy* thisObject = jsCast<JSProxy*>(object);
127     return thisObject->target()->methodTable(exec->vm())->getEnumerableLength(exec, thisObject->target());
128 }
129
130 void JSProxy::getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
131 {
132     // Skip the structure loop, since it is invalid for proxies.
133 }
134
135 void JSProxy::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
136 {
137     JSProxy* thisObject = jsCast<JSProxy*>(object);
138     // Get *all* of the property names, not just the generic ones, since we skipped the structure
139     // ones above.
140     thisObject->target()->methodTable(exec->vm())->getPropertyNames(thisObject->target(), exec, propertyNames, mode);
141 }
142
143 void JSProxy::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
144 {
145     JSProxy* thisObject = jsCast<JSProxy*>(object);
146     thisObject->target()->methodTable(exec->vm())->getOwnPropertyNames(thisObject->target(), exec, propertyNames, mode);
147 }
148
149 bool JSProxy::setPrototype(JSObject*, ExecState* exec, JSValue, bool shouldThrowIfCantSet)
150 {
151     auto scope = DECLARE_THROW_SCOPE(exec->vm());
152
153     return typeError(exec, scope, shouldThrowIfCantSet, ASCIILiteral("Cannot set prototype of this object"));
154 }
155
156 JSValue JSProxy::getPrototype(JSObject* object, ExecState* exec)
157 {
158     JSProxy* thisObject = jsCast<JSProxy*>(object);
159     return thisObject->target()->methodTable(exec->vm())->getPrototype(thisObject->target(), exec);
160 }
161
162 } // namespace JSC