diff options
Diffstat (limited to 'Source/WebCore/bindings/js/JSHistoryCustom.cpp')
-rw-r--r-- | Source/WebCore/bindings/js/JSHistoryCustom.cpp | 170 |
1 files changed, 42 insertions, 128 deletions
diff --git a/Source/WebCore/bindings/js/JSHistoryCustom.cpp b/Source/WebCore/bindings/js/JSHistoryCustom.cpp index c608f5328..1d4efac31 100644 --- a/Source/WebCore/bindings/js/JSHistoryCustom.cpp +++ b/Source/WebCore/bindings/js/JSHistoryCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 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,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,8 +29,9 @@ #include "config.h" #include "JSHistory.h" +#include "ExceptionCode.h" #include "Frame.h" -#include "History.h" +#include "JSDOMConvert.h" #include "SerializedScriptValue.h" #include <runtime/JSFunction.h> @@ -38,159 +39,72 @@ using namespace JSC; namespace WebCore { -static EncodedJSValue nonCachingStaticBackFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) +JSValue JSHistory::state(ExecState& state) const { - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 0, propertyName.publicName(), jsHistoryPrototypeFunctionBack)); -} - -static EncodedJSValue nonCachingStaticForwardFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) -{ - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 0, propertyName.publicName(), jsHistoryPrototypeFunctionForward)); -} - -static EncodedJSValue nonCachingStaticGoFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) -{ - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 1, propertyName.publicName(), jsHistoryPrototypeFunctionGo)); -} - -bool JSHistory::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - // When accessing History cross-domain, functions are always the native built-in ones. - // See JSDOMWindow::getOwnPropertySlotDelegate for additional details. - - // Our custom code is only needed to implement the Window cross-domain scheme, so if access is - // allowed, return false so the normal lookup will take place. - String message; - if (shouldAllowAccessToFrame(exec, impl().frame(), message)) - return false; - - // Check for the few functions that we allow, even when called cross-domain. - // Make these read-only / non-configurable to prevent writes via defineProperty. - const HashEntry* entry = JSHistoryPrototype::info()->propHashTable(exec)->entry(exec, propertyName); - if (entry) { - // Allow access to back(), forward() and go() from any frame. - if (entry->attributes() & JSC::Function) { - if (entry->function() == jsHistoryPrototypeFunctionBack) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticBackFunctionGetter); - return true; - } else if (entry->function() == jsHistoryPrototypeFunctionForward) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticForwardFunctionGetter); - return true; - } else if (entry->function() == jsHistoryPrototypeFunctionGo) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticGoFunctionGetter); - return true; - } - } - } else { - // Allow access to toString() cross-domain, but always Object.toString. - if (propertyName == exec->propertyNames().toString) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, objectToStringFunctionGetter); - return true; - } - } - - printErrorMessageForFrame(impl().frame(), message); - slot.setUndefined(); - return true; -} - -bool JSHistory::putDelegate(ExecState* exec, PropertyName, JSValue, PutPropertySlot&) -{ - if (!shouldAllowAccessToFrame(exec, impl().frame())) - return true; - return false; -} - -bool JSHistory::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) -{ - JSHistory* thisObject = jsCast<JSHistory*>(cell); - if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) - return false; - return Base::deleteProperty(thisObject, exec, propertyName); -} - -bool JSHistory::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName) -{ - JSHistory* thisObject = jsCast<JSHistory*>(cell); - if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) - return false; - return Base::deletePropertyByIndex(thisObject, exec, propertyName); -} - -void JSHistory::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) -{ - JSHistory* thisObject = jsCast<JSHistory*>(object); - if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) - return; - Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode); -} - -JSValue JSHistory::state(ExecState *exec) const -{ - History& history = impl(); + History& history = wrapped(); JSValue cachedValue = m_state.get(); if (!cachedValue.isEmpty() && !history.stateChanged()) return cachedValue; RefPtr<SerializedScriptValue> serialized = history.state(); - JSValue result = serialized ? serialized->deserialize(exec, globalObject(), 0) : jsNull(); - const_cast<JSHistory*>(this)->m_state.set(exec->vm(), this, result); + JSValue result = serialized ? serialized->deserialize(state, globalObject()) : jsNull(); + m_state.set(state.vm(), this, result); return result; } -JSValue JSHistory::pushState(ExecState* exec) +JSValue JSHistory::pushState(ExecState& state) { - if (!shouldAllowAccessToFrame(exec, impl().frame())) - return jsUndefined(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto argCount = state.argumentCount(); + if (UNLIKELY(argCount < 2)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(exec, exec->argument(0), 0, 0); - if (exec->hadException()) - return jsUndefined(); + auto historyState = SerializedScriptValue::create(state, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, JSValue()); + + // FIXME: title should not be nullable. + String title = convert<IDLNullable<IDLDOMString>>(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, JSValue()); - String title = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(1)); - if (exec->hadException()) - return jsUndefined(); - String url; - if (exec->argumentCount() > 2) { - url = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2)); - if (exec->hadException()) - return jsUndefined(); + if (argCount > 2) { + url = convert<IDLNullable<IDLUSVString>>(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, JSValue()); } - ExceptionCode ec = 0; - impl().stateObjectAdded(historyState.release(), title, url, History::StateObjectType::Push, ec); - setDOMException(exec, ec); + propagateException(state, scope, wrapped().stateObjectAdded(WTFMove(historyState), title, url, History::StateObjectType::Push)); m_state.clear(); return jsUndefined(); } -JSValue JSHistory::replaceState(ExecState* exec) +JSValue JSHistory::replaceState(ExecState& state) { - if (!shouldAllowAccessToFrame(exec, impl().frame())) - return jsUndefined(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto argCount = state.argumentCount(); + if (UNLIKELY(argCount < 2)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto historyState = SerializedScriptValue::create(state, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, JSValue()); - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(exec, exec->argument(0), 0, 0); - if (exec->hadException()) - return jsUndefined(); + // FIXME: title should not be nullable. + String title = convert<IDLNullable<IDLDOMString>>(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, JSValue()); - String title = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(1)); - if (exec->hadException()) - return jsUndefined(); - String url; - if (exec->argumentCount() > 2) { - url = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2)); - if (exec->hadException()) - return jsUndefined(); + if (argCount > 2) { + url = convert<IDLNullable<IDLUSVString>>(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, JSValue()); } - ExceptionCode ec = 0; - impl().stateObjectAdded(historyState.release(), title, url, History::StateObjectType::Replace, ec); - setDOMException(exec, ec); + propagateException(state, scope, wrapped().stateObjectAdded(WTFMove(historyState), title, url, History::StateObjectType::Replace)); m_state.clear(); |