mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Auto merge of #6378 - Ms2ger:callable, r=nox
<!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6378) <!-- Reviewable:end -->
This commit is contained in:
commit
24af4c4ec6
4 changed files with 28 additions and 30 deletions
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
//! Base classes to work with IDL callbacks.
|
//! Base classes to work with IDL callbacks.
|
||||||
|
|
||||||
|
use dom::bindings::error::{Fallible, Error};
|
||||||
use dom::bindings::global::global_object_for_js_object;
|
use dom::bindings::global::global_object_for_js_object;
|
||||||
use dom::bindings::js::JSRef;
|
use dom::bindings::js::JSRef;
|
||||||
use dom::bindings::utils::Reflectable;
|
use dom::bindings::utils::Reflectable;
|
||||||
|
@ -93,22 +94,20 @@ impl CallbackInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the property with the given `name`, if it is a callable object,
|
/// Returns the property with the given `name`, if it is a callable object,
|
||||||
/// or `Err(())` otherwise. If it returns `Err(())`, a JSAPI exception is
|
/// or an error otherwise.
|
||||||
/// pending.
|
|
||||||
pub fn get_callable_property(&self, cx: *mut JSContext, name: &str)
|
pub fn get_callable_property(&self, cx: *mut JSContext, name: &str)
|
||||||
-> Result<JSVal, ()> {
|
-> Fallible<JSVal> {
|
||||||
let mut callable = UndefinedValue();
|
let mut callable = UndefinedValue();
|
||||||
unsafe {
|
unsafe {
|
||||||
let name = CString::new(name).unwrap();
|
let c_name = CString::new(name).unwrap();
|
||||||
if JS_GetProperty(cx, self.callback(), name.as_ptr(), &mut callable) == 0 {
|
if JS_GetProperty(cx, self.callback(), c_name.as_ptr(), &mut callable) == 0 {
|
||||||
return Err(());
|
return Err(Error::JSFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !callable.is_object() ||
|
if !callable.is_object() ||
|
||||||
JS_ObjectIsCallable(cx, callable.to_object()) == 0 {
|
JS_ObjectIsCallable(cx, callable.to_object()) == 0 {
|
||||||
// FIXME(#347)
|
return Err(Error::Type(
|
||||||
//ThrowErrorMessage(cx, MSG_NOT_CALLABLE, description.get());
|
format!("The value of the {} property is not callable", name)));
|
||||||
return Err(());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(callable)
|
Ok(callable)
|
||||||
|
|
|
@ -5304,10 +5304,8 @@ class CallbackOperationBase(CallbackMethod):
|
||||||
"methodName": self.methodName
|
"methodName": self.methodName
|
||||||
}
|
}
|
||||||
getCallableFromProp = string.Template(
|
getCallableFromProp = string.Template(
|
||||||
'match self.parent.get_callable_property(cx, "${methodName}") {\n'
|
'try!(self.parent.get_callable_property(cx, "${methodName}"))'
|
||||||
' Err(_) => return Err(JSFailed),\n'
|
).substitute(replacements)
|
||||||
' Ok(callable) => callable,\n'
|
|
||||||
'}').substitute(replacements)
|
|
||||||
if not self.singleOperation:
|
if not self.singleOperation:
|
||||||
return 'JS::Rooted<JS::Value> callable(cx);\n' + getCallableFromProp
|
return 'JS::Rooted<JS::Value> callable(cx);\n' + getCallableFromProp
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
[TreeWalker-acceptNode-filter.html]
|
[TreeWalker-acceptNode-filter.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: CRASH
|
[Testing with filter function that throws]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Testing with filter object that throws]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -85,23 +85,21 @@ test(function()
|
||||||
assert_node(walker.currentNode, { type: Element, id: 'B1' });
|
assert_node(walker.currentNode, { type: Element, id: 'B1' });
|
||||||
}, 'Testing with undefined filter');
|
}, 'Testing with undefined filter');
|
||||||
|
|
||||||
// XXX Servo breaks the test when a callback isn't callable
|
|
||||||
test(function()
|
test(function()
|
||||||
{
|
{
|
||||||
var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, {});
|
var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, {});
|
||||||
assert_throws(null, function () { walker.firstChild(); });
|
assert_throws(new TypeError(), function () { walker.firstChild(); });
|
||||||
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
||||||
assert_throws(null, function () { walker.nextNode(); });
|
assert_throws(new TypeError(), function () { walker.nextNode(); });
|
||||||
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
||||||
}, 'Testing with object lacking acceptNode property');
|
}, 'Testing with object lacking acceptNode property');
|
||||||
|
|
||||||
// XXX Servo breaks the test when a callback isn't callable
|
|
||||||
test(function()
|
test(function()
|
||||||
{
|
{
|
||||||
var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, { acceptNode: "foo" });
|
var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, { acceptNode: "foo" });
|
||||||
assert_throws(null, function () { walker.firstChild(); });
|
assert_throws(new TypeError(), function () { walker.firstChild(); });
|
||||||
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
||||||
assert_throws(null, function () { walker.nextNode(); });
|
assert_throws(new TypeError(), function () { walker.nextNode(); });
|
||||||
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
||||||
}, 'Testing with object with non-function acceptNode property');
|
}, 'Testing with object with non-function acceptNode property');
|
||||||
|
|
||||||
|
@ -125,33 +123,31 @@ test(function()
|
||||||
assert_node(walker.firstChild(), { type: Element, id: 'A1' });
|
assert_node(walker.firstChild(), { type: Element, id: 'A1' });
|
||||||
}, 'Testing acceptNode callee');
|
}, 'Testing acceptNode callee');
|
||||||
|
|
||||||
// XXX Looks like Servo is doing something wrong when a callback function throws
|
|
||||||
test(function()
|
test(function()
|
||||||
{
|
{
|
||||||
|
var test_error = { name: "test" };
|
||||||
var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT,
|
var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT,
|
||||||
function(node) {
|
function(node) {
|
||||||
throw('filter exception');
|
throw test_error;
|
||||||
return /*NodeFilter.*/FILTER_ACCEPT;
|
|
||||||
});
|
});
|
||||||
assert_throws(null, function () { walker.firstChild(); });
|
assert_throws(test_error, function () { walker.firstChild(); });
|
||||||
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
||||||
assert_throws(null, function () { walker.nextNode(); });
|
assert_throws(test_error, function () { walker.nextNode(); });
|
||||||
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
||||||
}, 'Testing with filter function that throws');
|
}, 'Testing with filter function that throws');
|
||||||
|
|
||||||
// XXX Looks like Servo is doing something wrong when a callback function throws
|
|
||||||
test(function()
|
test(function()
|
||||||
{
|
{
|
||||||
|
var test_error = { name: "test" };
|
||||||
var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT,
|
var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT,
|
||||||
{
|
{
|
||||||
acceptNode : function(node) {
|
acceptNode : function(node) {
|
||||||
throw('filter exception');
|
throw test_error;
|
||||||
return /*NodeFilter.*/FILTER_ACCEPT;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assert_throws(null, function () { walker.firstChild(); });
|
assert_throws(test_error, function () { walker.firstChild(); });
|
||||||
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
||||||
assert_throws(null, function () { walker.nextNode(); });
|
assert_throws(test_error, function () { walker.nextNode(); });
|
||||||
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
assert_node(walker.currentNode, { type: Element, id: 'root' });
|
||||||
}, 'Testing with filter object that throws');
|
}, 'Testing with filter object that throws');
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue