1/*
2 * Copyright (C) 2003-2018 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. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "runtime_method.h"
28
29#include "JSDOMBinding.h"
30#include "JSHTMLElement.h"
31#include "JSPluginElementFunctions.h"
32#include "WebCoreJSClientData.h"
33#include "runtime_object.h"
34#include <JavaScriptCore/Error.h>
35#include <JavaScriptCore/FunctionPrototype.h>
36
37using namespace WebCore;
38
39namespace JSC {
40
41using namespace Bindings;
42
43WEBCORE_EXPORT const ClassInfo RuntimeMethod::s_info = { "RuntimeMethod", &InternalFunction::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(RuntimeMethod) };
44
45static EncodedJSValue JSC_HOST_CALL callRuntimeMethod(ExecState*);
46
47RuntimeMethod::RuntimeMethod(JSGlobalObject* globalObject, Structure* structure, Method* method)
48 // Callers will need to pass in the right global object corresponding to this native object "method".
49 : InternalFunction(globalObject->vm(), structure, callRuntimeMethod, nullptr)
50 , m_method(method)
51{
52}
53
54void RuntimeMethod::finishCreation(VM& vm, const String& ident)
55{
56 Base::finishCreation(vm, ident);
57 ASSERT(inherits(vm, info()));
58}
59
60EncodedJSValue RuntimeMethod::lengthGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
61{
62 VM& vm = exec->vm();
63 auto scope = DECLARE_THROW_SCOPE(vm);
64
65 RuntimeMethod* thisObject = jsDynamicCast<RuntimeMethod*>(vm, JSValue::decode(thisValue));
66 if (!thisObject)
67 return throwVMTypeError(exec, scope);
68 return JSValue::encode(jsNumber(thisObject->m_method->numParameters()));
69}
70
71bool RuntimeMethod::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
72{
73 VM& vm = exec->vm();
74 RuntimeMethod* thisObject = jsCast<RuntimeMethod*>(object);
75 if (propertyName == vm.propertyNames->length) {
76 slot.setCacheableCustom(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, thisObject->lengthGetter);
77 return true;
78 }
79
80 return InternalFunction::getOwnPropertySlot(thisObject, exec, propertyName, slot);
81}
82
83IsoSubspace* RuntimeMethod::subspaceForImpl(VM& vm)
84{
85 return &static_cast<JSVMClientData*>(vm.clientData)->runtimeMethodSpace();
86}
87
88static EncodedJSValue JSC_HOST_CALL callRuntimeMethod(ExecState* exec)
89{
90 VM& vm = exec->vm();
91 auto scope = DECLARE_THROW_SCOPE(vm);
92
93 RuntimeMethod* method = static_cast<RuntimeMethod*>(exec->jsCallee());
94
95 if (!method->method())
96 return JSValue::encode(jsUndefined());
97
98 RefPtr<Instance> instance;
99
100 JSValue thisValue = exec->thisValue();
101 if (thisValue.inherits<RuntimeObject>(vm)) {
102 RuntimeObject* runtimeObject = static_cast<RuntimeObject*>(asObject(thisValue));
103 instance = runtimeObject->getInternalInstance();
104 if (!instance)
105 return JSValue::encode(RuntimeObject::throwInvalidAccessError(exec, scope));
106 } else {
107 // Calling a runtime object of a plugin element?
108 if (thisValue.inherits<JSHTMLElement>(vm))
109 instance = pluginInstance(jsCast<JSHTMLElement*>(asObject(thisValue))->wrapped());
110 if (!instance)
111 return throwVMTypeError(exec, scope);
112 }
113 ASSERT(instance);
114
115 instance->begin();
116 JSValue result = instance->invokeMethod(exec, method);
117 instance->end();
118 return JSValue::encode(result);
119}
120
121}
122