1/* 2 * Copyright (C) 2013 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 "JSInjectedScriptHost.h" 28 29#if ENABLE(INSPECTOR) 30 31#include "DateInstance.h" 32#include "Error.h" 33#include "InjectedScriptHost.h" 34#include "JSArray.h" 35#include "JSFunction.h" 36#include "JSInjectedScriptHostPrototype.h" 37#include "JSTypedArrays.h" 38#include "ObjectConstructor.h" 39#include "JSCInlines.h" 40#include "RegExpObject.h" 41#include "SourceCode.h" 42#include "TypedArrayInlines.h" 43 44using namespace JSC; 45 46namespace Inspector { 47 48const ClassInfo JSInjectedScriptHost::s_info = { "InjectedScriptHost", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSInjectedScriptHost) }; 49 50JSInjectedScriptHost::JSInjectedScriptHost(VM& vm, Structure* structure, PassRefPtr<InjectedScriptHost> impl) 51 : JSDestructibleObject(vm, structure) 52 , m_impl(impl.leakRef()) 53{ 54} 55 56void JSInjectedScriptHost::finishCreation(VM& vm) 57{ 58 Base::finishCreation(vm); 59 ASSERT(inherits(info())); 60} 61 62JSObject* JSInjectedScriptHost::createPrototype(VM& vm, JSGlobalObject* globalObject) 63{ 64 return JSInjectedScriptHostPrototype::create(vm, globalObject, JSInjectedScriptHostPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); 65} 66 67void JSInjectedScriptHost::destroy(JSC::JSCell* cell) 68{ 69 JSInjectedScriptHost* thisObject = static_cast<JSInjectedScriptHost*>(cell); 70 thisObject->JSInjectedScriptHost::~JSInjectedScriptHost(); 71} 72 73void JSInjectedScriptHost::releaseImpl() 74{ 75 if (m_impl) { 76 m_impl->deref(); 77 m_impl = nullptr; 78 } 79} 80 81JSInjectedScriptHost::~JSInjectedScriptHost() 82{ 83 releaseImpl(); 84} 85 86JSValue JSInjectedScriptHost::evaluate(ExecState* exec) const 87{ 88 JSGlobalObject* globalObject = exec->lexicalGlobalObject(); 89 return globalObject->evalFunction(); 90} 91 92JSValue JSInjectedScriptHost::internalConstructorName(ExecState* exec) 93{ 94 if (exec->argumentCount() < 1) 95 return jsUndefined(); 96 97 JSObject* thisObject = jsCast<JSObject*>(exec->uncheckedArgument(0).toThis(exec, NotStrictMode)); 98 String result = thisObject->methodTable()->className(thisObject); 99 return jsString(exec, result); 100} 101 102JSValue JSInjectedScriptHost::isHTMLAllCollection(ExecState* exec) 103{ 104 if (exec->argumentCount() < 1) 105 return jsUndefined(); 106 107 JSValue value = exec->uncheckedArgument(0); 108 return jsBoolean(impl().isHTMLAllCollection(value)); 109} 110 111JSValue JSInjectedScriptHost::type(ExecState* exec) 112{ 113 if (exec->argumentCount() < 1) 114 return jsUndefined(); 115 116 JSValue value = exec->uncheckedArgument(0); 117 if (value.isString()) 118 return exec->vm().smallStrings.stringString(); 119 if (value.isBoolean()) 120 return exec->vm().smallStrings.booleanString(); 121 if (value.isNumber()) 122 return exec->vm().smallStrings.numberString(); 123 124 if (value.inherits(JSArray::info())) 125 return jsNontrivialString(exec, ASCIILiteral("array")); 126 if (value.inherits(DateInstance::info())) 127 return jsNontrivialString(exec, ASCIILiteral("date")); 128 if (value.inherits(RegExpObject::info())) 129 return jsNontrivialString(exec, ASCIILiteral("regexp")); 130 if (value.inherits(JSInt8Array::info()) || value.inherits(JSInt16Array::info()) || value.inherits(JSInt32Array::info())) 131 return jsNontrivialString(exec, ASCIILiteral("array")); 132 if (value.inherits(JSUint8Array::info()) || value.inherits(JSUint16Array::info()) || value.inherits(JSUint32Array::info())) 133 return jsNontrivialString(exec, ASCIILiteral("array")); 134 if (value.inherits(JSFloat32Array::info()) || value.inherits(JSFloat64Array::info())) 135 return jsNontrivialString(exec, ASCIILiteral("array")); 136 137 return impl().type(exec, value); 138} 139 140JSValue JSInjectedScriptHost::functionDetails(ExecState* exec) 141{ 142 if (exec->argumentCount() < 1) 143 return jsUndefined(); 144 145 JSValue value = exec->uncheckedArgument(0); 146 if (!value.asCell()->inherits(JSFunction::info())) 147 return jsUndefined(); 148 149 JSFunction* function = jsCast<JSFunction*>(value); 150 const SourceCode* sourceCode = function->sourceCode(); 151 if (!sourceCode) 152 return jsUndefined(); 153 154 int lineNumber = sourceCode->firstLine(); 155 if (lineNumber) 156 lineNumber -= 1; // In the inspector protocol all positions are 0-based while in SourceCode they are 1-based 157 158 String scriptID = String::number(sourceCode->provider()->asID()); 159 JSObject* location = constructEmptyObject(exec); 160 location->putDirect(exec->vm(), Identifier(exec, "lineNumber"), jsNumber(lineNumber)); 161 location->putDirect(exec->vm(), Identifier(exec, "scriptId"), jsString(exec, scriptID)); 162 163 JSObject* result = constructEmptyObject(exec); 164 result->putDirect(exec->vm(), Identifier(exec, "location"), location); 165 166 String name = function->name(exec); 167 if (!name.isEmpty()) 168 result->putDirect(exec->vm(), Identifier(exec, "name"), jsString(exec, name)); 169 170 String displayName = function->displayName(exec); 171 if (!displayName.isEmpty()) 172 result->putDirect(exec->vm(), Identifier(exec, "displayName"), jsString(exec, displayName)); 173 174 // FIXME: provide function scope data in "scopesRaw" property when JSC supports it. 175 // <https://webkit.org/b/87192> [JSC] expose function (closure) inner context to debugger 176 177 return result; 178} 179 180JSValue JSInjectedScriptHost::getInternalProperties(ExecState*) 181{ 182 // FIXME: <https://webkit.org/b/94533> [JSC] expose object inner properties to debugger 183 return jsUndefined(); 184} 185 186JSValue toJS(ExecState* exec, JSGlobalObject* globalObject, InjectedScriptHost* impl) 187{ 188 if (!impl) 189 return jsNull(); 190 191 JSObject* prototype = JSInjectedScriptHost::createPrototype(exec->vm(), globalObject); 192 Structure* structure = JSInjectedScriptHost::createStructure(exec->vm(), globalObject, prototype); 193 JSInjectedScriptHost* injectedScriptHost = JSInjectedScriptHost::create(exec->vm(), structure, impl); 194 195 return injectedScriptHost; 196} 197 198JSInjectedScriptHost* toJSInjectedScriptHost(JSValue value) 199{ 200 return value.inherits(JSInjectedScriptHost::info()) ? jsCast<JSInjectedScriptHost*>(value) : nullptr; 201} 202 203} // namespace Inspector 204 205#endif // ENABLE(INSPECTOR) 206