summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2009-08-26 12:42:59 +0100
committerBen Murdoch <benm@google.com>2009-09-02 12:32:47 +0100
commit30719f18a1aeee2464dca86c0b93bd9397a4ea42 (patch)
tree73c52b9e7ac22d6fc10ce710bd9a405d6d9b4285
parent4d19269bce7d5e32eb2c3cc1f469d207d8b15bb1 (diff)
downloadexternal_webkit-30719f18a1aeee2464dca86c0b93bd9397a4ea42.zip
external_webkit-30719f18a1aeee2464dca86c0b93bd9397a4ea42.tar.gz
external_webkit-30719f18a1aeee2464dca86c0b93bd9397a4ea42.tar.bz2
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.
-rw-r--r--WebCore/bindings/js/JSSQLTransactionCustom.cpp5
-rw-r--r--WebCore/bindings/v8/V8Binding.cpp8
-rw-r--r--WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp75
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 <v8.h>
@@ -191,10 +192,11 @@ String v8ValueToWebCoreString(v8::Handle<v8::Value> object)
v8::TryCatch block;
v8::Handle<v8::String> 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<SQLValue> 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<v8::Array> arguments = v8::Local<v8::Array>::Cast(args[1]);
- uint32_t length = arguments->Length();
-
- for (unsigned int i = 0; i < length; ++i) {
- v8::Local<v8::Value> 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<v8::Object> sqlArgsObject = args[1]->ToObject();
+ v8::Local<v8::Value> 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<v8::Integer> key = v8::Integer::New(i);
+ v8::Local<v8::Value> 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<SQLTransaction>(V8ClassIndex::SQLTRANSACTION, args.Holder());
@@ -84,22 +99,18 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql)
Frame* frame = V8Proxy::retrieveFrameForCurrentContext();
RefPtr<SQLStatementCallback> 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<SQLStatementErrorCallback> 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);