Commit 52ef5a2f authored by sigbjornf@opera.com's avatar sigbjornf@opera.com

Tidy up error reporting for calling-constructor-as-function.

Introduce an ExceptionMessage helper for emitting the desired error
message when calling a constructor as a function & have the IDL compiler
generate calls to it.

At the same time, make 'detail' a required argument to all 'failedToXX'
methods on ExceptionMessage -- better if the caller is required to
supply meaningful info.

R=nbarth@chromium.org,haraken@chromium.org
BUG=

Review URL: https://codereview.chromium.org/211333004

git-svn-id: svn://svn.chromium.org/blink/trunk@170037 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 2e67c643
...@@ -820,7 +820,7 @@ void {{v8_class}}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value> ...@@ -820,7 +820,7 @@ void {{v8_class}}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value>
UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{measure_as}}); UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{measure_as}});
{% endif %} {% endif %}
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("{{interface_name}}", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("{{interface_name}}"), info.GetIsolate());
return; return;
} }
......
...@@ -408,7 +408,7 @@ static void constructor{{constructor.overload_index}}(const v8::FunctionCallback ...@@ -408,7 +408,7 @@ static void constructor{{constructor.overload_index}}(const v8::FunctionCallback
static void {{v8_class}}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) static void {{v8_class}}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{ {
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("{{constructor.name}}", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("{{constructor.name}}"), info.GetIsolate());
return; return;
} }
......
...@@ -747,7 +747,7 @@ void V8TestInterface::constructorCallback(const v8::FunctionCallbackInfo<v8::Val ...@@ -747,7 +747,7 @@ void V8TestInterface::constructorCallback(const v8::FunctionCallbackInfo<v8::Val
{ {
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor");
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("TestInterface", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("TestInterface"), info.GetIsolate());
return; return;
} }
......
...@@ -114,7 +114,7 @@ void V8TestInterfaceConstructor::constructorCallback(const v8::FunctionCallbackI ...@@ -114,7 +114,7 @@ void V8TestInterfaceConstructor::constructorCallback(const v8::FunctionCallbackI
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor");
UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::TestFeature); UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::TestFeature);
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("TestInterfaceConstructor", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("TestInterfaceConstructor"), info.GetIsolate());
return; return;
} }
......
...@@ -103,7 +103,7 @@ void V8TestInterfaceConstructor2::constructorCallback(const v8::FunctionCallback ...@@ -103,7 +103,7 @@ void V8TestInterfaceConstructor2::constructorCallback(const v8::FunctionCallback
{ {
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor");
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("TestInterfaceConstructor2", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("TestInterfaceConstructor2"), info.GetIsolate());
return; return;
} }
......
...@@ -64,7 +64,7 @@ void V8TestInterfaceConstructor3::constructorCallback(const v8::FunctionCallback ...@@ -64,7 +64,7 @@ void V8TestInterfaceConstructor3::constructorCallback(const v8::FunctionCallback
{ {
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor");
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("TestInterfaceConstructor3", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("TestInterfaceConstructor3"), info.GetIsolate());
return; return;
} }
......
...@@ -49,7 +49,7 @@ void V8TestInterfaceCustomConstructor::constructorCallback(const v8::FunctionCal ...@@ -49,7 +49,7 @@ void V8TestInterfaceCustomConstructor::constructorCallback(const v8::FunctionCal
{ {
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor");
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("TestInterfaceCustomConstructor", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("TestInterfaceCustomConstructor"), info.GetIsolate());
return; return;
} }
......
...@@ -328,7 +328,7 @@ void V8TestInterfaceEventConstructor::constructorCallback(const v8::FunctionCall ...@@ -328,7 +328,7 @@ void V8TestInterfaceEventConstructor::constructorCallback(const v8::FunctionCall
{ {
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor");
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("TestInterfaceEventConstructor", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("TestInterfaceEventConstructor"), info.GetIsolate());
return; return;
} }
......
...@@ -50,7 +50,7 @@ const WrapperTypeInfo V8TestInterfaceEventTargetConstructor::wrapperTypeInfo = { ...@@ -50,7 +50,7 @@ const WrapperTypeInfo V8TestInterfaceEventTargetConstructor::wrapperTypeInfo = {
static void V8TestInterfaceEventTargetConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) static void V8TestInterfaceEventTargetConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{ {
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("Name", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("Name"), info.GetIsolate());
return; return;
} }
......
...@@ -74,7 +74,7 @@ const WrapperTypeInfo V8TestInterfaceNamedConstructorConstructor::wrapperTypeInf ...@@ -74,7 +74,7 @@ const WrapperTypeInfo V8TestInterfaceNamedConstructorConstructor::wrapperTypeInf
static void V8TestInterfaceNamedConstructorConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) static void V8TestInterfaceNamedConstructorConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{ {
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("Audio", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("Audio"), info.GetIsolate());
return; return;
} }
......
...@@ -50,7 +50,7 @@ const WrapperTypeInfo V8TestInterfaceNamedConstructor2Constructor::wrapperTypeIn ...@@ -50,7 +50,7 @@ const WrapperTypeInfo V8TestInterfaceNamedConstructor2Constructor::wrapperTypeIn
static void V8TestInterfaceNamedConstructor2ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) static void V8TestInterfaceNamedConstructor2ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{ {
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("Audio", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("Audio"), info.GetIsolate());
return; return;
} }
......
...@@ -74,7 +74,7 @@ void V8TestInterfacePython2::constructorCallback(const v8::FunctionCallbackInfo< ...@@ -74,7 +74,7 @@ void V8TestInterfacePython2::constructorCallback(const v8::FunctionCallbackInfo<
{ {
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor");
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("TestInterfacePython2", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("TestInterfacePython2"), info.GetIsolate());
return; return;
} }
......
...@@ -117,7 +117,7 @@ void V8TestInterfaceWillBeGarbageCollected::constructorCallback(const v8::Functi ...@@ -117,7 +117,7 @@ void V8TestInterfaceWillBeGarbageCollected::constructorCallback(const v8::Functi
{ {
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor");
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("TestInterfaceWillBeGarbageCollected", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("TestInterfaceWillBeGarbageCollected"), info.GetIsolate());
return; return;
} }
......
...@@ -148,7 +148,7 @@ void V8TestNode::constructorCallback(const v8::FunctionCallbackInfo<v8::Value>& ...@@ -148,7 +148,7 @@ void V8TestNode::constructorCallback(const v8::FunctionCallbackInfo<v8::Value>&
{ {
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor");
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("TestNode", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("TestNode"), info.GetIsolate());
return; return;
} }
......
...@@ -434,7 +434,7 @@ void V8TestTypedefs::constructorCallback(const v8::FunctionCallbackInfo<v8::Valu ...@@ -434,7 +434,7 @@ void V8TestTypedefs::constructorCallback(const v8::FunctionCallbackInfo<v8::Valu
{ {
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor");
if (!info.IsConstructCall()) { if (!info.IsConstructCall()) {
throwTypeError(ExceptionMessages::failedToConstruct("TestTypedefs", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("TestTypedefs"), info.GetIsolate());
return; return;
} }
......
...@@ -81,6 +81,11 @@ String ExceptionMessages::failedToDeleteIndexed(const String& type, const String ...@@ -81,6 +81,11 @@ String ExceptionMessages::failedToDeleteIndexed(const String& type, const String
return "Failed to delete an indexed property from '" + type + "': " + detail; return "Failed to delete an indexed property from '" + type + "': " + detail;
} }
String ExceptionMessages::constructorNotCallableAsFunction(const String& type)
{
return failedToConstruct(type, "Please use the 'new' operator, this DOM object constructor cannot be called as a function.");
}
String ExceptionMessages::incorrectPropertyType(const String& property, const String& detail) String ExceptionMessages::incorrectPropertyType(const String& property, const String& detail)
{ {
return "The '" + property + "' property " + detail; return "The '" + property + "' property " + detail;
......
...@@ -46,9 +46,12 @@ public: ...@@ -46,9 +46,12 @@ public:
ExclusiveBound, ExclusiveBound,
}; };
static String failedToConstruct(const String& type, const String& detail = String()); static String argumentNullOrIncorrectType(int argumentIndex, const String& expectedType);
static String failedToEnumerate(const String& type, const String& detail = String()); static String constructorNotCallableAsFunction(const String& type);
static String failedToExecute(const String& method, const String& type, const String& detail = String());
static String failedToConstruct(const String& type, const String& detail);
static String failedToEnumerate(const String& type, const String& detail);
static String failedToExecute(const String& method, const String& type, const String& detail);
static String failedToGet(const String& property, const String& type, const String& detail); static String failedToGet(const String& property, const String& type, const String& detail);
static String failedToSet(const String& property, const String& type, const String& detail); static String failedToSet(const String& property, const String& type, const String& detail);
static String failedToDelete(const String& property, const String& type, const String& detail); static String failedToDelete(const String& property, const String& type, const String& detail);
...@@ -56,20 +59,13 @@ public: ...@@ -56,20 +59,13 @@ public:
static String failedToSetIndexed(const String& type, const String& detail); static String failedToSetIndexed(const String& type, const String& detail);
static String failedToDeleteIndexed(const String& type, const String& detail); static String failedToDeleteIndexed(const String& type, const String& detail);
static String incorrectPropertyType(const String& property, const String& detail); template <typename NumType>
static String formatNumber(NumType number)
static String argumentNullOrIncorrectType(int argumentIndex, const String& expectedType); {
return formatFiniteNumber(number);
// If > 0, the argument index that failed type check (1-indexed.) }
// If == 0, a (non-argument) value (e.g., a setter) failed the same check.
static String notAnArrayTypeArgumentOrValue(int argumentIndex);
static String notASequenceTypeProperty(const String& propertyName);
static String notAFiniteNumber(double value, const char* name = "value provided");
static String notAFiniteNumber(const Decimal& value, const char* name = "value provided");
static String notEnoughArguments(unsigned expected, unsigned providedleastNumMandatoryParams);
static String readOnly(const char* detail = 0); static String incorrectPropertyType(const String& property, const String& detail);
template <typename NumberType> template <typename NumberType>
static String indexExceedsMaximumBound(const char* name, NumberType given, NumberType bound) static String indexExceedsMaximumBound(const char* name, NumberType given, NumberType bound)
...@@ -123,16 +119,18 @@ public: ...@@ -123,16 +119,18 @@ public:
return result.toString(); return result.toString();
} }
template <typename NumType> // If > 0, the argument index that failed type check (1-indexed.)
static String formatNumber(NumType number) // If == 0, a (non-argument) value (e.g., a setter) failed the same check.
{ static String notAnArrayTypeArgumentOrValue(int argumentIndex);
return formatFiniteNumber(number); static String notASequenceTypeProperty(const String& propertyName);
} static String notAFiniteNumber(double value, const char* name = "value provided");
static String notAFiniteNumber(const Decimal& value, const char* name = "value provided");
private: static String notEnoughArguments(unsigned expected, unsigned providedleastNumMandatoryParams);
static String ordinalNumber(int number);
static String readOnly(const char* detail = 0);
private:
template <typename NumType> template <typename NumType>
static String formatFiniteNumber(NumType number) static String formatFiniteNumber(NumType number)
{ {
...@@ -152,6 +150,8 @@ private: ...@@ -152,6 +150,8 @@ private:
return String::format("%e", number); return String::format("%e", number);
return String::number(number); return String::number(number);
} }
static String ordinalNumber(int number);
}; };
template <> String ExceptionMessages::formatNumber<float>(float number); template <> String ExceptionMessages::formatNumber<float>(float number);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment