diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/runtime/ProxyObject.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/runtime/ProxyObject.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/ProxyObject.cpp | 311 |
1 files changed, 0 insertions, 311 deletions
diff --git a/Source/JavaScriptCore/runtime/ProxyObject.cpp b/Source/JavaScriptCore/runtime/ProxyObject.cpp deleted file mode 100644 index 6ea856d73..000000000 --- a/Source/JavaScriptCore/runtime/ProxyObject.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (C) 2016 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ProxyObject.h" - -#include "Error.h" -#include "IdentifierInlines.h" -#include "JSCJSValueInlines.h" -#include "JSCellInlines.h" -#include "ObjectConstructor.h" -#include "SlotVisitorInlines.h" -#include "StructureInlines.h" - -namespace JSC { - -STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ProxyObject); - -const ClassInfo ProxyObject::s_info = { "ProxyObject", &Base::s_info, 0, CREATE_METHOD_TABLE(ProxyObject) }; - -ProxyObject::ProxyObject(VM& vm, Structure* structure) - : Base(vm, structure) -{ -} - -void ProxyObject::finishCreation(VM& vm, ExecState* exec, JSValue target, JSValue handler) -{ - Base::finishCreation(vm); - if (!target.isObject()) { - throwTypeError(exec, ASCIILiteral("A Proxy's 'target' should be an Object")); - return; - } - if (ProxyObject* targetAsProxy = jsDynamicCast<ProxyObject*>(target)) { - // FIXME: Add tests for this once we implement Proxy.revoke(.). - // https://bugs.webkit.org/show_bug.cgi?id=154321 - if (targetAsProxy->handler().isNull()) { - throwTypeError(exec, ASCIILiteral("If a Proxy's handler is another Proxy object, the other Proxy object must have a non-null handler.")); - return; - } - } - if (!handler.isObject()) { - throwTypeError(exec, ASCIILiteral("A Proxy's 'handler' should be an Object")); - return; - } - - m_target.set(vm, this, jsCast<JSObject*>(target)); - m_handler.set(vm, this, handler); -} - -static EncodedJSValue performProxyGet(ExecState* exec, EncodedJSValue thisValue, PropertyName propertyName) -{ - VM& vm = exec->vm(); - JSObject* thisObject = jsCast<JSObject*>(JSValue::decode(thisValue)); // This might be a value where somewhere in __proto__ chain lives a ProxyObject. - JSObject* proxyObjectAsObject = thisObject; - // FIXME: make it so that custom getters take both the |this| value and the slotBase (property holder). - // https://bugs.webkit.org/show_bug.cgi?id=154320 - while (true) { - if (LIKELY(proxyObjectAsObject->inherits(ProxyObject::info()))) - break; - - Structure& structure = *vm.heap.structureIDTable().get(proxyObjectAsObject->structureID()); - JSValue prototype = structure.storedPrototype(); - RELEASE_ASSERT(prototype.isObject()); - proxyObjectAsObject = asObject(prototype); - } - - ProxyObject* proxyObject = jsCast<ProxyObject*>(proxyObjectAsObject); - JSValue handlerValue = proxyObject->handler(); - if (handlerValue.isNull()) - return throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object.")); - - JSObject* handler = jsCast<JSObject*>(handlerValue); - CallData callData; - CallType callType; - JSValue getHandler = handler->getMethod(exec, callData, callType, vm.propertyNames->get, ASCIILiteral("'get' property of a Proxy's handler object should be callable.")); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - JSObject* target = proxyObject->target(); - if (getHandler.isUndefined()) - return JSValue::encode(target->get(exec, propertyName)); - - MarkedArgumentBuffer arguments; - arguments.append(target); - arguments.append(identifierToSafePublicJSValue(vm, Identifier::fromUid(&vm, propertyName.uid()))); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - arguments.append(thisObject); - JSValue trapResult = call(exec, getHandler, callType, callData, handler, arguments); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - PropertyDescriptor descriptor; - if (target->getOwnPropertyDescriptor(exec, propertyName, descriptor)) { - if (descriptor.isDataDescriptor() && !descriptor.configurable() && !descriptor.writable()) { - if (!sameValue(exec, descriptor.value(), trapResult)) - return throwVMTypeError(exec, ASCIILiteral("Proxy handler's 'get' result of a non-configurable and non-writable property should be the same value as the target's property.")); - } else if (descriptor.isAccessorDescriptor() && !descriptor.configurable() && descriptor.getter().isUndefined()) { - if (!trapResult.isUndefined()) - return throwVMTypeError(exec, ASCIILiteral("Proxy handler's 'get' result of a non-configurable accessor property without a getter should be undefined.")); - } - } - - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - return JSValue::encode(trapResult); -} - -bool ProxyObject::performInternalMethodGetOwnProperty(ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - VM& vm = exec->vm(); - slot.setValue(this, None, jsUndefined()); // We do this to protect against any bad actors. Nobody should depend on this value. - JSValue handlerValue = this->handler(); - if (handlerValue.isNull()) { - throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object.")); - return false; - } - - JSObject* handler = jsCast<JSObject*>(handlerValue); - CallData callData; - CallType callType; - JSValue getOwnPropertyDescriptorMethod = handler->getMethod(exec, callData, callType, makeIdentifier(vm, "getOwnPropertyDescriptor"), ASCIILiteral("'getOwnPropertyDescriptor' property of a Proxy's handler should be callable.")); - if (exec->hadException()) - return false; - JSObject* target = this->target(); - if (getOwnPropertyDescriptorMethod.isUndefined()) - return target->methodTable(vm)->getOwnPropertySlot(target, exec, propertyName, slot); - - MarkedArgumentBuffer arguments; - arguments.append(target); - arguments.append(identifierToSafePublicJSValue(vm, Identifier::fromUid(&vm, propertyName.uid()))); - if (exec->hadException()) - return false; - JSValue trapResult = call(exec, getOwnPropertyDescriptorMethod, callType, callData, handler, arguments); - if (exec->hadException()) - return false; - - if (!trapResult.isUndefined() && !trapResult.isObject()) { - throwVMTypeError(exec, ASCIILiteral("result of 'getOwnPropertyDescriptor' call should either be an Object or undefined.")); - return false; - } - - PropertyDescriptor targetPropertyDescriptor; - bool isTargetPropertyDescriptorDefined = target->getOwnPropertyDescriptor(exec, propertyName, targetPropertyDescriptor); - if (exec->hadException()) - return false; - - if (trapResult.isUndefined()) { - if (!isTargetPropertyDescriptorDefined) - return false; - if (!targetPropertyDescriptor.configurable()) { - throwVMTypeError(exec, ASCIILiteral("When the result of 'getOwnPropertyDescriptor' is undefined the target must be configurable.")); - return false; - } - // FIXME: this doesn't work if 'target' is another Proxy. We don't have isExtensible implemented in a way that fits w/ Proxys. - // https://bugs.webkit.org/show_bug.cgi?id=154375 - if (!target->isExtensible()) { - // FIXME: Come up with a test for this error. I'm not sure how to because - // Object.seal(o) will make all fields [[Configurable]] false. - // https://bugs.webkit.org/show_bug.cgi?id=154376 - throwVMTypeError(exec, ASCIILiteral("When 'getOwnPropertyDescriptor' returns undefined, the 'target' of a Proxy should be extensible.")); - return false; - } - - return false; - } - - PropertyDescriptor trapResultAsDescriptor; - toPropertyDescriptor(exec, trapResult, trapResultAsDescriptor); - if (exec->hadException()) - return false; - bool throwException = false; - bool valid = validateAndApplyPropertyDescriptor(exec, nullptr, propertyName, target->isExtensible(), - trapResultAsDescriptor, isTargetPropertyDescriptorDefined, targetPropertyDescriptor, throwException); - if (!valid) { - throwVMTypeError(exec, ASCIILiteral("Result from 'getOwnPropertyDescriptor' fails the IsCompatiblePropertyDescriptor test.")); - return false; - } - - if (!trapResultAsDescriptor.configurable()) { - if (!isTargetPropertyDescriptorDefined || targetPropertyDescriptor.configurable()) { - 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'.")); - return false; - } - } - - return true; -} - -bool ProxyObject::performHasProperty(ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - VM& vm = exec->vm(); - slot.setValue(this, None, jsUndefined()); // Nobody should rely on our value, but be safe and protect against any bad actors reading our value. - - JSValue handlerValue = this->handler(); - if (handlerValue.isNull()) { - throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object.")); - return false; - } - - JSObject* handler = jsCast<JSObject*>(handlerValue); - CallData callData; - CallType callType; - JSValue hasMethod = handler->getMethod(exec, callData, callType, vm.propertyNames->has, ASCIILiteral("'has' property of a Proxy's handler should be callable.")); - if (exec->hadException()) - return false; - JSObject* target = this->target(); - if (hasMethod.isUndefined()) - return target->methodTable(vm)->getOwnPropertySlot(target, exec, propertyName, slot); - - MarkedArgumentBuffer arguments; - arguments.append(target); - arguments.append(identifierToSafePublicJSValue(vm, Identifier::fromUid(&vm, propertyName.uid()))); - if (exec->hadException()) - return false; - JSValue trapResult = call(exec, hasMethod, callType, callData, handler, arguments); - if (exec->hadException()) - return false; - - bool trapResultAsBool = trapResult.toBoolean(exec); - if (exec->hadException()) - return false; - - if (!trapResultAsBool) { - PropertyDescriptor descriptor; - bool isPropertyDescriptorDefined = target->getOwnPropertyDescriptor(exec, propertyName, descriptor); - if (exec->hadException()) - return false; - if (isPropertyDescriptorDefined) { - if (!descriptor.configurable()) { - throwVMTypeError(exec, ASCIILiteral("Proxy 'has' must return 'true' for non-configurable properties.")); - return false; - } - if (!target->isExtensible()) { - throwVMTypeError(exec, ASCIILiteral("Proxy 'has' must return 'true' for a non-extensible 'target' object with a configurable property.")); - return false; - } - } - } - - return trapResultAsBool; -} - -bool ProxyObject::getOwnPropertySlotCommon(ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - slot.disableCaching(); - switch (slot.internalMethodType()) { - case PropertySlot::InternalMethodType::Get: - slot.setCustom(this, CustomAccessor, performProxyGet); - return true; - case PropertySlot::InternalMethodType::GetOwnProperty: - return performInternalMethodGetOwnProperty(exec, propertyName, slot); - case PropertySlot::InternalMethodType::HasProperty: - return performHasProperty(exec, propertyName, slot); - default: - return false; - } - - RELEASE_ASSERT_NOT_REACHED(); - return false; -} - -bool ProxyObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - ProxyObject* thisObject = jsCast<ProxyObject*>(object); - return thisObject->getOwnPropertySlotCommon(exec, propertyName, slot); -} - -bool ProxyObject::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot& slot) -{ - ProxyObject* thisObject = jsCast<ProxyObject*>(object); - Identifier ident = Identifier::from(exec, propertyName); - if (exec->hadException()) - return false; - return thisObject->getOwnPropertySlotCommon(exec, ident.impl(), slot); -} - -void ProxyObject::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - ProxyObject* thisObject = jsCast<ProxyObject*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - Base::visitChildren(thisObject, visitor); - - visitor.append(&thisObject->m_target); - visitor.append(&thisObject->m_handler); -} - -} // namespace JSC |