|
Lines 27-34
Source/JavaScriptCore/runtime/ProxyObject.cpp_sec1
|
| 27 |
#include "ProxyObject.h" |
27 |
#include "ProxyObject.h" |
| 28 |
|
28 |
|
| 29 |
#include "Error.h" |
29 |
#include "Error.h" |
|
|
30 |
#include "IdentifierInlines.h" |
| 30 |
#include "JSCJSValueInlines.h" |
31 |
#include "JSCJSValueInlines.h" |
| 31 |
#include "JSCellInlines.h" |
32 |
#include "JSCellInlines.h" |
|
|
33 |
#include "ObjectConstructor.h" |
| 32 |
#include "SlotVisitorInlines.h" |
34 |
#include "SlotVisitorInlines.h" |
| 33 |
#include "StructureInlines.h" |
35 |
#include "StructureInlines.h" |
| 34 |
|
36 |
|
|
Lines 90-114
static EncodedJSValue performProxyGet(Ex
Source/JavaScriptCore/runtime/ProxyObject.cpp_sec2
|
| 90 |
return throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object.")); |
92 |
return throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object.")); |
| 91 |
|
93 |
|
| 92 |
JSObject* handler = jsCast<JSObject*>(handlerValue); |
94 |
JSObject* handler = jsCast<JSObject*>(handlerValue); |
| 93 |
JSObject* target = proxyObject->target(); |
95 |
CallData callData; |
| 94 |
JSValue getHandler = handler->get(exec, vm.propertyNames->get); |
96 |
CallType callType; |
|
|
97 |
JSValue getHandler = handler->getMethod(exec, callData, callType, vm.propertyNames->get, ASCIILiteral("'get' property of a Proxy's handler object should be callable.")); |
| 95 |
if (exec->hadException()) |
98 |
if (exec->hadException()) |
| 96 |
return JSValue::encode(jsUndefined()); |
99 |
return JSValue::encode(jsUndefined()); |
| 97 |
|
100 |
|
|
|
101 |
JSObject* target = proxyObject->target(); |
| 98 |
if (getHandler.isUndefined()) |
102 |
if (getHandler.isUndefined()) |
| 99 |
return JSValue::encode(target->get(exec, propertyName)); |
103 |
return JSValue::encode(target->get(exec, propertyName)); |
| 100 |
|
104 |
|
| 101 |
if (!getHandler.isCell()) |
|
|
| 102 |
return throwVMTypeError(exec, ASCIILiteral("'get' property of Proxy's handler should be callable.")); |
| 103 |
|
| 104 |
CallData callData; |
| 105 |
CallType callType = getHandler.asCell()->methodTable()->getCallData(getHandler.asCell(), callData); |
| 106 |
if (callType == CallTypeNone) |
| 107 |
return throwVMTypeError(exec, ASCIILiteral("'get' property of Proxy's handler should be callable.")); |
| 108 |
|
| 109 |
MarkedArgumentBuffer arguments; |
105 |
MarkedArgumentBuffer arguments; |
| 110 |
arguments.append(target); |
106 |
arguments.append(target); |
| 111 |
arguments.append(jsString(exec, propertyName.uid())); |
107 |
arguments.append(jsString(exec, propertyName.uid())); |
|
|
108 |
if (exec->hadException()) |
| 109 |
return JSValue::encode(jsUndefined()); |
| 112 |
arguments.append(thisObject); |
110 |
arguments.append(thisObject); |
| 113 |
JSValue trapResult = call(exec, getHandler, callType, callData, handler, arguments); |
111 |
JSValue trapResult = call(exec, getHandler, callType, callData, handler, arguments); |
| 114 |
if (exec->hadException()) |
112 |
if (exec->hadException()) |
|
Lines 125-163
static EncodedJSValue performProxyGet(Ex
Source/JavaScriptCore/runtime/ProxyObject.cpp_sec3
|
| 125 |
} |
123 |
} |
| 126 |
} |
124 |
} |
| 127 |
|
125 |
|
| 128 |
// FIXME: when implementing Proxy.[[GetOwnProperty]] it would be a good test to |
|
|
| 129 |
// have handler be another Proxy where its handler throws on [[GetOwnProperty]] |
| 130 |
// right here. |
| 131 |
// https://bugs.webkit.org/show_bug.cgi?id=154314 |
| 132 |
if (exec->hadException()) |
126 |
if (exec->hadException()) |
| 133 |
return JSValue::encode(jsUndefined()); |
127 |
return JSValue::encode(jsUndefined()); |
| 134 |
|
128 |
|
| 135 |
return JSValue::encode(trapResult); |
129 |
return JSValue::encode(trapResult); |
| 136 |
} |
130 |
} |
| 137 |
|
131 |
|
| 138 |
bool ProxyObject::getOwnPropertySlotCommon(ExecState*, PropertySlot& slot) |
132 |
bool ProxyObject::performInternalMethodGetOwnProperty(ExecState* exec, PropertyName propertyName, PropertySlot& slot) |
|
|
133 |
{ |
| 134 |
VM& vm = exec->vm(); |
| 135 |
slot.setValue(this, None, jsUndefined()); // We do this to protect against any bad actors. Nobody should depend on this value. |
| 136 |
JSValue handlerValue = this->handler(); |
| 137 |
if (handlerValue.isNull()) { |
| 138 |
throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object.")); |
| 139 |
return false; |
| 140 |
} |
| 141 |
|
| 142 |
JSObject* handler = jsCast<JSObject*>(handlerValue); |
| 143 |
CallData callData; |
| 144 |
CallType callType; |
| 145 |
JSValue getOwnPropertyDescriptorMethod = handler->getMethod(exec, callData, callType, makeIdentifier(vm, "getOwnPropertyDescriptor"), ASCIILiteral("'getOwnPropertyDescriptor' property of a Proxy's handler should be callable.")); |
| 146 |
JSObject* target = this->target(); |
| 147 |
if (getOwnPropertyDescriptorMethod.isUndefined()) |
| 148 |
return target->methodTable(vm)->getOwnPropertySlot(target, exec, propertyName, slot); |
| 149 |
|
| 150 |
MarkedArgumentBuffer arguments; |
| 151 |
arguments.append(target); |
| 152 |
arguments.append(jsString(exec, propertyName.uid())); |
| 153 |
if (exec->hadException()) |
| 154 |
return false; |
| 155 |
JSValue trapResult = call(exec, getOwnPropertyDescriptorMethod, callType, callData, handler, arguments); |
| 156 |
if (exec->hadException()) |
| 157 |
return false; |
| 158 |
|
| 159 |
if (!trapResult.isUndefined() && !trapResult.isObject()) { |
| 160 |
throwVMTypeError(exec, ASCIILiteral("result of 'getOwnPropertyDescriptor' call should either be an Object or undefined.")); |
| 161 |
return false; |
| 162 |
} |
| 163 |
|
| 164 |
PropertyDescriptor targetPropertyDescriptor; |
| 165 |
bool isTargetPropertyDescriptorDefined = target->getOwnPropertyDescriptor(exec, propertyName, targetPropertyDescriptor); |
| 166 |
if (exec->hadException()) |
| 167 |
return false; |
| 168 |
|
| 169 |
if (trapResult.isUndefined()) { |
| 170 |
if (!isTargetPropertyDescriptorDefined) |
| 171 |
return false; |
| 172 |
if (!targetPropertyDescriptor.configurable()) { |
| 173 |
throwVMTypeError(exec, ASCIILiteral("When the result of 'getOwnPropertyDescriptor' is undefined the target must be configurable.")); |
| 174 |
return false; |
| 175 |
} |
| 176 |
// FIXME: this doesn't work if 'target' is another Proxy. We don't have isExtensible implemented in a way that fits w/ Proxys. |
| 177 |
// https://bugs.webkit.org/show_bug.cgi?id=154375 |
| 178 |
if (!target->isExtensible()) { |
| 179 |
// FIXME: Come up with a test for this error. I'm not sure how to because |
| 180 |
// Object.seal(o) will make all fields [[Configurable]] false. |
| 181 |
// https://bugs.webkit.org/show_bug.cgi?id=154376 |
| 182 |
throwVMTypeError(exec, ASCIILiteral("When 'getOwnPropertyDescriptor' returns undefined, the 'target' of a Proxy should be extensible.")); |
| 183 |
return false; |
| 184 |
} |
| 185 |
|
| 186 |
return false; |
| 187 |
} |
| 188 |
|
| 189 |
PropertyDescriptor trapResultAsDescriptor; |
| 190 |
toPropertyDescriptor(exec, trapResult, trapResultAsDescriptor); |
| 191 |
if (exec->hadException()) |
| 192 |
return false; |
| 193 |
// FIXME: implement step 14. CompletePropertyDescriptor(trapResultAsDescriptor) in the spec. Maybe this is already done? |
| 194 |
bool throwException = false; |
| 195 |
bool valid = validateAndApplyPropertyDescriptor(exec, nullptr, propertyName, target->isExtensible(), |
| 196 |
trapResultAsDescriptor, isTargetPropertyDescriptorDefined, targetPropertyDescriptor, throwException); |
| 197 |
if (!valid) { |
| 198 |
throwVMTypeError(exec, ASCIILiteral("Result from 'getOwnPropertyDescriptor' fails the IsCompatiblePropertyDescriptor test.")); |
| 199 |
return false; |
| 200 |
} |
| 201 |
|
| 202 |
if (!trapResultAsDescriptor.configurable()) { |
| 203 |
if (!isTargetPropertyDescriptorDefined || targetPropertyDescriptor.configurable()) { |
| 204 |
throwVMTypeError(exec, ASCIILiteral("Result from 'getOwnPropertyDescriptor' can't be non-configurable when the 'target' doesn't have it as an own property or if it is a configurable own property on 'target'.")); |
| 205 |
return false; |
| 206 |
} |
| 207 |
} |
| 208 |
|
| 209 |
return true; |
| 210 |
} |
| 211 |
|
| 212 |
bool ProxyObject::getOwnPropertySlotCommon(ExecState* exec, PropertyName propertyName, PropertySlot& slot) |
| 139 |
{ |
213 |
{ |
| 140 |
if (slot.internalMethodType() == PropertySlot::InternalMethodType::Get) { |
214 |
switch (slot.internalMethodType()) { |
|
|
215 |
case PropertySlot::InternalMethodType::Get: |
| 141 |
slot.setCustom(this, CustomAccessor, performProxyGet); |
216 |
slot.setCustom(this, CustomAccessor, performProxyGet); |
| 142 |
slot.disableCaching(); |
217 |
slot.disableCaching(); |
| 143 |
return true; |
218 |
return true; |
|
|
219 |
case PropertySlot::InternalMethodType::GetOwnProperty: |
| 220 |
return performInternalMethodGetOwnProperty(exec, propertyName, slot); |
| 221 |
default: |
| 222 |
// FIXME: Implement Proxy.[[HasProperty]]. |
| 223 |
// https://bugs.webkit.org/show_bug.cgi?id=154313 |
| 224 |
return false; |
| 144 |
} |
225 |
} |
| 145 |
|
226 |
|
| 146 |
// FIXME: Implement Proxy.[[HasProperty]] and Proxy.[[GetOwnProperty]] |
227 |
RELEASE_ASSERT_NOT_REACHED(); |
| 147 |
// https://bugs.webkit.org/show_bug.cgi?id=154313 |
|
|
| 148 |
// https://bugs.webkit.org/show_bug.cgi?id=154314 |
| 149 |
return false; |
228 |
return false; |
| 150 |
} |
229 |
} |
| 151 |
bool ProxyObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName, PropertySlot& slot) |
230 |
|
|
|
231 |
bool ProxyObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) |
| 152 |
{ |
232 |
{ |
| 153 |
ProxyObject* thisObject = jsCast<ProxyObject*>(object); |
233 |
ProxyObject* thisObject = jsCast<ProxyObject*>(object); |
| 154 |
return thisObject->getOwnPropertySlotCommon(exec, slot); |
234 |
return thisObject->getOwnPropertySlotCommon(exec, propertyName, slot); |
| 155 |
} |
235 |
} |
| 156 |
|
236 |
|
| 157 |
bool ProxyObject::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned, PropertySlot& slot) |
237 |
bool ProxyObject::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot& slot) |
| 158 |
{ |
238 |
{ |
| 159 |
ProxyObject* thisObject = jsCast<ProxyObject*>(object); |
239 |
ProxyObject* thisObject = jsCast<ProxyObject*>(object); |
| 160 |
return thisObject->getOwnPropertySlotCommon(exec, slot); |
240 |
Identifier ident = Identifier::from(exec, propertyName); |
|
|
241 |
if (exec->hadException()) |
| 242 |
return false; |
| 243 |
return thisObject->getOwnPropertySlotCommon(exec, ident.impl(), slot); |
| 161 |
} |
244 |
} |
| 162 |
|
245 |
|
| 163 |
void ProxyObject::visitChildren(JSCell* cell, SlotVisitor& visitor) |
246 |
void ProxyObject::visitChildren(JSCell* cell, SlotVisitor& visitor) |