DebuggerScope* DebuggerScope::create(VM& vm, JSScope* scope) { Structure* structure = scope->globalObject()->debuggerScopeStructure(); DebuggerScope* debuggerScope = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm, structure, scope); debuggerScope->finishCreation(vm); return debuggerScope; }
bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { DebuggerScope* scope = jsCast<DebuggerScope*>(object); ASSERT(scope->isValid()); if (!scope->isValid()) return false; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); slot.setThisValue(JSValue(thisObject)); // By default, JSObject::getPropertySlot() will look in the DebuggerScope's prototype // chain and not the wrapped scope, and JSObject::getPropertySlot() cannot be overridden // to behave differently for the DebuggerScope. // // Instead, we'll treat all properties in the wrapped scope and its prototype chain as // the own properties of the DebuggerScope. This is fine because the WebInspector // does not presently need to distinguish between what's owned at each level in the // prototype chain. Hence, we'll invoke getPropertySlot() on the wrapped scope here // instead of getOwnPropertySlot(). bool result = thisObject->getPropertySlot(exec, propertyName, slot); if (result && slot.isValue() && slot.getValue(exec, propertyName) == jsTDZValue()) { // FIXME: // We hit a scope property that has the TDZ empty value. // Currently, we just lie to the inspector and claim that this property is undefined. // This is not ideal and we should fix it. // https://bugs.webkit.org/show_bug.cgi?id=144977 slot.setValue(slot.slotBase(), DontEnum, jsUndefined()); return true; } return result; }
bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) { DebuggerScope* scope = jsCast<DebuggerScope*>(object); ASSERT(scope->isValid()); if (!scope->isValid()) return false; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); return thisObject->methodTable()->defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); }
void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { DebuggerScope* scope = jsCast<DebuggerScope*>(object); ASSERT(scope->isValid()); if (!scope->isValid()) return; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); thisObject->methodTable()->getPropertyNames(thisObject, exec, propertyNames, mode); }
bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) { DebuggerScope* scope = jsCast<DebuggerScope*>(cell); ASSERT(scope->isValid()); if (!scope->isValid()) return false; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); return thisObject->methodTable()->deleteProperty(thisObject, exec, propertyName); }
void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { DebuggerScope* scope = jsCast<DebuggerScope*>(cell); ASSERT(scope->isValid()); if (!scope->isValid()) return; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); slot.setThisValue(JSValue(thisObject)); thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot); }
void DebuggerScope::invalidateChain() { DebuggerScope* scope = this; while (scope) { ASSERT(scope->isValid()); DebuggerScope* nextScope = scope->m_next.get(); scope->m_next.clear(); scope->m_scope.clear(); scope = nextScope; } }
Deprecated::ScriptValue ScriptDebugServer::exceptionOrCaughtValue(JSC::ExecState* state) { if (reasonForPause() == PausedForException) return Deprecated::ScriptValue(state->vm(), currentException()); RefPtr<DebuggerCallFrame> debuggerCallFrame = currentDebuggerCallFrame(); while (debuggerCallFrame) { DebuggerScope* scope = debuggerCallFrame->scope(); if (scope->isCatchScope()) return Deprecated::ScriptValue(state->vm(), scope->caughtValue(state)); debuggerCallFrame = debuggerCallFrame->callerFrame(); } return Deprecated::ScriptValue(); }
JSValue JSJavaScriptCallFrame::scopeType(ExecState* exec) { if (!impl().scopeChain()) return jsUndefined(); if (!exec->argument(0).isInt32()) return jsUndefined(); int index = exec->argument(0).asInt32(); DebuggerScope* scopeChain = impl().scopeChain(); DebuggerScope::iterator end = scopeChain->end(); bool foundLocalScope = false; for (DebuggerScope::iterator iter = scopeChain->begin(); iter != end; ++iter) { DebuggerScope* scope = iter.get(); if (!foundLocalScope && scope->isFunctionOrEvalScope()) { // First function scope is the local scope, each successive one is a closure. if (!index) return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE); foundLocalScope = true; } if (!index) { if (scope->isCatchScope()) return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE); if (scope->isFunctionNameScope()) return jsNumber(JSJavaScriptCallFrame::FUNCTION_NAME_SCOPE); if (scope->isWithScope()) return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE); if (scope->isGlobalScope()) { ASSERT(++iter == end); return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE); } ASSERT(scope->isFunctionOrEvalScope()); return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE); } --index; } ASSERT_NOT_REACHED(); return jsUndefined(); }
JSValue JSJavaScriptCallFrame::scopeChain(ExecState* exec) const { if (!impl().scopeChain()) return jsNull(); DebuggerScope* scopeChain = impl().scopeChain(); DebuggerScope::iterator iter = scopeChain->begin(); DebuggerScope::iterator end = scopeChain->end(); // We must always have something in the scope chain. ASSERT(iter != end); MarkedArgumentBuffer list; do { list.append(iter.get()); ++iter; } while (iter != end); return constructArray(exec, nullptr, globalObject(), list); }
bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { DebuggerScope* scope = jsCast<DebuggerScope*>(object); ASSERT(scope->isValid()); if (!scope->isValid()) return false; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); slot.setThisValue(JSValue(thisObject)); // By default, JSObject::getPropertySlot() will look in the DebuggerScope's prototype // chain and not the wrapped scope, and JSObject::getPropertySlot() cannot be overridden // to behave differently for the DebuggerScope. // // Instead, we'll treat all properties in the wrapped scope and its prototype chain as // the own properties of the DebuggerScope. This is fine because the WebInspector // does not presently need to distinguish between what's owned at each level in the // prototype chain. Hence, we'll invoke getPropertySlot() on the wrapped scope here // instead of getOwnPropertySlot(). return thisObject->getPropertySlot(exec, propertyName, slot); }