diff options
Diffstat (limited to 'Source/JavaScriptCore/API/JSContextRef.cpp')
-rw-r--r-- | Source/JavaScriptCore/API/JSContextRef.cpp | 222 |
1 files changed, 170 insertions, 52 deletions
diff --git a/Source/JavaScriptCore/API/JSContextRef.cpp b/Source/JavaScriptCore/API/JSContextRef.cpp index 81b61cf47..e7dad19b0 100644 --- a/Source/JavaScriptCore/API/JSContextRef.cpp +++ b/Source/JavaScriptCore/API/JSContextRef.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2013, 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 @@ -10,37 +10,47 @@ * 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 COMPUTER, INC. ``AS IS'' AND ANY + * 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 COMPUTER, INC. OR + * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "JSContextRef.h" -#include "JSContextRefPrivate.h" +#include "JSContextRefInternal.h" #include "APICast.h" #include "CallFrame.h" -#include "CallFrameInlines.h" #include "InitializeThreading.h" #include "JSCallbackObject.h" #include "JSClassRef.h" #include "JSGlobalObject.h" #include "JSObject.h" -#include "Operations.h" +#include "JSCInlines.h" #include "SourceProvider.h" #include "StackVisitor.h" +#include "Watchdog.h" #include <wtf/text/StringBuilder.h> #include <wtf/text/StringHash.h> +#if ENABLE(REMOTE_INSPECTOR) +#include "JSGlobalObjectDebuggable.h" +#include "JSGlobalObjectInspectorController.h" +#include "JSRemoteInspector.h" +#endif + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +#include "JSContextRefInspectorSupport.h" +#endif + #if OS(DARWIN) #include <mach-o/dyld.h> @@ -57,7 +67,7 @@ using namespace JSC; JSContextGroupRef JSContextGroupCreate() { initializeThreading(); - return toRef(VM::createContextGroup().leakRef()); + return toRef(&VM::createContextGroup().leakRef()); } JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) @@ -68,16 +78,10 @@ JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) void JSContextGroupRelease(JSContextGroupRef group) { - IdentifierTable* savedIdentifierTable; VM& vm = *toJS(group); - { - JSLockHolder lock(vm); - savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(vm.identifierTable); - vm.deref(); - } - - wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable); + JSLockHolder locker(&vm); + vm.deref(); } static bool internalScriptTimeoutCallback(ExecState* exec, void* callbackPtr, void* callbackData) @@ -91,21 +95,21 @@ static bool internalScriptTimeoutCallback(ExecState* exec, void* callbackPtr, vo void JSContextGroupSetExecutionTimeLimit(JSContextGroupRef group, double limit, JSShouldTerminateCallback callback, void* callbackData) { VM& vm = *toJS(group); - APIEntryShim entryShim(&vm); - Watchdog& watchdog = vm.watchdog; + JSLockHolder locker(&vm); + Watchdog& watchdog = vm.ensureWatchdog(); if (callback) { void* callbackPtr = reinterpret_cast<void*>(callback); - watchdog.setTimeLimit(vm, limit, internalScriptTimeoutCallback, callbackPtr, callbackData); + watchdog.setTimeLimit(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<double>(limit)), internalScriptTimeoutCallback, callbackPtr, callbackData); } else - watchdog.setTimeLimit(vm, limit); + watchdog.setTimeLimit(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<double>(limit))); } void JSContextGroupClearExecutionTimeLimit(JSContextGroupRef group) { VM& vm = *toJS(group); - APIEntryShim entryShim(&vm); - Watchdog& watchdog = vm.watchdog; - watchdog.setTimeLimit(vm, std::numeric_limits<double>::infinity()); + JSLockHolder locker(&vm); + if (vm.watchdog()) + vm.watchdog()->setTimeLimit(Watchdog::noTimeLimit); } // From the API's perspective, a global context remains alive iff it has been JSGlobalContextRetained. @@ -129,30 +133,36 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass { initializeThreading(); - RefPtr<VM> vm = group ? PassRefPtr<VM>(toJS(group)) : VM::createContextGroup(); + Ref<VM> vm = group ? Ref<VM>(*toJS(group)) : VM::createContextGroup(); - APIEntryShim entryShim(vm.get(), false); - vm->makeUsableFromMultipleThreads(); + JSLockHolder locker(vm.ptr()); if (!globalObjectClass) { - JSGlobalObject* globalObject = JSGlobalObject::create(*vm, JSGlobalObject::createStructure(*vm, jsNull())); - globalObject->setGlobalThis(*vm, JSProxy::create(*vm, JSProxy::createStructure(*vm, globalObject, globalObject->prototype()), globalObject)); + JSGlobalObject* globalObject = JSGlobalObject::create(vm.get(), JSGlobalObject::createStructure(vm.get(), jsNull())); +#if ENABLE(REMOTE_INSPECTOR) + if (JSRemoteInspectorGetInspectionEnabledByDefault()) + globalObject->setRemoteDebuggingEnabled(true); +#endif return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec())); } - JSGlobalObject* globalObject = JSCallbackObject<JSGlobalObject>::create(*vm, globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(*vm, 0, jsNull())); + JSGlobalObject* globalObject = JSCallbackObject<JSGlobalObject>::create(vm.get(), globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(vm.get(), 0, jsNull())); ExecState* exec = globalObject->globalExec(); JSValue prototype = globalObjectClass->prototype(exec); if (!prototype) prototype = jsNull(); - globalObject->resetPrototype(*vm, prototype); + globalObject->resetPrototype(vm.get(), prototype); +#if ENABLE(REMOTE_INSPECTOR) + if (JSRemoteInspectorGetInspectionEnabledByDefault()) + globalObject->setRemoteDebuggingEnabled(true); +#endif return JSGlobalContextRetain(toGlobalRef(exec)); } JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx) { ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); VM& vm = exec->vm(); gcProtect(exec->vmEntryGlobalObject()); @@ -162,21 +172,14 @@ JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx) void JSGlobalContextRelease(JSGlobalContextRef ctx) { - IdentifierTable* savedIdentifierTable; ExecState* exec = toJS(ctx); - { - JSLockHolder lock(exec); - - VM& vm = exec->vm(); - savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(vm.identifierTable); + JSLockHolder locker(exec); - bool protectCountIsZero = Heap::heap(exec->vmEntryGlobalObject())->unprotect(exec->vmEntryGlobalObject()); - if (protectCountIsZero) - vm.heap.reportAbandonedObjectGraph(); - vm.deref(); - } - - wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable); + VM& vm = exec->vm(); + bool protectCountIsZero = Heap::heap(exec->vmEntryGlobalObject())->unprotect(exec->vmEntryGlobalObject()); + if (protectCountIsZero) + vm.heap.reportAbandonedObjectGraph(); + vm.deref(); } JSObjectRef JSContextGetGlobalObject(JSContextRef ctx) @@ -186,7 +189,7 @@ JSObjectRef JSContextGetGlobalObject(JSContextRef ctx) return 0; } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); return toRef(jsCast<JSObject*>(exec->lexicalGlobalObject()->methodTable()->toThis(exec->lexicalGlobalObject(), exec, NotStrictMode))); } @@ -208,7 +211,7 @@ JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx) return 0; } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); return toGlobalRef(exec->lexicalGlobalObject()->globalExec()); } @@ -221,7 +224,7 @@ JSStringRef JSGlobalContextCopyName(JSGlobalContextRef ctx) } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); String name = exec->vmEntryGlobalObject()->name(); if (name.isNull()) @@ -238,7 +241,7 @@ void JSGlobalContextSetName(JSGlobalContextRef ctx, JSStringRef name) } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); exec->vmEntryGlobalObject()->setName(name ? name->string() : String()); } @@ -252,12 +255,12 @@ public: { } - StackVisitor::Status operator()(StackVisitor& visitor) + StackVisitor::Status operator()(StackVisitor& visitor) const { if (m_remainingCapacityForFrameCapture) { // If callee is unknown, but we've not added any frame yet, we should // still add the frame, because something called us, and gave us arguments. - JSObject* callee = visitor->callee(); + JSCell* callee = visitor->callee(); if (!callee && visitor->index()) return StackVisitor::Done; @@ -270,7 +273,7 @@ public: builder.append(visitor->functionName()); builder.appendLiteral("() at "); builder.append(visitor->sourceURL()); - if (visitor->isJSFrame()) { + if (visitor->hasLineAndColumnInfo()) { builder.append(':'); unsigned lineNumber; unsigned unusedColumn; @@ -289,7 +292,7 @@ public: private: StringBuilder& m_builder; - unsigned m_remainingCapacityForFrameCapture; + mutable unsigned m_remainingCapacityForFrameCapture; }; JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize) @@ -310,4 +313,119 @@ JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize) return OpaqueJSString::create(builder.toString()).leakRef(); } +bool JSGlobalContextGetRemoteInspectionEnabled(JSGlobalContextRef ctx) +{ + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } + + ExecState* exec = toJS(ctx); + JSLockHolder lock(exec); + + return exec->vmEntryGlobalObject()->remoteDebuggingEnabled(); +} + +void JSGlobalContextSetRemoteInspectionEnabled(JSGlobalContextRef ctx, bool enabled) +{ + if (!ctx) { + ASSERT_NOT_REACHED(); + return; + } + + ExecState* exec = toJS(ctx); + JSLockHolder lock(exec); + + exec->vmEntryGlobalObject()->setRemoteDebuggingEnabled(enabled); +} + +bool JSGlobalContextGetIncludesNativeCallStackWhenReportingExceptions(JSGlobalContextRef ctx) +{ +#if ENABLE(REMOTE_INSPECTOR) + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } + + ExecState* exec = toJS(ctx); + JSLockHolder lock(exec); + + JSGlobalObject* globalObject = exec->vmEntryGlobalObject(); + return globalObject->inspectorController().includesNativeCallStackWhenReportingExceptions(); +#else + UNUSED_PARAM(ctx); + return false; +#endif +} + +void JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(JSGlobalContextRef ctx, bool includesNativeCallStack) +{ +#if ENABLE(REMOTE_INSPECTOR) + if (!ctx) { + ASSERT_NOT_REACHED(); + return; + } + + ExecState* exec = toJS(ctx); + JSLockHolder lock(exec); + + JSGlobalObject* globalObject = exec->vmEntryGlobalObject(); + globalObject->inspectorController().setIncludesNativeCallStackWhenReportingExceptions(includesNativeCallStack); +#else + UNUSED_PARAM(ctx); + UNUSED_PARAM(includesNativeCallStack); +#endif +} + +#if USE(CF) +CFRunLoopRef JSGlobalContextGetDebuggerRunLoop(JSGlobalContextRef ctx) +{ +#if ENABLE(REMOTE_INSPECTOR) + if (!ctx) { + ASSERT_NOT_REACHED(); + return nullptr; + } + + ExecState* exec = toJS(ctx); + JSLockHolder lock(exec); + + return exec->vmEntryGlobalObject()->inspectorDebuggable().targetRunLoop(); +#else + UNUSED_PARAM(ctx); + return nullptr; +#endif +} +void JSGlobalContextSetDebuggerRunLoop(JSGlobalContextRef ctx, CFRunLoopRef runLoop) +{ +#if ENABLE(REMOTE_INSPECTOR) + if (!ctx) { + ASSERT_NOT_REACHED(); + return; + } + + ExecState* exec = toJS(ctx); + JSLockHolder lock(exec); + + exec->vmEntryGlobalObject()->inspectorDebuggable().setTargetRunLoop(runLoop); +#else + UNUSED_PARAM(ctx); + UNUSED_PARAM(runLoop); +#endif +} +#endif // USE(CF) + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +Inspector::AugmentableInspectorController* JSGlobalContextGetAugmentableInspectorController(JSGlobalContextRef ctx) +{ + if (!ctx) { + ASSERT_NOT_REACHED(); + return nullptr; + } + + ExecState* exec = toJS(ctx); + JSLockHolder lock(exec); + + return &exec->vmEntryGlobalObject()->inspectorController(); +} +#endif |