From 30719f18a1aeee2464dca86c0b93bd9397a4ea42 Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Wed, 26 Aug 2009 12:42:59 +0100 Subject: Add functionality to V8 bindings for SQLTransaction to allow array-like objects to be passed as the second parameter to executeSql(), and ensure exceptions are thrown in the right places. --- WebCore/bindings/js/JSSQLTransactionCustom.cpp | 5 ++ WebCore/bindings/v8/V8Binding.cpp | 8 ++- .../bindings/v8/custom/V8SQLTransactionCustom.cpp | 75 +++++++++++++--------- 3 files changed, 53 insertions(+), 35 deletions(-) diff --git a/WebCore/bindings/js/JSSQLTransactionCustom.cpp b/WebCore/bindings/js/JSSQLTransactionCustom.cpp index 30d59aa..dbe8e3c 100644 --- a/WebCore/bindings/js/JSSQLTransactionCustom.cpp +++ b/WebCore/bindings/js/JSSQLTransactionCustom.cpp @@ -44,6 +44,11 @@ namespace WebCore { JSValue JSSQLTransaction::executeSql(ExecState* exec, const ArgList& args) { + if (args.isEmpty()) { + setDOMException(exec, SYNTAX_ERR); + return jsUndefined(); + } + String sqlStatement = args.at(0).toString(exec); if (exec->hadException()) return jsUndefined(); diff --git a/WebCore/bindings/v8/V8Binding.cpp b/WebCore/bindings/v8/V8Binding.cpp index c5d580a..0da910b 100644 --- a/WebCore/bindings/v8/V8Binding.cpp +++ b/WebCore/bindings/v8/V8Binding.cpp @@ -39,6 +39,7 @@ #include "StringBuffer.h" #include "StringHash.h" #include "Threading.h" +#include "V8Proxy.h" #include @@ -191,10 +192,11 @@ String v8ValueToWebCoreString(v8::Handle object) v8::TryCatch block; v8::Handle v8String = object->ToString(); - // Check for empty handles to handle the case where an exception - // is thrown as part of invoking toString on the objectect. - if (v8String.IsEmpty()) + // Handle the case where an exception is thrown as part of invoking toString on the object. + if (block.HasCaught()) { + throwError(block.Exception()); return StringImpl::empty(); + } return v8StringToWebCoreString(v8String, DoNotExternalize, PlainStringType); } diff --git a/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp b/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp index 8fa5bde..dc801bd 100644 --- a/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp @@ -49,34 +49,49 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) { INC_STATS("DOM.SQLTransaction.executeSql()"); - if (args.Length() == 0) { - V8Proxy::throwError(V8Proxy::SyntaxError, "SQL statement is required."); - return v8::Undefined(); - } + if (args.Length() == 0) + return throwError("SQL statement is required.", V8Proxy::SyntaxError); String statement = toWebCoreString(args[0]); Vector sqlValues; - if (args.Length() > 1) { - // FIXME: Make this work for v8::Arrayish objects, as well - if (!args[1]->IsArray()) { - V8Proxy::throwError(V8Proxy::TypeError, "Statement arguments must be an v8::Array."); - return v8::Undefined(); - } - - v8::Local arguments = v8::Local::Cast(args[1]); - uint32_t length = arguments->Length(); - - for (unsigned int i = 0; i < length; ++i) { - v8::Local value = arguments->Get(v8::Integer::New(i)); - if (value.IsEmpty() || value->IsNull()) - sqlValues.append(SQLValue()); - else if (value->IsNumber()) - sqlValues.append(SQLValue(value->NumberValue())); + if (args.Length() > 1 && !isUndefinedOrNull(args[1])) { + if (args[1]->IsObject()) { + uint32_t sqlArgsLength = 0; + v8::Local sqlArgsObject = args[1]->ToObject(); + v8::Local lengthGetter; + { + v8::TryCatch block; + lengthGetter = sqlArgsObject->Get(v8::String::New("length")); + if (block.HasCaught()) + return throwError(block.Exception()); + } + + if (isUndefinedOrNull(lengthGetter)) + sqlArgsLength = sqlArgsObject->GetPropertyNames()->Length(); else - sqlValues.append(SQLValue(toWebCoreString(value))); - } + sqlArgsLength = lengthGetter->Uint32Value(); + + for (unsigned int i = 0; i < sqlArgsLength; ++i) { + v8::Local key = v8::Integer::New(i); + v8::Local value; + { + v8::TryCatch block; + value = sqlArgsObject->Get(key); + if (block.HasCaught()) + return throwError(block.Exception()); + } + + if (value.IsEmpty() || value->IsNull()) + sqlValues.append(SQLValue()); + else if (value->IsNumber()) + sqlValues.append(SQLValue(value->NumberValue())); + else + sqlValues.append(SQLValue(toWebCoreString(value))); + } + } else + return throwError("sqlArgs should be array or object!", V8Proxy::TypeError); } SQLTransaction* transaction = V8DOMWrapper::convertToNativeObject(V8ClassIndex::SQLTRANSACTION, args.Holder()); @@ -84,22 +99,18 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); RefPtr callback; - if (args.Length() > 2) { - if (!args[2]->IsObject()) { - V8Proxy::throwError(V8Proxy::TypeError, "Statement callback must be of valid type."); - return v8::Undefined(); - } + if (args.Length() > 2 && !isUndefinedOrNull(args[2])) { + if (!args[2]->IsObject()) + return throwError("Statement callback must be of valid type.", V8Proxy::TypeError); if (frame) callback = V8CustomSQLStatementCallback::create(args[2], frame); } RefPtr errorCallback; - if (args.Length() > 3) { - if (!args[2]->IsObject()) { - V8Proxy::throwError(V8Proxy::TypeError, "Statement error callback must be of valid type."); - return v8::Undefined(); - } + if (args.Length() > 3 && !isUndefinedOrNull(args[3])) { + if (!args[3]->IsObject()) + return throwError("Statement error callback must be of valid type.", V8Proxy::TypeError); if (frame) errorCallback = V8CustomSQLStatementErrorCallback::create(args[3], frame); -- cgit v1.1