1/*
2 * Copyright (C) 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#pragma once
27
28#include "JSGlobalObject.h"
29#include "JSObject.h"
30
31namespace JSC {
32
33class ProxyObject final : public JSNonFinalObject {
34public:
35 typedef JSNonFinalObject Base;
36
37 const static unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetCallData | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | ProhibitsPropertyCaching;
38
39 static ProxyObject* create(ExecState* exec, JSGlobalObject* globalObject, JSValue target, JSValue handler)
40 {
41 VM& vm = exec->vm();
42 Structure* structure = ProxyObject::structureForTarget(globalObject, target);
43 ProxyObject* proxy = new (NotNull, allocateCell<ProxyObject>(vm.heap)) ProxyObject(vm, structure);
44 proxy->finishCreation(vm, exec, target, handler);
45 return proxy;
46 }
47
48 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, bool isCallable)
49 {
50 unsigned flags = StructureFlags;
51 if (isCallable)
52 flags |= (ImplementsHasInstance | ImplementsDefaultHasInstance);
53 Structure* result = Structure::create(vm, globalObject, prototype, TypeInfo(ProxyObjectType, flags), info(), NonArray | MayHaveIndexedAccessors);
54 result->setIsQuickPropertyAccessAllowedForEnumeration(false);
55 RELEASE_ASSERT(!result->canAccessPropertiesQuicklyForEnumeration());
56 RELEASE_ASSERT(!result->canCachePropertyNameEnumerator());
57 return result;
58 }
59
60 DECLARE_EXPORT_INFO;
61
62 JSObject* target() const { return m_target.get(); }
63 JSValue handler() const { return m_handler.get(); }
64
65 static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
66 static bool putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
67 bool putByIndexCommon(ExecState*, JSValue thisValue, unsigned propertyName, JSValue putValue, bool shouldThrow);
68 JSValue performGetPrototype(ExecState*);
69 void revoke(VM&);
70 bool isRevoked() const;
71
72private:
73 JS_EXPORT_PRIVATE ProxyObject(VM&, Structure*);
74 JS_EXPORT_PRIVATE void finishCreation(VM&, ExecState*, JSValue target, JSValue handler);
75 JS_EXPORT_PRIVATE static Structure* structureForTarget(JSGlobalObject*, JSValue target);
76
77 static String toStringName(const JSObject*, ExecState*);
78 static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
79 static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&);
80 static CallType getCallData(JSCell*, CallData&);
81 static ConstructType getConstructData(JSCell*, ConstructData&);
82 static bool deleteProperty(JSCell*, ExecState*, PropertyName);
83 static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
84 static bool preventExtensions(JSObject*, ExecState*);
85 static bool isExtensible(JSObject*, ExecState*);
86 static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
87 static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
88 static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
89 static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
90 static NO_RETURN_DUE_TO_CRASH void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
91 static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
92 static bool setPrototype(JSObject*, ExecState*, JSValue prototype, bool shouldThrowIfCantSet);
93 static JSValue getPrototype(JSObject*, ExecState*);
94 static void visitChildren(JSCell*, SlotVisitor&);
95
96 bool getOwnPropertySlotCommon(ExecState*, PropertyName, PropertySlot&);
97 bool performInternalMethodGetOwnProperty(ExecState*, PropertyName, PropertySlot&);
98 bool performGet(ExecState*, PropertyName, PropertySlot&);
99 bool performHasProperty(ExecState*, PropertyName, PropertySlot&);
100 template <typename DefaultDeleteFunction>
101 bool performDelete(ExecState*, PropertyName, DefaultDeleteFunction);
102 template <typename PerformDefaultPutFunction>
103 bool performPut(ExecState*, JSValue putValue, JSValue thisValue, PropertyName, PerformDefaultPutFunction, bool shouldThrow);
104 bool performPreventExtensions(ExecState*);
105 bool performIsExtensible(ExecState*);
106 bool performDefineOwnProperty(ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
107 void performGetOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode);
108 bool performSetPrototype(ExecState*, JSValue prototype, bool shouldThrowIfCantSet);
109
110 WriteBarrier<JSObject> m_target;
111 WriteBarrier<Unknown> m_handler;
112 bool m_isCallable : 1;
113 bool m_isConstructible : 1;
114};
115
116} // namespace JSC
117