mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 1066432. Update ForOfIterator to the changes in Web IDL's handling of sequences as iterables. We now commit to an iterable if we get a non-undefined value for the Symbol.iterator property, not just if we get a callable value. r=jorendorff
This commit is contained in:
parent
209307a037
commit
9804f71306
@ -56,6 +56,9 @@ TestInterfaceJS.prototype = {
|
||||
get cachedAttr() { return this._cachedAttr; },
|
||||
setCachedAttr: function(n) { this._cachedAttr = n; },
|
||||
clearCachedAttrCache: function () { this.__DOM_IMPL__._clearCachedCachedAttrValue(); },
|
||||
|
||||
testSequenceOverload: function(arg) {},
|
||||
testSequenceUnion: function(arg) {},
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestInterfaceJS])
|
||||
|
@ -50,3 +50,5 @@ skip-if = debug == false
|
||||
[test_throwing_method_noDCE.html]
|
||||
[test_treat_non_object_as_null.html]
|
||||
[test_traceProtos.html]
|
||||
[test_sequence_detection.html]
|
||||
skip-if = debug == false
|
||||
|
54
dom/bindings/test/test_sequence_detection.html
Normal file
54
dom/bindings/test/test_sequence_detection.html
Normal file
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1066432
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1066432</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1066432 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, function() {
|
||||
var testInterfaceJS = new TestInterfaceJS();
|
||||
ok(testInterfaceJS, "got a TestInterfaceJS object");
|
||||
try {
|
||||
testInterfaceJS.testSequenceOverload(
|
||||
{ "@@iterator": 5, [Symbol.iterator]: Array.prototype[Symbol.iterator] });
|
||||
ok(false, "Should have thrown in the overload case");
|
||||
} catch (e) {
|
||||
ise(e.name, "TypeError", "Should get a TypeError for the overload case");
|
||||
alert(e.message);
|
||||
ok(e.message.contains("not iterable"),
|
||||
"Should have a message about being non-iterable in the overload case");
|
||||
}
|
||||
|
||||
try {
|
||||
testInterfaceJS.testSequenceUnion(
|
||||
{ "@@iterator": 5, [Symbol.iterator]: Array.prototype[Symbol.iterator] });
|
||||
ok(false, "Should have thrown in the union case");
|
||||
} catch (e) {
|
||||
ise(e.name, "TypeError", "Should get a TypeError for the union case");
|
||||
alert(e.message);
|
||||
ok(e.message.contains("not iterable"),
|
||||
"Should have a message about being non-iterable in the union case");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1066432">Mozilla Bug 1066432</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -42,4 +42,10 @@ interface TestInterfaceJS {
|
||||
readonly attribute short cachedAttr;
|
||||
void setCachedAttr(short n);
|
||||
void clearCachedAttrCache();
|
||||
|
||||
// Test for sequence overloading and union behavior
|
||||
void testSequenceOverload(sequence<DOMString> arg);
|
||||
void testSequenceOverload(DOMString arg);
|
||||
|
||||
void testSequenceUnion((sequence<DOMString> or DOMString) arg);
|
||||
};
|
||||
|
@ -7,17 +7,19 @@ The tests in this directory exercise the JSAPI.
|
||||
|
||||
If you built JS, you already built the tests.
|
||||
|
||||
If you did `make check` in your JS objdir, you already ran them.
|
||||
|
||||
The tests are built by default when you build JS. All the tests are compiled
|
||||
into a single binary named jsapi-tests. They all run in a single process.
|
||||
|
||||
To run the tests:
|
||||
|
||||
cd $OBJDIR/dist/bin
|
||||
./jsapi-tests
|
||||
|
||||
To run the tests in a debugger:
|
||||
|
||||
cd $OBJDIR/jsapi-tests
|
||||
cd $OBJDIR/dist/bin
|
||||
gdb ./jsapi-tests
|
||||
|
||||
|
||||
--- Creating new tests
|
||||
|
||||
1. You can either add to an existing test*.cpp file or make a new one.
|
||||
|
@ -29,6 +29,7 @@ UNIFIED_SOURCES += [
|
||||
'testException.cpp',
|
||||
'testExternalStrings.cpp',
|
||||
'testFindSCCs.cpp',
|
||||
'testForOfIterator.cpp',
|
||||
'testFreshGlobalEvalRedefinition.cpp',
|
||||
'testFuncCallback.cpp',
|
||||
'testFunctionProperties.cpp',
|
||||
|
53
js/src/jsapi-tests/testForOfIterator.cpp
Normal file
53
js/src/jsapi-tests/testForOfIterator.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
BEGIN_TEST(testForOfIterator_basicNonIterable)
|
||||
{
|
||||
JS::RootedValue v(cx);
|
||||
// Hack to make it simple to produce an object that has a property
|
||||
// named Symbol.iterator.
|
||||
EVAL("var obj = { '@@iterator': 5, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; obj;", &v);
|
||||
JS::ForOfIterator iter(cx);
|
||||
bool ok = iter.init(v);
|
||||
CHECK(!ok);
|
||||
JS_ClearPendingException(cx);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testForOfIterator_basicNonIterable)
|
||||
|
||||
BEGIN_TEST(testForOfIterator_bug515273_part1)
|
||||
{
|
||||
JS::RootedValue v(cx);
|
||||
|
||||
// Hack to make it simple to produce an object that has a property
|
||||
// named Symbol.iterator.
|
||||
EVAL("var obj = { '@@iterator': 5, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; obj;", &v);
|
||||
|
||||
JS::ForOfIterator iter(cx);
|
||||
bool ok = iter.init(v, JS::ForOfIterator::AllowNonIterable);
|
||||
CHECK(!ok);
|
||||
JS_ClearPendingException(cx);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testForOfIterator_bug515273_part1)
|
||||
|
||||
BEGIN_TEST(testForOfIterator_bug515273_part2)
|
||||
{
|
||||
JS::RootedObject obj(cx,
|
||||
JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
|
||||
CHECK(obj);
|
||||
JS::RootedValue v(cx, JS::ObjectValue(*obj));
|
||||
|
||||
JS::ForOfIterator iter(cx);
|
||||
bool ok = iter.init(v, JS::ForOfIterator::AllowNonIterable);
|
||||
CHECK(ok);
|
||||
CHECK(!iter.valueIsIterable());
|
||||
return true;
|
||||
}
|
||||
END_TEST(testForOfIterator_bug515273_part2)
|
@ -5191,10 +5191,10 @@ class MOZ_STACK_CLASS JS_PUBLIC_API(ForOfIterator) {
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the iterator. If AllowNonIterable is passed then if iterable
|
||||
* does not have a callable @@iterator init() will just return true instead
|
||||
* of throwing. Callers should then check valueIsIterable() before
|
||||
* continuing with the iteration.
|
||||
* Initialize the iterator. If AllowNonIterable is passed then if getting
|
||||
* the @@iterator property from iterable returns undefined init() will just
|
||||
* return true instead of throwing. Callers must then check
|
||||
* valueIsIterable() before continuing with the iteration.
|
||||
*/
|
||||
bool init(JS::HandleValue iterable,
|
||||
NonIterableBehavior nonIterableBehavior = ThrowOnNonIterable);
|
||||
|
@ -1366,13 +1366,17 @@ ForOfIterator::init(HandleValue iterable, NonIterableBehavior nonIterableBehavio
|
||||
if (!JSObject::getProperty(cx, iterableObj, iterableObj, cx->names().std_iterator, &callee))
|
||||
return false;
|
||||
|
||||
// Throw if obj[@@iterator] isn't callable if we were asked to do so.
|
||||
// If obj[@@iterator] is undefined and we were asked to allow non-iterables,
|
||||
// bail out now without setting iterator. This will make valueIsIterable(),
|
||||
// which our caller should check, return false.
|
||||
if (nonIterableBehavior == AllowNonIterable && callee.isUndefined())
|
||||
return true;
|
||||
|
||||
// Throw if obj[@@iterator] isn't callable.
|
||||
// js::Invoke is about to check for this kind of error anyway, but it would
|
||||
// throw an inscrutable error message about |method| rather than this nice
|
||||
// one about |obj|.
|
||||
if (!callee.isObject() || !callee.toObject().isCallable()) {
|
||||
if (nonIterableBehavior == AllowNonIterable)
|
||||
return true;
|
||||
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, iterable, NullPtr());
|
||||
if (!bytes)
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user