Reviewed by Darin.
Test for http://bugs.webkit.org/show_bug.cgi?id=13727
REGRESSION: Reproducible hang setting the selection's extent offset to -1
<rdar://problem/
5206890>
* LayoutTests/editing/selection/selection-invalid-offset-expected.txt: Added.
* LayoutTests/editing/selection/selection-invalid-offset.html: Added.
WebCore:
Reviewed by Darin.
Fix for http://bugs.webkit.org/show_bug.cgi?id=13727
REGRESSION: Reproducible hang setting the selection's extent offset to -1
<rdar://problem/
5206890>
Rise INDEX_SIZE_ERR if used selection index is negative. This matches HTML5 for
getRangeAt() and collapse() which are part of the spec (FF throws NS_ERROR_FAILURE).
Not throwing exceptions yet for too high offsets (except getRangeAt()) as it is
unclear if WebCore's definition of offsets is the same as other browsers.
* bindings/js/kjs_window.cpp:
* WebCore/editing/SelectionController.cpp:
* WebCore/editing/SelectionController.h:
* WebCore/editing/VisiblePosition.cpp:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@21542
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2007-05-17 Antti Koivisto <antti@apple.com>
+
+ Reviewed by Darin.
+
+ Test for http://bugs.webkit.org/show_bug.cgi?id=13727
+ REGRESSION: Reproducible hang setting the selection's extent offset to -1
+ <rdar://problem/5206890>
+
+ * LayoutTests/editing/selection/selection-invalid-offset-expected.txt: Added.
+ * LayoutTests/editing/selection/selection-invalid-offset.html: Added.
+
2007-05-17 Adele Peterson <adele@apple.com>
Reviewed by Mitz.
--- /dev/null
+You should see six OKs below (and not hang):
+OK
+OK
+OK
+OK
+OK
+OK
+
--- /dev/null
+<body>
+You should see six OKs below (and not hang): <br>
+<script>
+if (window.layoutTestController)
+ layoutTestController.dumpAsText();
+var body = document.body;
+var selection = window.getSelection();
+try {
+selection.collapse(body, -1);
+} catch (e) {document.write(((e.code==DOMException.INDEX_SIZE_ERR) ? "OK" : "FAIL")+"<br>"); }
+
+try {
+selection.setBaseAndExtent(body, -1, body, 0);
+} catch (e) {document.write(((e.code==DOMException.INDEX_SIZE_ERR) ? "OK" : "FAIL")+"<br>"); }
+
+try {
+selection.setBaseAndExtent(body, 0, body, -1);
+} catch (e) {document.write(((e.code==DOMException.INDEX_SIZE_ERR) ? "OK" : "FAIL")+"<br>"); }
+
+try {
+selection.setPosition(body, -1);
+} catch (e) {document.write(((e.code==DOMException.INDEX_SIZE_ERR) ? "OK" : "FAIL")+"<br>"); }
+
+try {
+selection.getRangeAt(-1);
+} catch (e) {document.write(((e.code==DOMException.INDEX_SIZE_ERR) ? "OK" : "FAIL")+"<br>"); }
+
+try {
+selection.getRangeAt(10000);
+} catch (e) {document.write(((e.code==DOMException.INDEX_SIZE_ERR) ? "OK" : "FAIL")+"<br>"); }
+
+// these should throw as well but don't at the moment. Just checking they don't crash.
+selection.collapse(body, 10000);
+selection.setBaseAndExtent(body, 1000, body, 0);
+selection.setBaseAndExtent(body, 0, body, 10000);
+selection.setPosition(body, 10000);
+</script>
+2007-05-17 Antti Koivisto <antti@apple.com>
+
+ Reviewed by Darin.
+
+ Fix for http://bugs.webkit.org/show_bug.cgi?id=13727
+ REGRESSION: Reproducible hang setting the selection's extent offset to -1
+ <rdar://problem/5206890>
+
+ Rise INDEX_SIZE_ERR if used selection index is negative. This matches HTML5 for
+ getRangeAt() and collapse() which are part of the spec (FF throws NS_ERROR_FAILURE).
+
+ Not throwing exceptions yet for too high offsets (except getRangeAt()) as it is
+ unclear if WebCore's definition of offsets is the same as other browsers.
+
+ * bindings/js/kjs_window.cpp:
+ * WebCore/editing/SelectionController.cpp:
+ * WebCore/editing/SelectionController.h:
+ * WebCore/editing/VisiblePosition.cpp:
+
2007-05-17 Adele Peterson <adele@apple.com>
Reviewed by Mitz.
Frame *frame = selection->frame();
if (frame) {
SelectionController* s = frame->selectionController();
-
+ ExceptionCode ec = 0;
switch (id) {
case Selection::Collapse:
- s->collapse(toNode(args[0]), args[1]->toInt32(exec));
+ s->collapse(toNode(args[0]), args[1]->toInt32(exec), ec);
break;
case Selection::CollapseToEnd:
s->collapseToEnd();
s->empty();
break;
case Selection::SetBaseAndExtent:
- s->setBaseAndExtent(toNode(args[0]), args[1]->toInt32(exec), toNode(args[2]), args[3]->toInt32(exec));
+ s->setBaseAndExtent(toNode(args[0]), args[1]->toInt32(exec), toNode(args[2]), args[3]->toInt32(exec), ec);
break;
case Selection::SetPosition:
- s->setPosition(toNode(args[0]), args[1]->toInt32(exec));
+ s->setPosition(toNode(args[0]), args[1]->toInt32(exec), ec);
break;
case Selection::Modify:
s->modify(args[0]->toString(exec), args[1]->toString(exec), args[2]->toString(exec));
break;
case Selection::GetRangeAt:
- return toJS(exec, s->getRangeAt(args[0]->toInt32(exec)).get());
+ JSValue* val = toJS(exec, s->getRangeAt(args[0]->toInt32(exec), ec).get());
+ setDOMException(exec, ec);
+ return val;
case Selection::RemoveAllRanges:
s->removeAllRanges();
break;
case Selection::ToString:
return jsString(s->toString());
}
+ setDOMException(exec, ec);
}
return jsUndefined();
#include "Editor.h"
#include "Element.h"
#include "EventNames.h"
+#include "ExceptionCode.h"
#include "FocusController.h"
#include "Frame.h"
#include "FrameTree.h"
return String(plainText(m_sel.toRange().get()));
}
-PassRefPtr<Range> SelectionController::getRangeAt(int index) const
+PassRefPtr<Range> SelectionController::getRangeAt(int index, ExceptionCode& ec) const
{
- return index == 0 ? m_sel.toRange() : 0;
+ if (index < 0 || index >= rangeCount()) {
+ ec = INDEX_SIZE_ERR;
+ return 0;
+ }
+ return m_sel.toRange();
}
void SelectionController::removeAllRanges()
}
}
-void SelectionController::setBaseAndExtent(Node *baseNode, int baseOffset, Node *extentNode, int extentOffset)
+void SelectionController::setBaseAndExtent(Node *baseNode, int baseOffset, Node *extentNode, int extentOffset, ExceptionCode& ec)
{
+ if (baseOffset < 0 || extentOffset < 0) {
+ ec = INDEX_SIZE_ERR;
+ return;
+ }
VisiblePosition visibleBase = VisiblePosition(baseNode, baseOffset, DOWNSTREAM);
VisiblePosition visibleExtent = VisiblePosition(extentNode, extentOffset, DOWNSTREAM);
moveTo(visibleBase, visibleExtent);
}
-void SelectionController::setPosition(Node *node, int offset)
+void SelectionController::setPosition(Node *node, int offset, ExceptionCode& ec)
{
+ if (offset < 0) {
+ ec = INDEX_SIZE_ERR;
+ return;
+ }
moveTo(VisiblePosition(node, offset, DOWNSTREAM));
}
-void SelectionController::collapse(Node *node, int offset)
+void SelectionController::collapse(Node *node, int offset, ExceptionCode& ec)
{
+ if (offset < 0) {
+ ec = INDEX_SIZE_ERR;
+ return;
+ }
moveTo(VisiblePosition(node, offset, DOWNSTREAM));
}
moveTo(VisiblePosition());
}
-void SelectionController::extend(Node *node, int offset)
+void SelectionController::extend(Node *node, int offset, ExceptionCode& ec)
{
+ if (offset < 0) {
+ ec = INDEX_SIZE_ERR;
+ return;
+ }
moveTo(VisiblePosition(node, offset, DOWNSTREAM));
}
int baseOffset() const { return m_sel.base().offset(); }
int extentOffset() const { return m_sel.extent().offset(); }
String type() const;
- void setBaseAndExtent(Node* baseNode, int baseOffset, Node* extentNode, int extentOffset);
- void setPosition(Node*, int offset);
+ void setBaseAndExtent(Node* baseNode, int baseOffset, Node* extentNode, int extentOffset, ExceptionCode&);
+ void setPosition(Node*, int offset, ExceptionCode&);
bool modify(const String& alterString, const String& directionString, const String& granularityString, bool userTriggered = false);
// Mozilla Selection Object API
int focusOffset() const { return m_sel.isBaseFirst() ? m_sel.end().offset() : m_sel.start().offset(); }
bool isCollapsed() const { return !isRange(); }
String toString() const;
- void collapse(Node*, int offset);
+ void collapse(Node*, int offset, ExceptionCode&);
void collapseToEnd();
void collapseToStart();
- void extend(Node*, int offset);
- PassRefPtr<Range> getRangeAt(int index) const;
+ void extend(Node*, int offset, ExceptionCode&);
+ PassRefPtr<Range> getRangeAt(int index, ExceptionCode&) const;
int rangeCount() const { return !isNone() ? 1 : 0; }
void removeAllRanges();
void addRange(const Range*);
VisiblePosition::VisiblePosition(Node *node, int offset, EAffinity affinity)
{
+ ASSERT(offset >= 0);
init(Position(node, offset), affinity);
}