mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c.
This commit is contained in:
commit
88bb9aa85f
@ -120,7 +120,7 @@ SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent)
|
||||
// Fire caret move event if there's a caret in the selection.
|
||||
nsINode* caretCntrNode =
|
||||
nsCoreUtils::GetDOMNodeFromDOMPoint(sel->GetFocusNode(),
|
||||
sel->GetFocusOffset());
|
||||
sel->FocusOffset());
|
||||
if (!caretCntrNode)
|
||||
return;
|
||||
|
||||
|
@ -182,187 +182,6 @@ HyperTextAccessible::GetBoundsInFrame(nsIFrame* aFrame,
|
||||
return screenRect.ToNearestPixels(presContext->AppUnitsPerDevPixel());
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the specified text.
|
||||
*/
|
||||
nsIFrame*
|
||||
HyperTextAccessible::GetPosAndText(int32_t& aStartOffset, int32_t& aEndOffset,
|
||||
nsAString* aText, nsIFrame** aEndFrame,
|
||||
Accessible** aStartAcc,
|
||||
Accessible** aEndAcc)
|
||||
{
|
||||
aStartOffset = ConvertMagicOffset(aStartOffset);
|
||||
aEndOffset = ConvertMagicOffset(aEndOffset);
|
||||
|
||||
int32_t startOffset = aStartOffset;
|
||||
int32_t endOffset = aEndOffset;
|
||||
// XXX this prevents text interface usage on <input type="password">
|
||||
bool isPassword = (Role() == roles::PASSWORD_TEXT);
|
||||
|
||||
// Clear out parameters and set up loop
|
||||
if (aText) {
|
||||
aText->Truncate();
|
||||
}
|
||||
if (endOffset < 0) {
|
||||
const int32_t kMaxTextLength = 32767;
|
||||
endOffset = kMaxTextLength; // Max end offset
|
||||
}
|
||||
else if (startOffset > endOffset) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIFrame *startFrame = nullptr;
|
||||
nsIFrame* endFrame = nullptr;
|
||||
if (aEndFrame) {
|
||||
*aEndFrame = nullptr;
|
||||
}
|
||||
if (aStartAcc)
|
||||
*aStartAcc = nullptr;
|
||||
if (aEndAcc)
|
||||
*aEndAcc = nullptr;
|
||||
|
||||
nsIntRect unionRect;
|
||||
Accessible* lastAccessible = nullptr;
|
||||
|
||||
gfxSkipChars skipChars;
|
||||
gfxSkipCharsIterator iter;
|
||||
|
||||
// Loop through children and collect valid offsets, text and bounds
|
||||
// depending on what we need for out parameters.
|
||||
uint32_t childCount = ChildCount();
|
||||
for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
Accessible* childAcc = mChildren[childIdx];
|
||||
lastAccessible = childAcc;
|
||||
|
||||
nsIFrame *frame = childAcc->GetFrame();
|
||||
if (!frame) {
|
||||
continue;
|
||||
}
|
||||
endFrame = frame;
|
||||
if (!nsAccUtils::IsEmbeddedObject(childAcc)) {
|
||||
// We only need info up to rendered offset -- that is what we're
|
||||
// converting to content offset
|
||||
int32_t substringEndOffset = -1;
|
||||
uint32_t ourRenderedStart = 0;
|
||||
int32_t ourContentStart = 0;
|
||||
if (frame->GetType() == nsGkAtoms::textFrame) {
|
||||
nsresult rv = frame->GetRenderedText(nullptr, &skipChars, &iter);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
ourRenderedStart = iter.GetSkippedOffset();
|
||||
ourContentStart = iter.GetOriginalOffset();
|
||||
substringEndOffset =
|
||||
iter.ConvertOriginalToSkipped(skipChars.GetOriginalCharCount() +
|
||||
ourContentStart) - ourRenderedStart;
|
||||
}
|
||||
}
|
||||
if (substringEndOffset < 0) {
|
||||
// XXX for non-textframe text like list bullets,
|
||||
// should go away after list bullet rewrite
|
||||
substringEndOffset = nsAccUtils::TextLength(childAcc);
|
||||
}
|
||||
if (startOffset < substringEndOffset ||
|
||||
(startOffset == substringEndOffset && (childIdx == childCount - 1))) {
|
||||
// Our start is within this substring
|
||||
if (startOffset > 0 || endOffset < substringEndOffset) {
|
||||
// We don't want the whole string for this accessible
|
||||
// Get out the continuing text frame with this offset
|
||||
int32_t outStartLineUnused;
|
||||
int32_t contentOffset;
|
||||
if (frame->GetType() == nsGkAtoms::textFrame) {
|
||||
contentOffset = iter.ConvertSkippedToOriginal(startOffset) +
|
||||
ourRenderedStart - ourContentStart;
|
||||
}
|
||||
else {
|
||||
contentOffset = startOffset;
|
||||
}
|
||||
frame->GetChildFrameContainingOffset(contentOffset, true,
|
||||
&outStartLineUnused, &frame);
|
||||
if (aEndFrame) {
|
||||
*aEndFrame = frame; // We ended in the current frame
|
||||
if (aEndAcc)
|
||||
NS_ADDREF(*aEndAcc = childAcc);
|
||||
}
|
||||
if (substringEndOffset > endOffset) {
|
||||
// Need to stop before the end of the available text
|
||||
substringEndOffset = endOffset;
|
||||
}
|
||||
aEndOffset = endOffset;
|
||||
}
|
||||
if (aText) {
|
||||
if (isPassword) {
|
||||
for (int32_t count = startOffset; count < substringEndOffset; count ++)
|
||||
*aText += '*'; // Show *'s only for password text
|
||||
}
|
||||
else {
|
||||
childAcc->AppendTextTo(*aText, startOffset,
|
||||
substringEndOffset - startOffset);
|
||||
}
|
||||
}
|
||||
if (!startFrame) {
|
||||
startFrame = frame;
|
||||
aStartOffset = startOffset;
|
||||
if (aStartAcc)
|
||||
NS_ADDREF(*aStartAcc = childAcc);
|
||||
}
|
||||
// We already started copying in this accessible's string,
|
||||
// for the next accessible we'll start at offset 0
|
||||
startOffset = 0;
|
||||
}
|
||||
else {
|
||||
// We have not found the start position yet, get the new startOffset
|
||||
// that is relative to next accessible
|
||||
startOffset -= substringEndOffset;
|
||||
}
|
||||
// The endOffset needs to be relative to the new startOffset
|
||||
endOffset -= substringEndOffset;
|
||||
}
|
||||
else {
|
||||
// Embedded object, append marker
|
||||
// XXX Append \n for <br>'s
|
||||
if (startOffset >= 1) {
|
||||
-- startOffset;
|
||||
}
|
||||
else {
|
||||
if (endOffset > 0) {
|
||||
if (aText) {
|
||||
// XXX: should use nsIAccessible::AppendTextTo.
|
||||
if (frame->GetType() == nsGkAtoms::brFrame) {
|
||||
*aText += kForcedNewLineChar;
|
||||
} else if (nsAccUtils::MustPrune(this)) {
|
||||
*aText += kImaginaryEmbeddedObjectChar;
|
||||
// Expose imaginary embedded object character if the accessible
|
||||
// hans't children.
|
||||
} else {
|
||||
*aText += kEmbeddedObjectChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!startFrame) {
|
||||
startFrame = frame;
|
||||
aStartOffset = 0;
|
||||
if (aStartAcc)
|
||||
NS_ADDREF(*aStartAcc = childAcc);
|
||||
}
|
||||
}
|
||||
-- endOffset;
|
||||
}
|
||||
if (endOffset <= 0 && startFrame) {
|
||||
break; // If we don't have startFrame yet, get that in next loop iteration
|
||||
}
|
||||
}
|
||||
|
||||
if (aStartAcc && !*aStartAcc) {
|
||||
NS_IF_ADDREF(*aStartAcc = lastAccessible);
|
||||
}
|
||||
if (aEndFrame && !*aEndFrame) {
|
||||
*aEndFrame = endFrame;
|
||||
if (aEndAcc && !*aEndAcc)
|
||||
NS_IF_ADDREF(*aEndAcc = lastAccessible);
|
||||
}
|
||||
|
||||
return startFrame;
|
||||
}
|
||||
|
||||
void
|
||||
HyperTextAccessible::TextSubstring(int32_t aStartOffset, int32_t aEndOffset,
|
||||
nsAString& aText)
|
||||
@ -622,46 +441,47 @@ HyperTextAccessible::FindOffset(int32_t aOffset, nsDirection aDirection,
|
||||
nsSelectionAmount aAmount,
|
||||
EWordMovementType aWordMovementType)
|
||||
{
|
||||
// Convert hypertext offset to frame-relative offset.
|
||||
int32_t offsetInFrame = aOffset, notUsedOffset = aOffset;
|
||||
nsRefPtr<Accessible> accAtOffset;
|
||||
nsIFrame* frameAtOffset =
|
||||
GetPosAndText(offsetInFrame, notUsedOffset, nullptr, nullptr,
|
||||
getter_AddRefs(accAtOffset));
|
||||
if (!frameAtOffset) {
|
||||
if (aOffset == CharacterCount()) {
|
||||
// Asking for start of line, while on last character.
|
||||
if (accAtOffset)
|
||||
frameAtOffset = accAtOffset->GetFrame();
|
||||
}
|
||||
NS_ASSERTION(frameAtOffset, "No start frame for text getting!");
|
||||
if (!frameAtOffset)
|
||||
// Find a leaf accessible frame to start with. PeekOffset wants this.
|
||||
HyperTextAccessible* text = this;
|
||||
Accessible* child = nullptr;
|
||||
int32_t innerOffset = aOffset;
|
||||
|
||||
do {
|
||||
int32_t childIdx = text->GetChildIndexAtOffset(innerOffset);
|
||||
NS_ASSERTION(childIdx != -1, "Bad in offset!");
|
||||
if (childIdx == -1)
|
||||
return -1;
|
||||
|
||||
// We're on the last continuation since we're on the last character.
|
||||
frameAtOffset = frameAtOffset->LastContinuation();
|
||||
child = text->GetChildAt(childIdx);
|
||||
innerOffset -= text->GetChildOffset(childIdx);
|
||||
|
||||
text = child->AsHyperText();
|
||||
} while (text);
|
||||
|
||||
nsIFrame* childFrame = child->GetFrame();
|
||||
NS_ENSURE_TRUE(childFrame, -1);
|
||||
|
||||
int32_t innerContentOffset = innerOffset;
|
||||
if (child->IsTextLeaf()) {
|
||||
NS_ASSERTION(childFrame->GetType() == nsGkAtoms::textFrame, "Wrong frame!");
|
||||
RenderedToContentOffset(childFrame, innerOffset, &innerContentOffset);
|
||||
}
|
||||
|
||||
// Return hypertext offset of the boundary of the found word.
|
||||
int32_t contentOffset = offsetInFrame;
|
||||
nsIFrame* primaryFrame = accAtOffset->GetFrame();
|
||||
NS_ENSURE_TRUE(primaryFrame, -1);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (primaryFrame->GetType() == nsGkAtoms::textFrame) {
|
||||
rv = RenderedToContentOffset(primaryFrame, offsetInFrame, &contentOffset);
|
||||
NS_ENSURE_SUCCESS(rv, -1);
|
||||
}
|
||||
nsIFrame* frameAtOffset = childFrame;
|
||||
int32_t unusedOffsetInFrame = 0;
|
||||
childFrame->GetChildFrameContainingOffset(innerContentOffset, true,
|
||||
&unusedOffsetInFrame,
|
||||
&frameAtOffset);
|
||||
|
||||
const bool kIsJumpLinesOk = true; // okay to jump lines
|
||||
const bool kIsScrollViewAStop = false; // do not stop at scroll views
|
||||
const bool kIsKeyboardSelect = true; // is keyboard selection
|
||||
const bool kIsVisualBidi = false; // use visual order for bidi text
|
||||
nsPeekOffsetStruct pos(aAmount, aDirection, contentOffset,
|
||||
nsPeekOffsetStruct pos(aAmount, aDirection, innerContentOffset,
|
||||
0, kIsJumpLinesOk, kIsScrollViewAStop,
|
||||
kIsKeyboardSelect, kIsVisualBidi,
|
||||
aWordMovementType);
|
||||
rv = frameAtOffset->PeekOffset(&pos);
|
||||
nsresult rv = frameAtOffset->PeekOffset(&pos);
|
||||
|
||||
// PeekOffset fails on last/first lines of the text in certain cases.
|
||||
if (NS_FAILED(rv) && aAmount == eSelectLine) {
|
||||
@ -1339,7 +1159,7 @@ HyperTextAccessible::CaretOffset() const
|
||||
NS_ENSURE_TRUE(domSel, -1);
|
||||
|
||||
nsINode* focusNode = domSel->GetFocusNode();
|
||||
int32_t focusOffset = domSel->GetFocusOffset();
|
||||
uint32_t focusOffset = domSel->FocusOffset();
|
||||
|
||||
// No caret if this DOM node is inside of focused node but the selection's
|
||||
// focus point is not inside of this DOM node.
|
||||
@ -1381,7 +1201,7 @@ HyperTextAccessible::CaretLineNumber()
|
||||
return -1;
|
||||
|
||||
int32_t returnOffsetUnused;
|
||||
int32_t caretOffset = domSel->GetFocusOffset();
|
||||
uint32_t caretOffset = domSel->FocusOffset();
|
||||
nsFrameSelection::HINT hint = frameSelection->GetHint();
|
||||
nsIFrame *caretFrame = frameSelection->GetFrameForNodeOffset(caretContent, caretOffset,
|
||||
hint, &returnOffsetUnused);
|
||||
|
@ -448,35 +448,6 @@ protected:
|
||||
nsSelectionAmount aAmount,
|
||||
EWordMovementType aWordMovementType = eDefaultBehavior);
|
||||
|
||||
/**
|
||||
* Provides information for substring that is defined by the given start
|
||||
* and end offsets for this hyper text.
|
||||
*
|
||||
* @param aStartOffset [inout] the start offset into the hyper text. This
|
||||
* is also an out parameter used to return the offset
|
||||
* into the start frame's rendered text content
|
||||
* (start frame is the @return)
|
||||
*
|
||||
* @param aEndOffset [inout] the end offset into the hyper text. This is
|
||||
* also an out parameter used to return
|
||||
* the offset into the end frame's rendered
|
||||
* text content.
|
||||
*
|
||||
* @param aText [out, optional] return the substring's text
|
||||
* @param aEndFrame [out, optional] return the end frame for this
|
||||
* substring
|
||||
* @param aStartAcc [out, optional] return the start accessible for this
|
||||
* substring
|
||||
* @param aEndAcc [out, optional] return the end accessible for this
|
||||
* substring
|
||||
* @return the start frame for this substring
|
||||
*/
|
||||
nsIFrame* GetPosAndText(int32_t& aStartOffset, int32_t& aEndOffset,
|
||||
nsAString *aText = nullptr,
|
||||
nsIFrame **aEndFrame = nullptr,
|
||||
Accessible** aStartAcc = nullptr,
|
||||
Accessible** aEndAcc = nullptr);
|
||||
|
||||
/**
|
||||
* Return the boundaries of the substring in case of textual frame or
|
||||
* frame boundaries in case of non textual frame, offsets are ignored.
|
||||
|
@ -222,6 +222,19 @@
|
||||
[ 18, "ml_edivbr1", kTodo, kTodo, kOk ] ] ],
|
||||
[ 19, 19, "", 19, 19 ] ]);
|
||||
|
||||
// a <a href="#">b</a>
|
||||
// a *
|
||||
testTextBeforeOffset("cntr_1", BOUNDARY_WORD_START,
|
||||
[ [ 0, 1, "", 0, 0 ],
|
||||
[ 2, 3, "a ", 0, 2 ] ]);
|
||||
|
||||
testTextAtOffset("cntr_1", BOUNDARY_WORD_START,
|
||||
[ [ 0, 1, "a ", 0, 2 ],
|
||||
[ 2, 3, kEmbedChar, 2, 3 ] ]);
|
||||
testTextAfterOffset("cntr_1", BOUNDARY_WORD_START,
|
||||
[ [ 0, 1, kEmbedChar, 2, 3 ],
|
||||
[ 2, 3, "", 3, 3 ] ]);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -280,5 +293,6 @@ two words
|
||||
</textarea>
|
||||
</pre>
|
||||
|
||||
<div id="cntr_1">a <a href="#">b</a></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -84,7 +84,7 @@ pref("mozilla.widget.force-24bpp", true);
|
||||
pref("mozilla.widget.use-buffer-pixmap", true);
|
||||
pref("mozilla.widget.disable-native-theme", true);
|
||||
pref("layout.reflow.synthMouseMove", false);
|
||||
pref("layers.force-tiles", false);
|
||||
pref("layers.enable-tiles", false);
|
||||
|
||||
/* download manager (don't show the window or alert) */
|
||||
pref("browser.download.useDownloadDir", true);
|
||||
|
@ -84,14 +84,64 @@ var gPluginHandler = {
|
||||
return newName;
|
||||
},
|
||||
|
||||
isTooSmall : function (plugin, overlay) {
|
||||
/**
|
||||
* Update the visibility of the plugin overlay.
|
||||
*/
|
||||
setVisibility : function (plugin, overlay, shouldShow) {
|
||||
overlay.classList.toggle("visible", shouldShow);
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether the plugin should be visible on the page. A plugin should
|
||||
* not be visible if the overlay is too big, or if any other page content
|
||||
* overlays it.
|
||||
*
|
||||
* This function will handle showing or hiding the overlay.
|
||||
* @returns true if the plugin is invisible.
|
||||
*/
|
||||
shouldShowOverlay : function (plugin, overlay) {
|
||||
// If the overlay size is 0, we haven't done layout yet. Presume that
|
||||
// plugins are visible until we know otherwise.
|
||||
if (overlay.scrollWidth == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Is the <object>'s size too small to hold what we want to show?
|
||||
let pluginRect = plugin.getBoundingClientRect();
|
||||
// XXX bug 446693. The text-shadow on the submitted-report text at
|
||||
// the bottom causes scrollHeight to be larger than it should be.
|
||||
let overflows = (overlay.scrollWidth > pluginRect.width) ||
|
||||
(overlay.scrollHeight - 5 > pluginRect.height);
|
||||
return overflows;
|
||||
if (overflows) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the plugin covered up by other content so that it is not clickable?
|
||||
// Floating point can confuse .elementFromPoint, so inset just a bit
|
||||
let left = pluginRect.left + 2;
|
||||
let right = pluginRect.right - 2;
|
||||
let top = pluginRect.top + 2;
|
||||
let bottom = pluginRect.bottom - 2;
|
||||
let centerX = left + (right - left) / 2;
|
||||
let centerY = top + (bottom - top) / 2;
|
||||
let points = [[left, top],
|
||||
[left, bottom],
|
||||
[right, top],
|
||||
[right, bottom],
|
||||
[centerX, centerY]];
|
||||
|
||||
if (right <= 0 || top <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let [x, y] of points) {
|
||||
let el = plugin.ownerDocument.elementFromPoint(x, y);
|
||||
if (el !== plugin) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
addLinkClickCallback: function (linkNode, callbackName /*callbackArgs...*/) {
|
||||
@ -319,26 +369,18 @@ var gPluginHandler = {
|
||||
if (eventType != "PluginCrashed") {
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (overlay != null) {
|
||||
if (!this.isTooSmall(plugin, overlay))
|
||||
overlay.style.visibility = "visible";
|
||||
|
||||
plugin.addEventListener("overflow", function(event) {
|
||||
overlay.style.visibility = "hidden";
|
||||
gPluginHandler._setPluginNotificationIcon(browser);
|
||||
});
|
||||
plugin.addEventListener("underflow", function(event) {
|
||||
// this is triggered if only one dimension underflows,
|
||||
// the other dimension might still overflow
|
||||
if (!gPluginHandler.isTooSmall(plugin, overlay)) {
|
||||
overlay.style.visibility = "visible";
|
||||
}
|
||||
gPluginHandler._setPluginNotificationIcon(browser);
|
||||
});
|
||||
this.setVisibility(plugin, overlay,
|
||||
this.shouldShowOverlay(plugin, overlay));
|
||||
let resizeListener = (event) => {
|
||||
this.setVisibility(plugin, overlay,
|
||||
this.shouldShowOverlay(plugin, overlay));
|
||||
this._setPluginNotificationIcon(browser);
|
||||
};
|
||||
plugin.addEventListener("overflow", resizeListener);
|
||||
plugin.addEventListener("underflow", resizeListener);
|
||||
}
|
||||
}
|
||||
|
||||
// Only show the notification after we've done the isTooSmall check, so
|
||||
// that the notification can decide whether to show the "alert" icon
|
||||
if (shouldShowNotification) {
|
||||
this._showClickToPlayNotification(browser, plugin, false);
|
||||
}
|
||||
@ -378,8 +420,9 @@ var gPluginHandler = {
|
||||
|
||||
hideClickToPlayOverlay: function(aPlugin) {
|
||||
let overlay = this.getPluginUI(aPlugin, "main");
|
||||
if (overlay)
|
||||
overlay.style.visibility = "hidden";
|
||||
if (overlay) {
|
||||
overlay.classList.remove("visible");
|
||||
}
|
||||
},
|
||||
|
||||
stopPlayPreview: function PH_stopPlayPreview(aPlugin, aPlayPlugin) {
|
||||
@ -530,8 +573,9 @@ var gPluginHandler = {
|
||||
let overlay = this.getPluginUI(aPlugin, "main");
|
||||
|
||||
if (pluginPermission == Ci.nsIPermissionManager.DENY_ACTION) {
|
||||
if (overlay)
|
||||
overlay.style.visibility = "hidden";
|
||||
if (overlay) {
|
||||
overlay.classList.remove("visible");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -929,7 +973,9 @@ var gPluginHandler = {
|
||||
if (!overlay) {
|
||||
continue;
|
||||
}
|
||||
if (!this.isTooSmall(plugin, overlay)) {
|
||||
let shouldShow = this.shouldShowOverlay(plugin, overlay);
|
||||
this.setVisibility(plugin, overlay, shouldShow);
|
||||
if (shouldShow) {
|
||||
actions.delete(info.permissionString);
|
||||
if (actions.size == 0) {
|
||||
break;
|
||||
@ -1186,22 +1232,18 @@ var gPluginHandler = {
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox(browser);
|
||||
|
||||
let isShowing = true;
|
||||
let isShowing = this.shouldShowOverlay(plugin, overlay);
|
||||
|
||||
// Is the <object>'s size too small to hold what we want to show?
|
||||
if (this.isTooSmall(plugin, overlay)) {
|
||||
if (!isShowing) {
|
||||
// First try hiding the crash report submission UI.
|
||||
statusDiv.removeAttribute("status");
|
||||
|
||||
if (this.isTooSmall(plugin, overlay)) {
|
||||
// Hide the overlay's contents. Use visibility style, so that it doesn't
|
||||
// collapse down to 0x0.
|
||||
isShowing = false;
|
||||
}
|
||||
isShowing = this.shouldShowOverlay(plugin, overlay);
|
||||
}
|
||||
this.setVisibility(plugin, overlay, isShowing);
|
||||
|
||||
if (isShowing) {
|
||||
overlay.style.visibility = "visible";
|
||||
// If a previous plugin on the page was too small and resulted in adding a
|
||||
// notification bar, then remove it because this plugin instance it big
|
||||
// enough to serve as in-content notification.
|
||||
|
@ -72,6 +72,8 @@ support-files =
|
||||
plugin_clickToPlayDeny.html
|
||||
plugin_data_url.html
|
||||
plugin_hidden_to_visible.html
|
||||
plugin_overlayed.html
|
||||
plugin_positioned.html
|
||||
plugin_small.html
|
||||
plugin_syncRemoved.html
|
||||
plugin_test.html
|
||||
|
@ -71,9 +71,9 @@ function test1() {
|
||||
|
||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
let doc = gTestBrowser.contentDocument;
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(overlay, "Test 1, Should have an overlay.");
|
||||
is(window.getComputedStyle(overlay).visibility, 'hidden', "Test 1, Overlay should be hidden");
|
||||
ok(!overlay.classList.contains("visible"), "Test 1, Overlay should be hidden");
|
||||
|
||||
plugin.style.width = '300px';
|
||||
executeSoon(test2);
|
||||
@ -82,34 +82,34 @@ function test1() {
|
||||
function test2() {
|
||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
let doc = gTestBrowser.contentDocument;
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(overlay, "Test 2, Should have an overlay.");
|
||||
is(window.getComputedStyle(overlay).visibility, 'hidden', "Test 2, Overlay should be hidden");
|
||||
ok(!overlay.classList.contains("visible"), "Test 2, Overlay should be hidden");
|
||||
|
||||
plugin.style.height = '300px';
|
||||
let condition = () => window.getComputedStyle(overlay).visibility == 'visible';
|
||||
let condition = () => overlay.classList.contains("visible");
|
||||
waitForCondition(condition, test3, "Test 2, Waited too long for overlay to become visible");
|
||||
}
|
||||
|
||||
function test3() {
|
||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
let doc = gTestBrowser.contentDocument;
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(overlay, "Test 3, Should have an overlay.");
|
||||
is(window.getComputedStyle(overlay).visibility, 'visible', "Test 3, Overlay should be visible");
|
||||
ok(overlay.classList.contains("visible"), "Test 3, Overlay should be visible");
|
||||
|
||||
plugin.style.width = '10px';
|
||||
plugin.style.height = '10px';
|
||||
let condition = () => window.getComputedStyle(overlay).visibility == 'hidden';
|
||||
let condition = () => !overlay.classList.contains("visible");
|
||||
waitForCondition(condition, test4, "Test 3, Waited too long for overlay to become hidden");
|
||||
}
|
||||
|
||||
function test4() {
|
||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
let doc = gTestBrowser.contentDocument;
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(overlay, "Test 4, Should have an overlay.");
|
||||
is(window.getComputedStyle(overlay).visibility, 'hidden', "Test 4, Overlay should be hidden");
|
||||
ok(!overlay.classList.contains("visible"), "Test 4, Overlay should be hidden");
|
||||
|
||||
clearAllPluginPermissions();
|
||||
finishTest();
|
||||
|
@ -324,7 +324,7 @@ function test14() {
|
||||
function test15() {
|
||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var mainBox = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
var mainBox = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(mainBox, "Test 15, Plugin with id=" + plugin.id + " overlay should exist");
|
||||
|
||||
prepareTest(runAfterPluginBindingAttached(test17), gTestRoot + "plugin_bug749455.html");
|
||||
@ -356,8 +356,8 @@ function test18a() {
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, "Test 18a, plugin fallback type should be PLUGIN_VULNERABLE_UPDATABLE");
|
||||
ok(!objLoadingContent.activated, "Test 18a, Plugin should not be activated");
|
||||
var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
ok(overlay.style.visibility != "hidden", "Test 18a, Plugin overlay should exist, not be hidden");
|
||||
var overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(overlay.classList.contains("visible"), "Test 18a, Plugin overlay should exist, not be hidden");
|
||||
var updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink");
|
||||
ok(updateLink.style.visibility != "hidden", "Test 18a, Plugin should have an update link");
|
||||
|
||||
@ -380,8 +380,8 @@ function test18b() {
|
||||
var plugin = doc.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(!objLoadingContent.activated, "Test 18b, Plugin should not be activated");
|
||||
var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
ok(overlay.style.visibility != "hidden", "Test 18b, Plugin overlay should exist, not be hidden");
|
||||
var overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(overlay.classList.contains("visible"), "Test 18b, Plugin overlay should exist, not be hidden");
|
||||
|
||||
setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableNoUpdate.xml",
|
||||
function() {
|
||||
@ -399,8 +399,8 @@ function test18c() {
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE, "Test 18c, plugin fallback type should be PLUGIN_VULNERABLE_NO_UPDATE");
|
||||
ok(!objLoadingContent.activated, "Test 18c, Plugin should not be activated");
|
||||
var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
ok(overlay.style.visibility != "hidden", "Test 18c, Plugin overlay should exist, not be hidden");
|
||||
var overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(overlay.classList.contains("visible"), "Test 18c, Plugin overlay should exist, not be hidden");
|
||||
var updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink");
|
||||
ok(updateLink.style.display != "block", "Test 18c, Plugin should not have an update link");
|
||||
|
||||
@ -528,7 +528,7 @@ function test20a() {
|
||||
ok(!clickToPlayNotification, "Test 20a, Should not have a click-to-play notification");
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("plugin");
|
||||
var mainBox = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
var mainBox = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(mainBox, "Test 20a, plugin overlay should not be null");
|
||||
var pluginRect = mainBox.getBoundingClientRect();
|
||||
ok(pluginRect.width == 0, "Test 20a, plugin should have an overlay with 0px width");
|
||||
@ -551,7 +551,7 @@ function test20b() {
|
||||
ok(clickToPlayNotification, "Test 20b, Should now have a click-to-play notification");
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("plugin");
|
||||
var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
|
||||
var pluginRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
|
||||
ok(pluginRect.width == 200, "Test 20b, plugin should have an overlay with 200px width");
|
||||
ok(pluginRect.height == 200, "Test 20b, plugin should have an overlay with 200px height");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
@ -575,7 +575,7 @@ function test20c() {
|
||||
function test20d() {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("plugin");
|
||||
var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
|
||||
var pluginRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
|
||||
ok(pluginRect.width == 0, "Test 20d, plugin should have click-to-play overlay with zero width");
|
||||
ok(pluginRect.height == 0, "Test 20d, plugin should have click-to-play overlay with zero height");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
@ -595,7 +595,7 @@ function test21a() {
|
||||
var ids = ["test", "secondtestA", "secondtestB"];
|
||||
for (var id of ids) {
|
||||
var plugin = doc.getElementById(id);
|
||||
var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
|
||||
var rect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
|
||||
ok(rect.width == 200, "Test 21a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
|
||||
ok(rect.height == 200, "Test 21a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
@ -645,7 +645,7 @@ function test21c() {
|
||||
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("test");
|
||||
var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
|
||||
var rect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
|
||||
ok(rect.width == 0, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 0px width after being clicked");
|
||||
ok(rect.height == 0, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 0px height after being clicked");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
@ -654,7 +654,7 @@ function test21c() {
|
||||
var ids = ["secondtestA", "secondtestB"];
|
||||
for (var id of ids) {
|
||||
var plugin = doc.getElementById(id);
|
||||
var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
|
||||
var rect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
|
||||
ok(rect.width == 200, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
|
||||
ok(rect.height == 200, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
@ -699,7 +699,7 @@ function test21e() {
|
||||
var ids = ["test", "secondtestA", "secondtestB"];
|
||||
for (var id of ids) {
|
||||
var plugin = doc.getElementById(id);
|
||||
var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
|
||||
var rect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
|
||||
ok(rect.width == 0, "Test 21e, Plugin with id=" + plugin.id + " overlay rect should have 0px width after being clicked");
|
||||
ok(rect.height == 0, "Test 21e, Plugin with id=" + plugin.id + " overlay rect should have 0px height after being clicked");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
@ -870,6 +870,56 @@ function test27() {
|
||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
|
||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null,
|
||||
finishTest,
|
||||
() => {
|
||||
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
|
||||
prepareTest(test28, gTestRoot + "plugin_overlayed.html");
|
||||
},
|
||||
"Test 27, expected to not have a plugin notification bar");
|
||||
}
|
||||
|
||||
function test28() {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||
ok(notification, "Test 28: There should be a plugin notification");
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
||||
test28b,
|
||||
"Test 28, expected the plugin infobar to be triggered when plugin was overlayed");
|
||||
}
|
||||
|
||||
function test28b()
|
||||
{
|
||||
let doc = gTestBrowser.contentDocument;
|
||||
let plugin = doc.getElementById("test");
|
||||
ok(plugin, "Test 28b, Found plugin in page");
|
||||
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(plugin.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 28b, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
|
||||
ok(!plugin.activated, "Test 28b, Plugin should not be activated");
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(!overlay.classList.contains("visible"), "Test 28b, Plugin overlay should be hidden");
|
||||
|
||||
prepareTest(test29, gTestRoot + "plugin_positioned.html");
|
||||
}
|
||||
|
||||
function test29() {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||
ok(notification, "Test 29: There should be a plugin notification");
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
||||
test29b,
|
||||
"Test 29, expected the plugin infobar to be triggered when plugin was overlayed");
|
||||
}
|
||||
|
||||
function test29b() {
|
||||
let doc = gTestBrowser.contentDocument;
|
||||
let plugin = doc.getElementById("test");
|
||||
ok(plugin, "Test 29b, Found plugin in page");
|
||||
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(plugin.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 29b, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
|
||||
ok(!plugin.activated, "Test 29b, Plugin should not be activated");
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(!overlay.classList.contains("visible"), "Test 29b, Plugin overlay should be hidden");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
27
browser/base/content/test/general/plugin_overlayed.html
Normal file
27
browser/base/content/test/general/plugin_overlayed.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style type="text/css">
|
||||
.absthing {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 20px;
|
||||
}
|
||||
#d1 {
|
||||
z-index: 1;
|
||||
}
|
||||
#d2 {
|
||||
z-index: 2;
|
||||
background-color: rgba(0,0,255,0.5);
|
||||
border: 1px solid red;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="absthing" id="d1">
|
||||
<embed id="test" type="application/x-test">
|
||||
</div>
|
||||
<div class="absthing" id="d2">
|
||||
<p>This is overlaying
|
||||
</div>
|
12
browser/base/content/test/general/plugin_positioned.html
Normal file
12
browser/base/content/test/general/plugin_positioned.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style type="text/css">
|
||||
#test {
|
||||
position: absolute;
|
||||
left: -1000px;
|
||||
top: -1000px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<embed id="test" type="application/x-test">
|
@ -103,9 +103,7 @@ function getStorageEntryCount(device, goon) {
|
||||
}
|
||||
|
||||
function get_cache_for_private_window () {
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
win.addEventListener("load", function () {
|
||||
win.removeEventListener("load", arguments.callee, false);
|
||||
let win = whenNewWindowLoaded({private: true}, function() {
|
||||
|
||||
executeSoon(function() {
|
||||
|
||||
@ -135,5 +133,5 @@ function get_cache_for_private_window () {
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
@ -70,6 +70,16 @@ var Browser = {
|
||||
dump("###########" + e + "\n");
|
||||
}
|
||||
|
||||
if (!Services.metro) {
|
||||
// Services.metro is only available on Windows Metro. We want to be able
|
||||
// to test metro on other platforms, too, so we provide a minimal shim.
|
||||
Services.metro = {
|
||||
activationURI: "",
|
||||
pinTileAsync: function () {},
|
||||
unpinTileAsync: function () {}
|
||||
};
|
||||
}
|
||||
|
||||
/* handles dispatching clicks on browser into clicks in content or zooms */
|
||||
Elements.browsers.customDragger = new Browser.MainDragger();
|
||||
|
||||
|
@ -259,7 +259,7 @@ MOZ_ARG_WITH_STRING(android-sdk,
|
||||
location where the Android SDK can be found (base directory, e.g. .../android/platforms/android-6)],
|
||||
android_sdk=$withval)
|
||||
|
||||
android_sdk_root=$withval/../../
|
||||
android_sdk_root=${withval%/platforms/android-*}
|
||||
|
||||
case "$target" in
|
||||
*-android*|*-linuxandroid*)
|
||||
|
@ -506,13 +506,14 @@ public:
|
||||
nsIURI* aBaseURI);
|
||||
|
||||
/**
|
||||
* Convert aInput (in charset aCharset) to UTF16 in aOutput.
|
||||
* Convert aInput (in encoding aEncoding) to UTF16 in aOutput.
|
||||
*
|
||||
* @param aCharset the name of the charset; if empty, we assume UTF8
|
||||
* @param aEncoding the Gecko-canonical name of the encoding or the empty
|
||||
* string (meaning UTF-8)
|
||||
*/
|
||||
static nsresult ConvertStringFromCharset(const nsACString& aCharset,
|
||||
const nsACString& aInput,
|
||||
nsAString& aOutput);
|
||||
static nsresult ConvertStringFromEncoding(const nsACString& aEncoding,
|
||||
const nsACString& aInput,
|
||||
nsAString& aOutput);
|
||||
|
||||
/**
|
||||
* Determine whether a buffer begins with a BOM for UTF-8, UTF-16LE,
|
||||
@ -526,9 +527,6 @@ public:
|
||||
static bool CheckForBOM(const unsigned char* aBuffer, uint32_t aLength,
|
||||
nsACString& aCharset);
|
||||
|
||||
static nsresult GuessCharset(const char *aData, uint32_t aDataLen,
|
||||
nsACString &aCharset);
|
||||
|
||||
static nsresult CheckQName(const nsAString& aQualifiedName,
|
||||
bool aNamespaceAware = true,
|
||||
const PRUnichar** aColon = nullptr);
|
||||
|
@ -1307,6 +1307,9 @@ private:
|
||||
NodeHandlingClick,
|
||||
// Set if the node has had :hover selectors matched against it
|
||||
NodeHasRelevantHoverRules,
|
||||
// Set if the element has a parser insertion mode other than "in body",
|
||||
// per the HTML5 "Parse state" section.
|
||||
ElementHasWeirdParserInsertionMode,
|
||||
// Guard value
|
||||
BooleanFlagCount
|
||||
};
|
||||
@ -1466,6 +1469,9 @@ protected:
|
||||
void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
|
||||
bool HasLockedStyleStates() const
|
||||
{ return GetBoolFlag(ElementHasLockedStyleStates); }
|
||||
void SetHasWeirdParserInsertionMode() { SetBoolFlag(ElementHasWeirdParserInsertionMode); }
|
||||
bool HasWeirdParserInsertionMode() const
|
||||
{ return GetBoolFlag(ElementHasWeirdParserInsertionMode); }
|
||||
bool HandlingClick() const { return GetBoolFlag(NodeHandlingClick); }
|
||||
void SetHandlingClick() { SetBoolFlag(NodeHandlingClick); }
|
||||
void ClearHandlingClick() { ClearBoolFlag(NodeHandlingClick); }
|
||||
|
@ -18,7 +18,7 @@ interface nsINode;
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
[scriptable, builtinclass, uuid(12cf5a4d-fffb-4f2f-9cec-c65195661d76)]
|
||||
[scriptable, builtinclass, uuid(e0a4d4b3-f34e-44bd-b1f2-4e3bde9b6915)]
|
||||
interface nsISelection : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -125,13 +125,6 @@ interface nsISelection : nsISupports
|
||||
*/
|
||||
void deleteFromDocument();
|
||||
|
||||
/**
|
||||
* Modifies the cursor Bidi level after a change in keyboard direction
|
||||
* @param langRTL is PR_TRUE if the new language is right-to-left or
|
||||
* PR_FALSE if the new language is left-to-right.
|
||||
*/
|
||||
void selectionLanguageChange(in boolean langRTL);
|
||||
|
||||
/**
|
||||
* Returns the whole selection into a plain text string.
|
||||
*/
|
||||
|
@ -28,24 +28,24 @@ template<class T> class nsTArray;
|
||||
native nsDirection(nsDirection);
|
||||
native ScrollAxis(nsIPresShell::ScrollAxis);
|
||||
|
||||
[scriptable, builtinclass, uuid(3ede44eb-2df8-41de-ab79-6f3dbd10090b)]
|
||||
[scriptable, builtinclass, uuid(52629837-7b3f-4434-940d-a14de7ef9b7a)]
|
||||
interface nsISelectionPrivate : nsISelection
|
||||
{
|
||||
const short ENDOFPRECEDINGLINE=0;
|
||||
const short STARTOFNEXTLINE=1;
|
||||
|
||||
|
||||
attribute boolean interlinePosition;
|
||||
|
||||
/* startBatchChanges
|
||||
match this up with endbatchChanges. will stop ui updates while multiple selection methods are called
|
||||
*/
|
||||
void startBatchChanges();
|
||||
|
||||
[noscript] void startBatchChanges();
|
||||
|
||||
/* endBatchChanges
|
||||
match this up with startBatchChanges
|
||||
*/
|
||||
void endBatchChanges();
|
||||
|
||||
[noscript] void endBatchChanges();
|
||||
|
||||
DOMString toStringWithFormat(in string formatType, in unsigned long flags, in int32_t wrapColumn);
|
||||
void addSelectionListener(in nsISelectionListener newListener);
|
||||
void removeSelectionListener(in nsISelectionListener listenerToRemove);
|
||||
@ -55,19 +55,19 @@ interface nsISelectionPrivate : nsISelection
|
||||
items in nsFrameSelection to a
|
||||
new nsITableSelection interface
|
||||
*/
|
||||
const long TABLESELECTION_NONE = 0;
|
||||
const long TABLESELECTION_CELL = 1;
|
||||
const long TABLESELECTION_ROW = 2;
|
||||
const long TABLESELECTION_COLUMN = 3;
|
||||
const long TABLESELECTION_TABLE = 4;
|
||||
const long TABLESELECTION_NONE = 0;
|
||||
const long TABLESELECTION_CELL = 1;
|
||||
const long TABLESELECTION_ROW = 2;
|
||||
const long TABLESELECTION_COLUMN = 3;
|
||||
const long TABLESELECTION_TABLE = 4;
|
||||
const long TABLESELECTION_ALLCELLS = 5;
|
||||
|
||||
/** Test if supplied range points to a single table element:
|
||||
* Result is one of above constants. "None" means
|
||||
* a table element isn't selected.
|
||||
*/
|
||||
long getTableSelectionType(in nsIDOMRange range);
|
||||
|
||||
[noscript] long getTableSelectionType(in nsIDOMRange range);
|
||||
|
||||
/* canCacheFrameOffset
|
||||
* Frame Offset cache can be used just during calling nsEditor::EndPlaceHolderTransaction.
|
||||
* EndPlaceHolderTransaction will give rise to reflow/refreshing view/scroll, and call times
|
||||
@ -155,5 +155,12 @@ interface nsISelectionPrivate : nsISelection
|
||||
in boolean aIsSynchronous,
|
||||
in ScrollAxis aVertical,
|
||||
in ScrollAxis aHorizontal);
|
||||
|
||||
/**
|
||||
* Modifies the cursor Bidi level after a change in keyboard direction
|
||||
* @param langRTL is PR_TRUE if the new language is right-to-left or
|
||||
* PR_FALSE if the new language is left-to-right.
|
||||
*/
|
||||
[noscript] void selectionLanguageChange(in boolean langRTL);
|
||||
};
|
||||
|
||||
|
@ -2613,6 +2613,28 @@ FragmentOrElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup)
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ContainsMarkup(const nsAString& aStr)
|
||||
{
|
||||
// Note: we can't use FindCharInSet because null is one of the characters we
|
||||
// want to search for.
|
||||
const PRUnichar* start = aStr.BeginReading();
|
||||
const PRUnichar* end = aStr.EndReading();
|
||||
|
||||
while (start != end) {
|
||||
PRUnichar c = *start;
|
||||
if (c == PRUnichar('<') ||
|
||||
c == PRUnichar('&') ||
|
||||
c == PRUnichar('\r') ||
|
||||
c == PRUnichar('\0')) {
|
||||
return true;
|
||||
}
|
||||
++start;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError)
|
||||
{
|
||||
@ -2625,6 +2647,19 @@ FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult
|
||||
target = frag;
|
||||
}
|
||||
|
||||
// Fast-path for strings with no markup. Limit this to short strings, to
|
||||
// avoid ContainsMarkup taking too long. The choice for 100 is based on
|
||||
// gut feeling.
|
||||
//
|
||||
// Don't do this for elements with a weird parser insertion mode, for
|
||||
// instance setting innerHTML = "" on a <html> element should add the
|
||||
// optional <head> and <body> elements.
|
||||
if (!target->HasWeirdParserInsertionMode() &&
|
||||
aInnerHTML.Length() < 100 && !ContainsMarkup(aInnerHTML)) {
|
||||
aError = nsContentUtils::SetNodeTextContent(target, aInnerHTML, false);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIDocument* doc = target->OwnerDoc();
|
||||
|
||||
// Batch possible DOMSubtreeModified events.
|
||||
|
@ -85,8 +85,6 @@
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIChannelPolicy.h"
|
||||
#include "nsICharsetDetectionObserver.h"
|
||||
#include "nsICharsetDetector.h"
|
||||
#include "nsIChromeRegistry.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIContent.h"
|
||||
@ -134,7 +132,6 @@
|
||||
#include "nsIParser.h"
|
||||
#include "nsIParserService.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
#include "nsIPluginHost.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIScriptContext.h"
|
||||
@ -3458,26 +3455,23 @@ nsContentUtils::MatchElementId(nsIContent *aContent, const nsAString& aId)
|
||||
return MatchElementId(aContent, id);
|
||||
}
|
||||
|
||||
// Convert the string from the given charset to Unicode.
|
||||
// Convert the string from the given encoding to Unicode.
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::ConvertStringFromCharset(const nsACString& aCharset,
|
||||
const nsACString& aInput,
|
||||
nsAString& aOutput)
|
||||
nsContentUtils::ConvertStringFromEncoding(const nsACString& aEncoding,
|
||||
const nsACString& aInput,
|
||||
nsAString& aOutput)
|
||||
{
|
||||
if (aCharset.IsEmpty()) {
|
||||
// Treat the string as UTF8
|
||||
CopyUTF8toUTF16(aInput, aOutput);
|
||||
return NS_OK;
|
||||
nsAutoCString encoding;
|
||||
if (aEncoding.IsEmpty()) {
|
||||
encoding.AssignLiteral("UTF-8");
|
||||
} else {
|
||||
encoding.Assign(aEncoding);
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
nsAutoPtr<TextDecoder> decoder(new TextDecoder());
|
||||
decoder->Init(NS_ConvertUTF8toUTF16(aCharset), false, rv);
|
||||
if (rv.Failed()) {
|
||||
rv.ClearMessage();
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
decoder->InitWithEncoding(encoding, false);
|
||||
|
||||
decoder->Decode(aInput.BeginReading(), aInput.Length(), false,
|
||||
aOutput, rv);
|
||||
@ -3511,80 +3505,6 @@ nsContentUtils::CheckForBOM(const unsigned char* aBuffer, uint32_t aLength,
|
||||
return found;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CharsetDetectionObserver,
|
||||
nsICharsetDetectionObserver)
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::GuessCharset(const char *aData, uint32_t aDataLen,
|
||||
nsACString &aCharset)
|
||||
{
|
||||
// First try the universal charset detector
|
||||
nsCOMPtr<nsICharsetDetector> detector =
|
||||
do_CreateInstance(NS_CHARSET_DETECTOR_CONTRACTID_BASE
|
||||
"universal_charset_detector");
|
||||
if (!detector) {
|
||||
// No universal charset detector, try the default charset detector
|
||||
const nsAdoptingCString& detectorName =
|
||||
Preferences::GetLocalizedCString("intl.charset.detector");
|
||||
if (!detectorName.IsEmpty()) {
|
||||
nsAutoCString detectorContractID;
|
||||
detectorContractID.AssignLiteral(NS_CHARSET_DETECTOR_CONTRACTID_BASE);
|
||||
detectorContractID += detectorName;
|
||||
detector = do_CreateInstance(detectorContractID.get());
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// The charset detector doesn't work for empty (null) aData. Testing
|
||||
// aDataLen instead of aData so that we catch potential errors.
|
||||
if (detector && aDataLen) {
|
||||
nsRefPtr<CharsetDetectionObserver> observer =
|
||||
new CharsetDetectionObserver();
|
||||
|
||||
rv = detector->Init(observer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool dummy;
|
||||
rv = detector->DoIt(aData, aDataLen, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = detector->Done();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aCharset = observer->GetResult();
|
||||
} else {
|
||||
// no charset detector available, check the BOM
|
||||
unsigned char sniffBuf[3];
|
||||
uint32_t numRead =
|
||||
(aDataLen >= sizeof(sniffBuf) ? sizeof(sniffBuf) : aDataLen);
|
||||
memcpy(sniffBuf, aData, numRead);
|
||||
|
||||
CheckForBOM(sniffBuf, numRead, aCharset);
|
||||
}
|
||||
|
||||
if (aCharset.IsEmpty()) {
|
||||
// no charset detected, default to the system charset
|
||||
nsCOMPtr<nsIPlatformCharset> platformCharset =
|
||||
do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = platformCharset->GetCharset(kPlatformCharsetSel_PlainTextInFile,
|
||||
aCharset);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to get the system charset!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aCharset.IsEmpty()) {
|
||||
// no sniffed or default charset, assume UTF-8
|
||||
aCharset.AssignLiteral("UTF-8");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver)
|
||||
@ -6540,9 +6460,9 @@ nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> anchorNode = aSelection->GetAnchorNode();
|
||||
int32_t anchorOffset = aSelection->GetAnchorOffset();
|
||||
uint32_t anchorOffset = aSelection->AnchorOffset();
|
||||
nsCOMPtr<nsINode> focusNode = aSelection->GetFocusNode();
|
||||
int32_t focusOffset = aSelection->GetFocusOffset();
|
||||
uint32_t focusOffset = aSelection->FocusOffset();
|
||||
|
||||
// We have at most two children, consisting of an optional text node followed
|
||||
// by an optional <br>.
|
||||
|
@ -388,7 +388,15 @@ nsDOMFileReader::DoOnStopRequest(nsIRequest *aRequest,
|
||||
case FILE_AS_BINARY:
|
||||
break; //Already accumulated mResult
|
||||
case FILE_AS_TEXT:
|
||||
rv = GetAsText(mCharset, mFileData, mDataLen, mResult);
|
||||
if (!mFileData) {
|
||||
if (mDataLen) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
rv = GetAsText(file, mCharset, "", mDataLen, mResult);
|
||||
break;
|
||||
}
|
||||
rv = GetAsText(file, mCharset, mFileData, mDataLen, mResult);
|
||||
break;
|
||||
case FILE_AS_DATAURL:
|
||||
rv = GetAsDataURL(file, mFileData, mDataLen, mResult);
|
||||
@ -476,28 +484,43 @@ nsDOMFileReader::ReadFileContent(JSContext* aCx,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMFileReader::GetAsText(const nsACString &aCharset,
|
||||
nsDOMFileReader::GetAsText(nsIDOMBlob *aFile,
|
||||
const nsACString &aCharset,
|
||||
const char *aFileData,
|
||||
uint32_t aDataLen,
|
||||
nsAString& aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoCString charsetGuess;
|
||||
if (!aCharset.IsEmpty()) {
|
||||
charsetGuess = aCharset;
|
||||
} else {
|
||||
rv = nsContentUtils::GuessCharset(aFileData, aDataLen, charsetGuess);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// The BOM sniffing is baked into the "decode" part of the Encoding
|
||||
// Standard, which the File API references.
|
||||
nsAutoCString encoding;
|
||||
if (!nsContentUtils::CheckForBOM(
|
||||
reinterpret_cast<const unsigned char *>(aFileData),
|
||||
aDataLen,
|
||||
encoding)) {
|
||||
// BOM sniffing failed. Try the API argument.
|
||||
if (!EncodingUtils::FindEncodingForLabel(aCharset,
|
||||
encoding)) {
|
||||
// API argument failed. Try the type property of the blob.
|
||||
nsAutoString type16;
|
||||
aFile->GetType(type16);
|
||||
NS_ConvertUTF16toUTF8 type(type16);
|
||||
nsAutoCString specifiedCharset;
|
||||
bool haveCharset;
|
||||
int32_t charsetStart, charsetEnd;
|
||||
NS_ExtractCharsetFromContentType(type,
|
||||
specifiedCharset,
|
||||
&haveCharset,
|
||||
&charsetStart,
|
||||
&charsetEnd);
|
||||
if (!EncodingUtils::FindEncodingForLabel(specifiedCharset, encoding)) {
|
||||
// Type property failed. Use UTF-8.
|
||||
encoding.AssignLiteral("UTF-8");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString charset;
|
||||
if (!EncodingUtils::FindEncodingForLabel(charsetGuess, charset)) {
|
||||
return NS_ERROR_DOM_ENCODING_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
|
||||
rv = ConvertStream(aFileData, aDataLen, charset.get(), aResult);
|
||||
|
||||
return NS_OK;
|
||||
nsDependentCSubstring data(aFileData, aDataLen);
|
||||
return nsContentUtils::ConvertStringFromEncoding(encoding, data, aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -527,31 +550,6 @@ nsDOMFileReader::GetAsDataURL(nsIDOMBlob *aFile,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMFileReader::ConvertStream(const char *aFileData,
|
||||
uint32_t aDataLen,
|
||||
const char *aCharset,
|
||||
nsAString &aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIUnicodeDecoder> unicodeDecoder =
|
||||
EncodingUtils::DecoderForEncoding(aCharset);
|
||||
|
||||
int32_t destLength;
|
||||
rv = unicodeDecoder->GetMaxLength(aFileData, aDataLen, &destLength);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!aResult.SetLength(destLength, fallible_t()))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
int32_t srcLength = aDataLen;
|
||||
rv = unicodeDecoder->Convert(aFileData, &srcLength, aResult.BeginWriting(), &destLength);
|
||||
aResult.SetLength(destLength); //Trim down to the correct size
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* virtual */ JSObject*
|
||||
nsDOMFileReader::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
|
@ -125,10 +125,9 @@ protected:
|
||||
void ReadFileContent(JSContext* aCx, nsIDOMBlob* aBlob,
|
||||
const nsAString &aCharset, eDataFormat aDataFormat,
|
||||
ErrorResult& aRv);
|
||||
nsresult GetAsText(const nsACString &aCharset,
|
||||
nsresult GetAsText(nsIDOMBlob *aFile, const nsACString &aCharset,
|
||||
const char *aFileData, uint32_t aDataLen, nsAString &aResult);
|
||||
nsresult GetAsDataURL(nsIDOMBlob *aFile, const char *aFileData, uint32_t aDataLen, nsAString &aResult);
|
||||
nsresult ConvertStream(const char *aFileData, uint32_t aDataLen, const char *aCharset, nsAString &aResult);
|
||||
|
||||
void FreeFileData() {
|
||||
moz_free(mFileData);
|
||||
|
@ -8847,7 +8847,9 @@ nsDocument::ScrollToRef()
|
||||
if (NS_FAILED(rv)) {
|
||||
const nsACString &docCharset = GetDocumentCharacterSet();
|
||||
|
||||
rv = nsContentUtils::ConvertStringFromCharset(docCharset, unescapedRef, ref);
|
||||
rv = nsContentUtils::ConvertStringFromEncoding(docCharset,
|
||||
unescapedRef,
|
||||
ref);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
|
||||
rv = shell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
|
||||
|
@ -311,6 +311,7 @@ GK_ATOM(dragover, "dragover")
|
||||
GK_ATOM(dragSession, "dragSession")
|
||||
GK_ATOM(dragstart, "dragstart")
|
||||
GK_ATOM(drawintitlebar, "drawintitlebar")
|
||||
GK_ATOM(drawtitle, "drawtitle")
|
||||
GK_ATOM(drop, "drop")
|
||||
GK_ATOM(dropAfter, "dropAfter")
|
||||
GK_ATOM(dropBefore, "dropBefore")
|
||||
|
@ -34,8 +34,13 @@ nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI,
|
||||
nsAutoCString charset;
|
||||
aURI->GetOriginCharset(charset);
|
||||
nsAutoString ref;
|
||||
nsresult rv = nsContentUtils::ConvertStringFromCharset(charset, refPart, ref);
|
||||
nsresult rv = nsContentUtils::ConvertStringFromEncoding(charset,
|
||||
refPart,
|
||||
ref);
|
||||
if (NS_FAILED(rv)) {
|
||||
// XXX Eww. If fallible malloc failed, using a conversion method that
|
||||
// assumes UTF-8 and doesn't handle UTF-8 errors.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=951082
|
||||
CopyUTF8toUTF16(refPart, ref);
|
||||
}
|
||||
if (ref.IsEmpty())
|
||||
|
@ -52,6 +52,7 @@ public:
|
||||
mNumCols(0),
|
||||
mCurrentRowColHint(NS_STYLE_HINT_REFLOW)
|
||||
{
|
||||
SetHasWeirdParserInsertionMode();
|
||||
}
|
||||
virtual ~HTMLFrameSetElement();
|
||||
|
||||
|
@ -5077,18 +5077,18 @@ HTMLInputElement::SetRangeText(const nsAString& aReplacement, uint32_t aStart,
|
||||
}
|
||||
|
||||
if (aSelectionStart == -1 && aSelectionEnd == -1) {
|
||||
aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd);
|
||||
if (aRv.Failed()) {
|
||||
nsTextEditorState* state = GetEditorState();
|
||||
if (state && state->IsSelectionCached()) {
|
||||
aSelectionStart = state->GetSelectionProperties().mStart;
|
||||
aSelectionEnd = state->GetSelectionProperties().mEnd;
|
||||
aRv = NS_OK;
|
||||
}
|
||||
aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd);
|
||||
if (aRv.Failed()) {
|
||||
nsTextEditorState* state = GetEditorState();
|
||||
if (state && state->IsSelectionCached()) {
|
||||
aSelectionStart = state->GetSelectionProperties().mStart;
|
||||
aSelectionEnd = state->GetSelectionProperties().mEnd;
|
||||
aRv = NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aStart < aEnd) {
|
||||
if (aStart <= aEnd) {
|
||||
value.Replace(aStart, aEnd - aStart, aReplacement);
|
||||
SetValueInternal(value, false, false);
|
||||
}
|
||||
@ -5115,15 +5115,17 @@ HTMLInputElement::SetRangeText(const nsAString& aReplacement, uint32_t aStart,
|
||||
break;
|
||||
case mozilla::dom::SelectionMode::Preserve:
|
||||
{
|
||||
if ((uint32_t)aSelectionStart > aEnd)
|
||||
if ((uint32_t)aSelectionStart > aEnd) {
|
||||
aSelectionStart += delta;
|
||||
else if ((uint32_t)aSelectionStart > aStart)
|
||||
aSelectionStart = aStart;
|
||||
} else if ((uint32_t)aSelectionStart > aStart) {
|
||||
aSelectionStart = aStart;
|
||||
}
|
||||
|
||||
if ((uint32_t)aSelectionEnd > aEnd)
|
||||
if ((uint32_t)aSelectionEnd > aEnd) {
|
||||
aSelectionEnd += delta;
|
||||
else if ((uint32_t)aSelectionEnd > aStart)
|
||||
} else if ((uint32_t)aSelectionEnd > aStart) {
|
||||
aSelectionEnd = newEnd;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -116,6 +116,8 @@ HTMLSelectElement::HTMLSelectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||
mOptGroupCount(0),
|
||||
mSelectedIndex(-1)
|
||||
{
|
||||
SetHasWeirdParserInsertionMode();
|
||||
|
||||
// DoneAddingChildren() will be called later if it's from the parser,
|
||||
// otherwise it is
|
||||
|
||||
|
@ -32,6 +32,10 @@ public:
|
||||
HTMLSharedElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
{
|
||||
if (mNodeInfo->Equals(nsGkAtoms::head) ||
|
||||
mNodeInfo->Equals(nsGkAtoms::html)) {
|
||||
SetHasWeirdParserInsertionMode();
|
||||
}
|
||||
}
|
||||
virtual ~HTMLSharedElement();
|
||||
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
HTMLTableCaptionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
{
|
||||
SetHasWeirdParserInsertionMode();
|
||||
}
|
||||
virtual ~HTMLTableCaptionElement();
|
||||
|
||||
|
@ -23,6 +23,7 @@ public:
|
||||
HTMLTableCellElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
{
|
||||
SetHasWeirdParserInsertionMode();
|
||||
}
|
||||
virtual ~HTMLTableCellElement();
|
||||
|
||||
|
@ -17,6 +17,7 @@ public:
|
||||
HTMLTableColElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
{
|
||||
SetHasWeirdParserInsertionMode();
|
||||
}
|
||||
virtual ~HTMLTableColElement();
|
||||
|
||||
|
@ -286,6 +286,7 @@ HTMLTableElement::HTMLTableElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo),
|
||||
mTableInheritedAttributes(TABLE_ATTRS_DIRTY)
|
||||
{
|
||||
SetHasWeirdParserInsertionMode();
|
||||
}
|
||||
|
||||
HTMLTableElement::~HTMLTableElement()
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
HTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
{
|
||||
SetHasWeirdParserInsertionMode();
|
||||
}
|
||||
|
||||
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLTableRowElement, tr)
|
||||
|
@ -18,6 +18,7 @@ public:
|
||||
HTMLTableSectionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
{
|
||||
SetHasWeirdParserInsertionMode();
|
||||
}
|
||||
|
||||
// nsISupports
|
||||
|
@ -33,6 +33,7 @@ namespace dom {
|
||||
HTMLTemplateElement::HTMLTemplateElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
{
|
||||
SetHasWeirdParserInsertionMode();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -939,17 +939,17 @@ HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
|
||||
}
|
||||
|
||||
if (aSelectionStart == -1 && aSelectionEnd == -1) {
|
||||
aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd);
|
||||
if (aRv.Failed()) {
|
||||
if (mState.IsSelectionCached()) {
|
||||
aSelectionStart = mState.GetSelectionProperties().mStart;
|
||||
aSelectionEnd = mState.GetSelectionProperties().mEnd;
|
||||
aRv = NS_OK;
|
||||
}
|
||||
aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd);
|
||||
if (aRv.Failed()) {
|
||||
if (mState.IsSelectionCached()) {
|
||||
aSelectionStart = mState.GetSelectionProperties().mStart;
|
||||
aSelectionEnd = mState.GetSelectionProperties().mEnd;
|
||||
aRv = NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aStart < aEnd) {
|
||||
if (aStart <= aEnd) {
|
||||
value.Replace(aStart, aEnd - aStart, aReplacement);
|
||||
SetValueInternal(value, false);
|
||||
}
|
||||
@ -976,15 +976,17 @@ HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
|
||||
break;
|
||||
case mozilla::dom::SelectionMode::Preserve:
|
||||
{
|
||||
if ((uint32_t)aSelectionStart > aEnd)
|
||||
if ((uint32_t)aSelectionStart > aEnd) {
|
||||
aSelectionStart += delta;
|
||||
else if ((uint32_t)aSelectionStart > aStart)
|
||||
aSelectionStart = aStart;
|
||||
} else if ((uint32_t)aSelectionStart > aStart) {
|
||||
aSelectionStart = aStart;
|
||||
}
|
||||
|
||||
if ((uint32_t)aSelectionEnd > aEnd)
|
||||
if ((uint32_t)aSelectionEnd > aEnd) {
|
||||
aSelectionEnd += delta;
|
||||
else if ((uint32_t)aSelectionEnd > aStart)
|
||||
} else if ((uint32_t)aSelectionEnd > aStart) {
|
||||
aSelectionEnd = newEnd;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
file_anchor_ping.html
|
||||
|
||||
[test_allowMedia.html]
|
||||
[test_anchor_ping.html]
|
||||
|
13
content/html/content/test/file_anchor_ping.html
Normal file
13
content/html/content/test/file_anchor_ping.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>file_anchor_ping.html</title>
|
||||
</head>
|
||||
<body onload="document.body.firstElementChild.click()">
|
||||
<a href="/">click me</a>
|
||||
<script>
|
||||
document.body.firstElementChild.ping = window.location.search.slice(1);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -90,15 +90,59 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364
|
||||
ok(false, "input event should NOT be fired for " + + aEvent.target.id);
|
||||
}, false);
|
||||
|
||||
//test setRange(replacement)
|
||||
var test = " setRange(replacement), shrink";
|
||||
elem.value = "0123456789ABCDEF";
|
||||
elem.setSelectionRange(1, 6);
|
||||
elem.setRangeText("xyz");
|
||||
is(elem.value, "0xyz6789ABCDEF", msg + ".value == \"0xyz6789ABCDEF\"");
|
||||
is(elem.selectionStart, 1, msg + ".selectionStart == 1");
|
||||
is(elem.selectionEnd, 4, msg + ".selectionEnd == 4");
|
||||
is(elem.value, "0xyz6789ABCDEF", msg + test);
|
||||
is(elem.selectionStart, 1, msg + test);
|
||||
is(elem.selectionEnd, 4, msg + test);
|
||||
elem.setRangeText("mnk");
|
||||
is(elem.value, "0mnk6789ABCDEF", msg + ".value == \"0mnk6789ABCDEF\"");
|
||||
is(elem.value, "0mnk6789ABCDEF", msg + test);
|
||||
expectedNumOfSelectCalls += 2;
|
||||
|
||||
test = " setRange(replacement), expand";
|
||||
elem.value = "0123456789ABCDEF";
|
||||
elem.setSelectionRange(1, 2);
|
||||
elem.setRangeText("xyz");
|
||||
is(elem.value, "0xyz23456789ABCDEF", msg + test);
|
||||
is(elem.selectionStart, 1, msg + test);
|
||||
is(elem.selectionEnd, 4, msg + test);
|
||||
elem.setRangeText("mnk");
|
||||
is(elem.value, "0mnk23456789ABCDEF", msg + test);
|
||||
expectedNumOfSelectCalls += 2;
|
||||
|
||||
test = " setRange(replacement) pure insertion at start";
|
||||
elem.value = "0123456789ABCDEF";
|
||||
elem.setSelectionRange(0, 0);
|
||||
elem.setRangeText("xyz");
|
||||
is(elem.value, "xyz0123456789ABCDEF", msg + test);
|
||||
is(elem.selectionStart, 0, msg + test);
|
||||
is(elem.selectionEnd, 0, msg + test);
|
||||
elem.setRangeText("mnk");
|
||||
is(elem.value, "mnkxyz0123456789ABCDEF", msg + test);
|
||||
expectedNumOfSelectCalls += 2;
|
||||
|
||||
test = " setRange(replacement) pure insertion in the middle";
|
||||
elem.value = "0123456789ABCDEF";
|
||||
elem.setSelectionRange(4, 4);
|
||||
elem.setRangeText("xyz");
|
||||
is(elem.value, "0123xyz456789ABCDEF", msg + test);
|
||||
is(elem.selectionStart, 4, msg + test);
|
||||
is(elem.selectionEnd, 4, msg + test);
|
||||
elem.setRangeText("mnk");
|
||||
is(elem.value, "0123mnkxyz456789ABCDEF", msg + test);
|
||||
expectedNumOfSelectCalls += 2;
|
||||
|
||||
test = " setRange(replacement) pure insertion at the end";
|
||||
elem.value = "0123456789ABCDEF";
|
||||
elem.setSelectionRange(16, 16);
|
||||
elem.setRangeText("xyz");
|
||||
is(elem.value, "0123456789ABCDEFxyz", msg + test);
|
||||
is(elem.selectionStart, 16, msg + test);
|
||||
is(elem.selectionEnd, 16, msg + test);
|
||||
elem.setRangeText("mnk");
|
||||
is(elem.value, "0123456789ABCDEFmnkxyz", msg + test);
|
||||
expectedNumOfSelectCalls += 2;
|
||||
|
||||
//test SetRange(replacement, start, end, mode) with start > end
|
||||
|
253
content/html/content/test/test_anchor_ping.html
Normal file
253
content/html/content/test/test_anchor_ping.html
Normal file
@ -0,0 +1,253 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=786347
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 786347</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 786347 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
addLoadEvent(function () {
|
||||
Task.spawn(function run_tests() {
|
||||
while (tests.length) {
|
||||
let test = tests.shift();
|
||||
info("-- running " + test.name);
|
||||
yield Task.spawn(test);
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
let tests = [
|
||||
|
||||
// Ensure that sending pings is enabled.
|
||||
function setup() {
|
||||
Services.prefs.setBoolPref("browser.send_pings", true);
|
||||
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("browser.send_pings");
|
||||
});
|
||||
},
|
||||
|
||||
// If both the address of the document containing the hyperlink being audited
|
||||
// and ping URL have the same origin then the request must include a Ping-From
|
||||
// HTTP header with, as its value, the address of the document containing the
|
||||
// hyperlink, and a Ping-To HTTP header with, as its value, the target URL.
|
||||
// The request must not include a Referer (sic) HTTP header.
|
||||
function same_origin() {
|
||||
let from = "/ping-from/" + Math.random();
|
||||
let to = "/ping-to/" + Math.random();
|
||||
let ping = "/ping/" + Math.random();
|
||||
|
||||
let base;
|
||||
let server = new HttpServer();
|
||||
|
||||
// The page that contains the link.
|
||||
createFromPathHandler(server, from, to, () => ping);
|
||||
|
||||
// The page that the link's href points to.
|
||||
let promiseHref = createToPathHandler(server, to);
|
||||
|
||||
// The ping we want to receive.
|
||||
let promisePing = createPingPathHandler(server, ping, () => {
|
||||
return {from: base + from, to: base + to};
|
||||
});
|
||||
|
||||
// Start the server, get its base URL and run the test.
|
||||
server.start(-1);
|
||||
base = "http://localhost:" + server.identity.primaryPort;
|
||||
navigate(base + from);
|
||||
|
||||
// Wait until the target and ping url have loaded.
|
||||
yield Promise.all([promiseHref, promisePing]);
|
||||
|
||||
// Cleanup.
|
||||
yield stopServer(server);
|
||||
},
|
||||
|
||||
// If the origins are different, but the document containing the hyperlink
|
||||
// being audited was not retrieved over an encrypted connection then the
|
||||
// request must include a Referer (sic) HTTP header with, as its value, the
|
||||
// address of the document containing the hyperlink, a Ping-From HTTP header
|
||||
// with the same value, and a Ping-To HTTP header with, as its value, target
|
||||
// URL.
|
||||
function diff_origin() {
|
||||
let from = "/ping-from/" + Math.random();
|
||||
let to = "/ping-to/" + Math.random();
|
||||
let ping = "/ping/" + Math.random();
|
||||
|
||||
// We will use two servers to simulate two different origins.
|
||||
let base, base2;
|
||||
let server = new HttpServer();
|
||||
let server2 = new HttpServer();
|
||||
|
||||
// The page that contains the link.
|
||||
createFromPathHandler(server, from, to, () => base2 + ping);
|
||||
|
||||
// The page that the link's href points to.
|
||||
let promiseHref = createToPathHandler(server, to);
|
||||
|
||||
// Start the first server and get its base URL.
|
||||
server.start(-1);
|
||||
base = "http://localhost:" + server.identity.primaryPort;
|
||||
|
||||
// The ping we want to receive.
|
||||
let promisePing = createPingPathHandler(server2, ping, () => {
|
||||
return {referrer: base + from, from: base + from, to: base + to};
|
||||
});
|
||||
|
||||
// Start the second server, get its base URL and run the test.
|
||||
server2.start(-1);
|
||||
base2 = "http://localhost:" + server2.identity.primaryPort;
|
||||
navigate(base + from);
|
||||
|
||||
// Wait until the target and ping url have loaded.
|
||||
yield Promise.all([promiseHref, promisePing]);
|
||||
|
||||
// Cleanup.
|
||||
yield stopServer(server);
|
||||
yield stopServer(server2);
|
||||
},
|
||||
|
||||
// If the origins are different and the document containing the hyperlink
|
||||
// being audited was retrieved over an encrypted connection then the request
|
||||
// must include a Ping-To HTTP header with, as its value, target URL. The
|
||||
// request must neither include a Referer (sic) HTTP header nor include a
|
||||
// Ping-From HTTP header.
|
||||
function diff_origin_secure_referrer() {
|
||||
let ping = "/ping/" + Math.random();
|
||||
let server = new HttpServer();
|
||||
|
||||
// The ping we want to receive.
|
||||
let promisePing = createPingPathHandler(server, ping, () => {
|
||||
return {to: "https://example.com/"};
|
||||
});
|
||||
|
||||
// Start the server and run the test.
|
||||
server.start(-1);
|
||||
|
||||
// The referrer will be loaded using a secure channel.
|
||||
navigate("https://example.com/chrome/content/html/content/test/" +
|
||||
"file_anchor_ping.html?" + "http://localhost:" +
|
||||
server.identity.primaryPort + ping);
|
||||
|
||||
// Wait until the ping has been sent.
|
||||
yield promisePing;
|
||||
|
||||
// Cleanup.
|
||||
yield stopServer(server);
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
// Navigate the iframe used for testing to a new URL.
|
||||
function navigate(uri) {
|
||||
document.getElementById("frame").src = uri;
|
||||
}
|
||||
|
||||
// Registers a path handler for the given server that will serve a page
|
||||
// containing an <a ping> element. The page will automatically simulate
|
||||
// clicking the link after it has loaded.
|
||||
function createFromPathHandler(server, path, href, lazyPing) {
|
||||
server.registerPathHandler(path, function (request, response) {
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/html;charset=utf-8", false);
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
|
||||
let body = '<body onload="document.body.firstChild.click()">' +
|
||||
'<a href="' + href + '" ping="' + lazyPing() + '"></a></body>';
|
||||
response.write(body);
|
||||
});
|
||||
}
|
||||
|
||||
// Registers a path handler for the given server that will serve a simple empty
|
||||
// page we can use as the href attribute for links. It returns a promise that
|
||||
// will be resolved once the page has been requested.
|
||||
function createToPathHandler(server, path) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
server.registerPathHandler(path, function (request, response) {
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/html;charset=utf-8", false);
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.write("OK");
|
||||
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// Registers a path handler for the given server that will receive pings as
|
||||
// sent when an <a ping> element has been clicked. It will check that the
|
||||
// correct http method has been used, the post data is correct and all headers
|
||||
// are given as expected. It returns a promise that will be resolved once the
|
||||
// ping has been received.
|
||||
function createPingPathHandler(server, path, lazyHeaders) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
server.registerPathHandler(path, function (request, response) {
|
||||
let headers = lazyHeaders();
|
||||
|
||||
is(request.method, "POST", "correct http method used");
|
||||
is(request.getHeader("Ping-To"), headers.to, "valid ping-to header");
|
||||
|
||||
if ("from" in headers) {
|
||||
is(request.getHeader("Ping-From"), headers.from, "valid ping-from header");
|
||||
} else {
|
||||
ok(!request.hasHeader("Ping-From"), "no ping-from header");
|
||||
}
|
||||
|
||||
if ("referrer" in headers) {
|
||||
is(request.getHeader("Referer"), headers.referrer, "valid referer header");
|
||||
} else {
|
||||
ok(!request.hasHeader("Referer"), "no referer header");
|
||||
}
|
||||
|
||||
let bs = request.bodyInputStream;
|
||||
let body = NetUtil.readInputStreamToString(bs, bs.available());
|
||||
is(body, "PING", "correct body sent");
|
||||
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/html;charset=utf-8", false);
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.write("OK");
|
||||
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// Returns a promise that is resolved when the given http server instance has
|
||||
// been stopped.
|
||||
function stopServer(server) {
|
||||
let deferred = Promise.defer();
|
||||
server.stop(deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786347">Mozilla Bug 786347</a>
|
||||
<p id="display"></p>
|
||||
<iframe id="frame" />
|
||||
</body>
|
||||
</html>
|
@ -1202,8 +1202,8 @@ nsHTMLDocument::GetCookie(nsAString& aCookie, ErrorResult& rv)
|
||||
service->GetCookieString(codebaseURI, mChannel, getter_Copies(cookie));
|
||||
// CopyUTF8toUTF16 doesn't handle error
|
||||
// because it assumes that the input is valid.
|
||||
nsContentUtils::ConvertStringFromCharset(NS_LITERAL_CSTRING("utf-8"),
|
||||
cookie, aCookie);
|
||||
nsContentUtils::ConvertStringFromEncoding(NS_LITERAL_CSTRING("UTF-8"),
|
||||
cookie, aCookie);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2096,7 +2096,7 @@ nsHTMLDocument::GetSelection(nsISelection** aReturn)
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
already_AddRefed<nsISelection>
|
||||
already_AddRefed<Selection>
|
||||
nsHTMLDocument::GetSelection(ErrorResult& rv)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(GetScopeObject());
|
||||
@ -2112,7 +2112,8 @@ nsHTMLDocument::GetSelection(ErrorResult& rv)
|
||||
|
||||
nsCOMPtr<nsISelection> sel;
|
||||
rv = window->GetSelection(getter_AddRefs(sel));
|
||||
return sel.forget();
|
||||
nsRefPtr<Selection> selection = static_cast<Selection*>(sel.get());
|
||||
return selection.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -239,7 +239,7 @@ public:
|
||||
{
|
||||
// Deprecated
|
||||
}
|
||||
already_AddRefed<nsISelection> GetSelection(mozilla::ErrorResult& rv);
|
||||
already_AddRefed<mozilla::Selection> GetSelection(mozilla::ErrorResult& rv);
|
||||
// The XPCOM CaptureEvents works fine for us.
|
||||
// The XPCOM ReleaseEvents works fine for us.
|
||||
// We're picking up GetLocation from Document
|
||||
|
@ -1003,6 +1003,10 @@ nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
|
||||
SetDrawsInTitlebar(
|
||||
aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
|
||||
}
|
||||
else if (aName == nsGkAtoms::drawtitle) {
|
||||
SetDrawsTitle(
|
||||
aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
|
||||
}
|
||||
else if (aName == nsGkAtoms::localedir) {
|
||||
// if the localedir changed on the root element, reset the document direction
|
||||
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
|
||||
@ -1058,6 +1062,9 @@ nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
|
||||
else if (aName == nsGkAtoms::drawintitlebar) {
|
||||
SetDrawsInTitlebar(false);
|
||||
}
|
||||
else if (aName == nsGkAtoms::drawtitle) {
|
||||
SetDrawsTitle(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1829,6 +1836,17 @@ nsXULElement::SetDrawsInTitlebar(bool aState)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXULElement::SetDrawsTitle(bool aState)
|
||||
{
|
||||
nsIWidget* mainWidget = GetWindowWidget();
|
||||
if (mainWidget) {
|
||||
// We can do this synchronously because SetDrawsTitle doesn't have any
|
||||
// synchronous effects apart from a harmless invalidation.
|
||||
mainWidget->SetDrawsTitle(aState);
|
||||
}
|
||||
}
|
||||
|
||||
class MarginSetter : public nsRunnable
|
||||
{
|
||||
public:
|
||||
|
@ -680,6 +680,7 @@ protected:
|
||||
void SetTitlebarColor(nscolor aColor, bool aActive);
|
||||
|
||||
void SetDrawsInTitlebar(bool aState);
|
||||
void SetDrawsTitle(bool aState);
|
||||
|
||||
void RemoveBroadcaster(const nsAString & broadcasterId);
|
||||
|
||||
|
@ -91,6 +91,7 @@
|
||||
|
||||
// Interfaces Needed
|
||||
#include "nsIUploadChannel.h"
|
||||
#include "nsIUploadChannel2.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsILayoutHistoryState.h"
|
||||
#include "nsITimer.h"
|
||||
@ -401,8 +402,8 @@ static void
|
||||
OnPingTimeout(nsITimer *timer, void *closure)
|
||||
{
|
||||
nsILoadGroup *loadGroup = static_cast<nsILoadGroup *>(closure);
|
||||
loadGroup->Cancel(NS_ERROR_ABORT);
|
||||
loadGroup->Release();
|
||||
if (loadGroup)
|
||||
loadGroup->Cancel(NS_ERROR_ABORT);
|
||||
}
|
||||
|
||||
// Check to see if two URIs have the same host or not
|
||||
@ -426,19 +427,52 @@ public:
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
nsPingListener(bool requireSameHost, nsIContent* content)
|
||||
nsPingListener(bool requireSameHost, nsIContent* content, nsILoadGroup* loadGroup)
|
||||
: mRequireSameHost(requireSameHost),
|
||||
mContent(content)
|
||||
mContent(content),
|
||||
mLoadGroup(loadGroup)
|
||||
{}
|
||||
|
||||
~nsPingListener();
|
||||
|
||||
NS_IMETHODIMP StartTimeout();
|
||||
|
||||
private:
|
||||
bool mRequireSameHost;
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsPingListener, nsIStreamListener, nsIRequestObserver,
|
||||
nsIInterfaceRequestor, nsIChannelEventSink)
|
||||
|
||||
nsPingListener::~nsPingListener()
|
||||
{
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
mTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPingListener::StartTimeout()
|
||||
{
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
|
||||
if (timer) {
|
||||
nsresult rv = timer->InitWithFuncCallback(OnPingTimeout, mLoadGroup,
|
||||
PING_TIMEOUT,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mTimer = timer;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPingListener::OnStartRequest(nsIRequest *request, nsISupports *context)
|
||||
{
|
||||
@ -458,6 +492,7 @@ NS_IMETHODIMP
|
||||
nsPingListener::OnStopRequest(nsIRequest *request, nsISupports *context,
|
||||
nsresult status)
|
||||
{
|
||||
mLoadGroup = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -506,6 +541,7 @@ struct SendPingInfo {
|
||||
int32_t numPings;
|
||||
int32_t maxPings;
|
||||
bool requireSameHost;
|
||||
nsIURI *target;
|
||||
nsIURI *referrer;
|
||||
};
|
||||
|
||||
@ -542,8 +578,6 @@ SendPing(void *closure, nsIContent *content, nsIURI *uri, nsIIOService *ios)
|
||||
if (httpInternal)
|
||||
httpInternal->SetDocumentURI(doc->GetDocumentURI());
|
||||
|
||||
if (info->referrer)
|
||||
httpChan->SetReferrer(info->referrer);
|
||||
|
||||
httpChan->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
|
||||
|
||||
@ -555,20 +589,56 @@ SendPing(void *closure, nsIContent *content, nsIURI *uri, nsIIOService *ios)
|
||||
httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-encoding"),
|
||||
EmptyCString(), false);
|
||||
|
||||
nsCOMPtr<nsIUploadChannel> uploadChan = do_QueryInterface(httpChan);
|
||||
// Always send a Ping-To header.
|
||||
nsAutoCString pingTo;
|
||||
if (NS_SUCCEEDED(info->target->GetSpec(pingTo)))
|
||||
httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-To"), pingTo, false);
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> sm =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
|
||||
|
||||
if (sm && info->referrer) {
|
||||
bool referrerIsSecure;
|
||||
uint32_t flags = nsIProtocolHandler::URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT;
|
||||
nsresult rv = NS_URIChainHasFlags(info->referrer, flags, &referrerIsSecure);
|
||||
|
||||
// Default to sending less data if NS_URIChainHasFlags() fails.
|
||||
referrerIsSecure = NS_FAILED(rv) || referrerIsSecure;
|
||||
|
||||
bool sameOrigin =
|
||||
NS_SUCCEEDED(sm->CheckSameOriginURI(info->referrer, uri, false));
|
||||
|
||||
// If both the address of the document containing the hyperlink being
|
||||
// audited and "ping URL" have the same origin or the document containing
|
||||
// the hyperlink being audited was not retrieved over an encrypted
|
||||
// connection, send a Ping-From header.
|
||||
if (sameOrigin || !referrerIsSecure) {
|
||||
nsAutoCString pingFrom;
|
||||
if (NS_SUCCEEDED(info->referrer->GetSpec(pingFrom)))
|
||||
httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-From"), pingFrom, false);
|
||||
}
|
||||
|
||||
// If the document containing the hyperlink being audited was not retrieved
|
||||
// over an encrypted connection and its address does not have the same
|
||||
// origin as "ping URL", send a referrer.
|
||||
if (!sameOrigin && !referrerIsSecure)
|
||||
httpChan->SetReferrer(info->referrer);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIUploadChannel2> uploadChan = do_QueryInterface(httpChan);
|
||||
if (!uploadChan)
|
||||
return;
|
||||
|
||||
// To avoid sending an unnecessary Content-Type header, we encode the
|
||||
// closing portion of the headers in the POST body.
|
||||
NS_NAMED_LITERAL_CSTRING(uploadData, "Content-Length: 0\r\n\r\n");
|
||||
NS_NAMED_LITERAL_CSTRING(uploadData, "PING");
|
||||
|
||||
nsCOMPtr<nsIInputStream> uploadStream;
|
||||
NS_NewPostDataStream(getter_AddRefs(uploadStream), false, uploadData);
|
||||
if (!uploadStream)
|
||||
return;
|
||||
|
||||
uploadChan->SetUploadStream(uploadStream, EmptyCString(), -1);
|
||||
uploadChan->ExplicitSetUploadStream(uploadStream,
|
||||
NS_LITERAL_CSTRING("text/ping"), uploadData.Length(),
|
||||
NS_LITERAL_CSTRING("POST"), false);
|
||||
|
||||
// The channel needs to have a loadgroup associated with it, so that we can
|
||||
// cancel the channel and any redirected channels it may create.
|
||||
@ -581,11 +651,14 @@ SendPing(void *closure, nsIContent *content, nsIURI *uri, nsIIOService *ios)
|
||||
// Construct a listener that merely discards any response. If successful at
|
||||
// opening the channel, then it is not necessary to hold a reference to the
|
||||
// channel. The networking subsystem will take care of that for us.
|
||||
nsCOMPtr<nsIStreamListener> listener =
|
||||
new nsPingListener(info->requireSameHost, content);
|
||||
if (!listener)
|
||||
nsPingListener *pingListener =
|
||||
new nsPingListener(info->requireSameHost, content, loadGroup);
|
||||
if (!pingListener)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIStreamListener> listener =
|
||||
static_cast<nsIStreamListener*>(pingListener);
|
||||
|
||||
// Observe redirects as well:
|
||||
nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(listener);
|
||||
NS_ASSERTION(callbacks, "oops");
|
||||
@ -599,29 +672,16 @@ SendPing(void *closure, nsIContent *content, nsIURI *uri, nsIIOService *ios)
|
||||
info->numPings++;
|
||||
|
||||
// Prevent ping requests from stalling and never being garbage collected...
|
||||
nsCOMPtr<nsITimer> timer =
|
||||
do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
if (timer) {
|
||||
nsresult rv = timer->InitWithFuncCallback(OnPingTimeout, loadGroup,
|
||||
PING_TIMEOUT,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// When the timer expires, the callback function will release this
|
||||
// reference to the loadgroup.
|
||||
static_cast<nsILoadGroup *>(loadGroup.get())->AddRef();
|
||||
loadGroup = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If we failed to setup the timer, then we should just cancel the channel
|
||||
// because we won't be able to ensure that it goes away in a timely manner.
|
||||
if (loadGroup)
|
||||
if (NS_FAILED(pingListener->StartTimeout())) {
|
||||
// If we failed to setup the timer, then we should just cancel the channel
|
||||
// because we won't be able to ensure that it goes away in a timely manner.
|
||||
chan->Cancel(NS_ERROR_ABORT);
|
||||
}
|
||||
}
|
||||
|
||||
// Spec: http://whatwg.org/specs/web-apps/current-work/#ping
|
||||
static void
|
||||
DispatchPings(nsIContent *content, nsIURI *referrer)
|
||||
DispatchPings(nsIContent *content, nsIURI *target, nsIURI *referrer)
|
||||
{
|
||||
SendPingInfo info;
|
||||
|
||||
@ -631,6 +691,7 @@ DispatchPings(nsIContent *content, nsIURI *referrer)
|
||||
return;
|
||||
|
||||
info.numPings = 0;
|
||||
info.target = target;
|
||||
info.referrer = referrer;
|
||||
|
||||
ForEachPing(content, SendPing, &info);
|
||||
@ -12543,7 +12604,7 @@ nsDocShell::OnLinkClickSync(nsIContent *aContent,
|
||||
aDocShell, // DocShell out-param
|
||||
aRequest); // Request out-param
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
DispatchPings(aContent, referer);
|
||||
DispatchPings(aContent, aURI, referer);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -115,7 +115,6 @@
|
||||
#include "nsIDOMCRMFObject.h"
|
||||
#endif
|
||||
#include "nsIControllers.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsIBoxObject.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsITreeSelection.h"
|
||||
@ -351,9 +350,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
NS_DEFINE_CLASSINFO_DATA(CSSStyleSheet, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(Selection, nsDOMGenericSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
// XUL classes
|
||||
#ifdef MOZ_XUL
|
||||
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCommandDispatcher, nsDOMGenericSH,
|
||||
@ -1041,10 +1037,6 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSStyleSheet)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(Selection, nsISelection)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsISelection)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
DOM_CLASSINFO_MAP_BEGIN(XULCommandDispatcher, nsIDOMXULCommandDispatcher)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCommandDispatcher)
|
||||
|
@ -22,9 +22,6 @@ DOMCI_CLASS(CSSRuleList)
|
||||
DOMCI_CLASS(StyleSheetList)
|
||||
DOMCI_CLASS(CSSStyleSheet)
|
||||
|
||||
// Range classes
|
||||
DOMCI_CLASS(Selection)
|
||||
|
||||
// XUL classes
|
||||
#ifdef MOZ_XUL
|
||||
DOMCI_CLASS(XULCommandDispatcher)
|
||||
|
@ -209,7 +209,6 @@
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "nsITabChild.h"
|
||||
#include "nsIDOMMediaQueryList.h"
|
||||
#include "mozilla/dom/MediaQueryList.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
||||
@ -5053,11 +5052,10 @@ nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
|
||||
nsIDOMMediaQueryList** aResult)
|
||||
nsISupports** aResult)
|
||||
{
|
||||
ErrorResult rv;
|
||||
nsCOMPtr<nsIDOMMediaQueryList> mediaQueryList =
|
||||
MatchMedia(aMediaQueryList, rv);
|
||||
nsRefPtr<MediaQueryList> mediaQueryList = MatchMedia(aMediaQueryList, rv);
|
||||
mediaQueryList.forget(aResult);
|
||||
|
||||
return rv.ErrorCode();
|
||||
@ -8821,7 +8819,7 @@ nsGlobalWindow::UpdateCommands(const nsAString& anAction)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsISelection*
|
||||
Selection*
|
||||
nsGlobalWindow::GetSelection(ErrorResult& aError)
|
||||
{
|
||||
FORWARD_TO_OUTER_OR_THROW(GetSelection, (aError), aError, nullptr);
|
||||
@ -8834,8 +8832,8 @@ nsGlobalWindow::GetSelection(ErrorResult& aError)
|
||||
if (!presShell) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
|
||||
return static_cast<Selection*>(presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -104,6 +104,7 @@ struct nsRect;
|
||||
class nsWindowSizes;
|
||||
|
||||
namespace mozilla {
|
||||
class Selection;
|
||||
namespace dom {
|
||||
class BarProp;
|
||||
class Function;
|
||||
@ -846,7 +847,7 @@ public:
|
||||
mozilla::ErrorResult& aError);
|
||||
nsIDOMStorage* GetSessionStorage(mozilla::ErrorResult& aError);
|
||||
nsIDOMStorage* GetLocalStorage(mozilla::ErrorResult& aError);
|
||||
nsISelection* GetSelection(mozilla::ErrorResult& aError);
|
||||
mozilla::Selection* GetSelection(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::indexedDB::IDBFactory* GetIndexedDB(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsICSSDeclaration>
|
||||
GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
|
||||
|
@ -965,6 +965,11 @@ DOMInterfaces = {
|
||||
'nativeType': 'nsDOMScrollAreaEvent',
|
||||
},
|
||||
|
||||
'Selection': {
|
||||
'nativeType': 'mozilla::Selection',
|
||||
'resultNotAddRefed': [ 'anchorNode', 'focusNode', 'getRangeAt' ],
|
||||
},
|
||||
|
||||
'ShadowRoot': {
|
||||
'resultNotAddRefed': [
|
||||
'styleSheets'
|
||||
@ -1891,6 +1896,7 @@ addExternalIface('nsIDOMCrypto', nativeType='nsIDOMCrypto',
|
||||
headerFile='Crypto.h')
|
||||
addExternalIface('nsIInputStreamCallback', nativeType='nsIInputStreamCallback',
|
||||
headerFile='nsIAsyncInputStream.h')
|
||||
addExternalIface('nsISelectionListener', nativeType='nsISelectionListener')
|
||||
addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
|
||||
addExternalIface('nsISupports', nativeType='nsISupports')
|
||||
addExternalIface('nsIDocShell', nativeType='nsIDocShell', notflattened=True)
|
||||
@ -1901,7 +1907,6 @@ addExternalIface('OutputStream', nativeType='nsIOutputStream',
|
||||
addExternalIface('Pkcs11')
|
||||
addExternalIface('Principal', nativeType='nsIPrincipal',
|
||||
headerFile='nsIPrincipal.h', notflattened=True)
|
||||
addExternalIface('Selection', nativeType='nsISelection')
|
||||
addExternalIface('StackFrame', nativeType='nsIStackFrame',
|
||||
headerFile='nsIException.h', notflattened=True)
|
||||
addExternalIface('StyleSheetList')
|
||||
|
@ -12,20 +12,27 @@ namespace dom {
|
||||
static const PRUnichar kReplacementChar = static_cast<PRUnichar>(0xFFFD);
|
||||
|
||||
void
|
||||
TextDecoder::Init(const nsAString& aEncoding, const bool aFatal,
|
||||
TextDecoder::Init(const nsAString& aLabel, const bool aFatal,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsAutoString label(aEncoding);
|
||||
nsAutoString label(aLabel);
|
||||
EncodingUtils::TrimSpaceCharacters(label);
|
||||
|
||||
nsAutoCString encoding;
|
||||
// Let encoding be the result of getting an encoding from label.
|
||||
// If encoding is failure or replacement, throw a TypeError.
|
||||
if (!EncodingUtils::FindEncodingForLabel(label, mEncoding) ||
|
||||
mEncoding.EqualsLiteral("replacement")) {
|
||||
if (!EncodingUtils::FindEncodingForLabel(label, encoding) ||
|
||||
encoding.EqualsLiteral("replacement")) {
|
||||
aRv.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &label);
|
||||
return;
|
||||
}
|
||||
InitWithEncoding(encoding, aFatal);
|
||||
}
|
||||
|
||||
void
|
||||
TextDecoder::InitWithEncoding(const nsACString& aEncoding, const bool aFatal)
|
||||
{
|
||||
mEncoding = aEncoding;
|
||||
// If the constructor is called with an options argument,
|
||||
// and the fatal property of the dictionary is set,
|
||||
// set the internal fatal flag of the decoder object.
|
||||
|
@ -59,16 +59,24 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates provided encoding and throws an exception if invalid encoding.
|
||||
* If no encoding is provided then mEncoding is default initialised to "utf-8".
|
||||
* Validates provided label and throws an exception if invalid label.
|
||||
*
|
||||
* @param aEncoding Optional encoding (case insensitive) provided.
|
||||
* Default value is "utf-8" if no encoding is provided.
|
||||
* @param aFatal aFatal, indicates whether to throw an 'EncodingError'
|
||||
* exception or not.
|
||||
* @param aLabel The encoding label (case insensitive) provided.
|
||||
* @param aFatal indicates whether to throw an 'EncodingError'
|
||||
* exception or not when decoding.
|
||||
* @return aRv EncodingError exception else null.
|
||||
*/
|
||||
void Init(const nsAString& aEncoding, const bool aFatal, ErrorResult& aRv);
|
||||
void Init(const nsAString& aLabel, const bool aFatal, ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Performs initialization with a Gecko-canonical encoding name (as opposed
|
||||
* to a label.)
|
||||
*
|
||||
* @param aEncoding A Gecko-canonical encoding name
|
||||
* @param aFatal indicates whether to throw an 'EncodingError'
|
||||
* exception or not when decoding.
|
||||
*/
|
||||
void InitWithEncoding(const nsACString& aEncoding, const bool aFatal);
|
||||
|
||||
/**
|
||||
* Return the encoding name.
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mozilla/dom/ArchiveReaderBinding.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -35,13 +36,20 @@ ArchiveReader::Constructor(const GlobalObject& aGlobal,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsAutoCString encoding;
|
||||
if (!EncodingUtils::FindEncodingForLabel(aOptions.mEncoding, encoding) ||
|
||||
encoding.EqualsLiteral("replacement")) {
|
||||
aError.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &aOptions.mEncoding);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<ArchiveReader> reader =
|
||||
new ArchiveReader(aBlob, window, aOptions.mEncoding);
|
||||
new ArchiveReader(aBlob, window, encoding);
|
||||
return reader.forget();
|
||||
}
|
||||
|
||||
ArchiveReader::ArchiveReader(nsIDOMBlob* aBlob, nsPIDOMWindow* aWindow,
|
||||
const nsString& aEncoding)
|
||||
const nsACString& aEncoding)
|
||||
: mBlob(aBlob)
|
||||
, mWindow(aWindow)
|
||||
, mStatus(NOT_STARTED)
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
const ArchiveReaderOptions& aOptions, ErrorResult& aError);
|
||||
|
||||
ArchiveReader(nsIDOMBlob* aBlob, nsPIDOMWindow* aWindow,
|
||||
const nsString& aEncoding);
|
||||
const nsACString& aEncoding);
|
||||
|
||||
nsIDOMWindow* GetParentObject() const
|
||||
{
|
||||
@ -107,7 +107,7 @@ protected:
|
||||
nsresult status;
|
||||
} mData;
|
||||
|
||||
nsString mEncoding;
|
||||
nsCString mEncoding;
|
||||
};
|
||||
|
||||
END_FILE_NAMESPACE
|
||||
|
@ -22,7 +22,7 @@ USING_FILE_NAMESPACE
|
||||
|
||||
ArchiveZipItem::ArchiveZipItem(const char* aFilename,
|
||||
const ZipCentral& aCentralStruct,
|
||||
const nsAString& aEncoding)
|
||||
const nsACString& aEncoding)
|
||||
: mFilename(aFilename),
|
||||
mCentralStruct(aCentralStruct),
|
||||
mEncoding(aEncoding)
|
||||
@ -43,8 +43,8 @@ ArchiveZipItem::ConvertFilename()
|
||||
}
|
||||
|
||||
nsString filenameU;
|
||||
nsresult rv = nsContentUtils::ConvertStringFromCharset(
|
||||
NS_ConvertUTF16toUTF8(mEncoding),
|
||||
nsresult rv = nsContentUtils::ConvertStringFromEncoding(
|
||||
mEncoding,
|
||||
mFilename, filenameU);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -111,7 +111,7 @@ ArchiveZipItem::StrToInt16(const uint8_t* aStr)
|
||||
// ArchiveReaderZipEvent
|
||||
|
||||
ArchiveReaderZipEvent::ArchiveReaderZipEvent(ArchiveReader* aArchiveReader,
|
||||
const nsAString& aEncoding)
|
||||
const nsACString& aEncoding)
|
||||
: ArchiveReaderEvent(aArchiveReader),
|
||||
mEncoding(aEncoding)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ class ArchiveZipItem : public ArchiveItem
|
||||
public:
|
||||
ArchiveZipItem(const char* aFilename,
|
||||
const ZipCentral& aCentralStruct,
|
||||
const nsAString& aEncoding);
|
||||
const nsACString& aEncoding);
|
||||
virtual ~ArchiveZipItem();
|
||||
|
||||
nsresult GetFilename(nsString& aFilename) MOZ_OVERRIDE;
|
||||
@ -46,7 +46,7 @@ private: // data
|
||||
nsString mFilenameU;
|
||||
ZipCentral mCentralStruct;
|
||||
|
||||
nsString mEncoding;
|
||||
nsCString mEncoding;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -56,12 +56,12 @@ class ArchiveReaderZipEvent : public ArchiveReaderEvent
|
||||
{
|
||||
public:
|
||||
ArchiveReaderZipEvent(ArchiveReader* aArchiveReader,
|
||||
const nsAString& aEncoding);
|
||||
const nsACString& aEncoding);
|
||||
|
||||
nsresult Exec() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
nsString mEncoding;
|
||||
nsCString mEncoding;
|
||||
};
|
||||
|
||||
END_FILE_NAMESPACE
|
||||
|
@ -1040,25 +1040,26 @@ ReadTextHelper::GetSuccessResult(JSContext* aCx,
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCString charsetGuess;
|
||||
if (!mEncoding.IsEmpty()) {
|
||||
CopyUTF16toUTF8(mEncoding, charsetGuess);
|
||||
}
|
||||
else {
|
||||
const nsCString& data = mStream->Data();
|
||||
uint32_t dataLen = data.Length();
|
||||
rv = nsContentUtils::GuessCharset(data.get(), dataLen, charsetGuess);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCString charset;
|
||||
if (!EncodingUtils::FindEncodingForLabel(charsetGuess, charset)) {
|
||||
return NS_ERROR_DOM_ENCODING_NOT_SUPPORTED_ERR;
|
||||
nsAutoCString encoding;
|
||||
const nsCString& data = mStream->Data();
|
||||
// The BOM sniffing is baked into the "decode" part of the Encoding
|
||||
// Standard, which the File API references.
|
||||
if (!nsContentUtils::CheckForBOM(
|
||||
reinterpret_cast<const unsigned char *>(data.get()),
|
||||
data.Length(),
|
||||
encoding)) {
|
||||
// BOM sniffing failed. Try the API argument.
|
||||
if (!EncodingUtils::FindEncodingForLabel(mEncoding, encoding)) {
|
||||
// API argument failed. Since we are dealing with a file system file,
|
||||
// we don't have a meaningful type attribute for the blob available,
|
||||
// so proceeding to the next step, which is defaulting to UTF-8.
|
||||
encoding.AssignLiteral("UTF-8");
|
||||
}
|
||||
}
|
||||
|
||||
nsString tmpString;
|
||||
rv = nsContentUtils::ConvertStringFromCharset(charset, mStream->Data(),
|
||||
tmpString);
|
||||
rv = nsContentUtils::ConvertStringFromEncoding(encoding, data,
|
||||
tmpString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JS::Value> rval(aCx);
|
||||
|
@ -59,17 +59,11 @@
|
||||
{
|
||||
var binaryFile = createNonUnicodeData();
|
||||
|
||||
var r = new ArchiveReader(binaryFile, { encoding: "random stuff" });
|
||||
isnot(r, null, "ArchiveReader cannot be null");
|
||||
|
||||
// GetFilename
|
||||
var handle = r.getFilenames();
|
||||
isnot(handle, null, "ArchiveReader.getFilenames() cannot be null");
|
||||
handle.onsuccess = function() {
|
||||
ok(true, "ArchiveReader.getFilenames() should return a 'success'");
|
||||
is(this.result instanceof Array, true, "ArchiveReader.getFilenames() should return an array");
|
||||
is(this.result.length, 0, "ArchiveReader.getFilenames(): the array contains 0 item");
|
||||
ok(this.reader, r, "ArchiveRequest.reader should be == ArchiveReader");
|
||||
try {
|
||||
new ArchiveReader(binaryFile, { encoding: "random stuff" });
|
||||
ok(false, "Should have thrown for bogus encoding label.");
|
||||
} catch (e) {
|
||||
ok(e instanceof TypeError, "Expected a TypeError");
|
||||
finishTest();
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ MOCHITEST_FILES := \
|
||||
test_collapseToStartEnd.html.json \
|
||||
test_extend.html.json \
|
||||
test_getSelection.html.json \
|
||||
test_interfaces.html.json \
|
||||
test_removeAllRanges.html.json \
|
||||
test_selectAllChildren.html.json \
|
||||
$(NULL)
|
||||
|
@ -1,18 +0,0 @@
|
||||
{
|
||||
"Selection interface: existence and properties of interface object":true,
|
||||
"Selection interface: existence and properties of interface prototype object":true,
|
||||
"Selection interface object length":true,
|
||||
"Selection interface: existence and properties of interface prototype object's \"constructor\" property":true,
|
||||
"Selection interface: attribute anchorNode":true,
|
||||
"Selection interface: attribute anchorOffset":true,
|
||||
"Selection interface: attribute focusNode":true,
|
||||
"Selection interface: attribute focusOffset":true,
|
||||
"Selection interface: attribute isCollapsed":true,
|
||||
"Selection interface: attribute rangeCount":true,
|
||||
"Selection interface: calling collapse(Node,unsigned long) on getSelection() with too few arguments must throw TypeError":true,
|
||||
"Selection interface: calling extend(Node,unsigned long) on getSelection() with too few arguments must throw TypeError":true,
|
||||
"Selection interface: calling selectAllChildren(Node) on getSelection() with too few arguments must throw TypeError":true,
|
||||
"Selection interface: calling getRangeAt(unsigned long) on getSelection() with too few arguments must throw TypeError":true,
|
||||
"Selection interface: calling addRange(Range) on getSelection() with too few arguments must throw TypeError":true,
|
||||
"Selection interface: calling removeRange(Range) on getSelection() with too few arguments must throw TypeError":true
|
||||
}
|
@ -74,6 +74,8 @@ skip-if = os == "mac" || os == "android"
|
||||
[test_setVersion_exclusion.js]
|
||||
[test_success_events_after_abort.js]
|
||||
[test_temporary_storage.js]
|
||||
# bug 951017: intermittent failure on Android x86 emulator
|
||||
skip-if = os == "android" && processor == "x86"
|
||||
[test_traffic_jam.js]
|
||||
[test_transaction_abort.js]
|
||||
[test_transaction_abort_hang.js]
|
||||
|
@ -22,7 +22,6 @@ XPIDL_SOURCES += [
|
||||
'nsIDOMHistory.idl',
|
||||
'nsIDOMJSWindow.idl',
|
||||
'nsIDOMLocation.idl',
|
||||
'nsIDOMMediaQueryList.idl',
|
||||
'nsIDOMModalContentWindow.idl',
|
||||
'nsIDOMNavigator.idl',
|
||||
'nsIDOMPkcs11.idl',
|
||||
|
@ -1,26 +0,0 @@
|
||||
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
||||
/* 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 "domstubs.idl"
|
||||
|
||||
interface nsIDOMMediaQueryListListener;
|
||||
|
||||
/* see http://dev.w3.org/csswg/cssom-view/#the-mediaquerylist-interface */
|
||||
|
||||
[scriptable, uuid(e0e49c52-915b-40f9-9cba-6026305cdf3e)]
|
||||
interface nsIDOMMediaQueryList : nsISupports
|
||||
{
|
||||
readonly attribute DOMString media;
|
||||
readonly attribute boolean matches;
|
||||
|
||||
void addListener(in nsIDOMMediaQueryListListener listener);
|
||||
void removeListener(in nsIDOMMediaQueryListListener listener);
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(279a5cbd-5c15-475d-847b-e0de1624eb77)]
|
||||
interface nsIDOMMediaQueryListListener : nsISupports
|
||||
{
|
||||
void handleChange(in nsIDOMMediaQueryList mql);
|
||||
};
|
@ -9,7 +9,6 @@ interface nsIFrameRequestCallback;
|
||||
interface nsIControllers;
|
||||
interface nsIDOMBlob;
|
||||
interface nsIDOMLocation;
|
||||
interface nsIDOMMediaQueryList;
|
||||
interface nsIDOMOfflineResourceList;
|
||||
interface nsIDOMStorage;
|
||||
interface nsIPrompt;
|
||||
@ -265,7 +264,7 @@ interface nsIDOMWindow : nsISupports
|
||||
|
||||
// CSSOM-View
|
||||
// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface
|
||||
nsIDOMMediaQueryList matchMedia(in DOMString media_query_list);
|
||||
nsISupports matchMedia(in DOMString media_query_list);
|
||||
|
||||
readonly attribute nsIDOMScreen screen;
|
||||
|
||||
|
@ -4,8 +4,6 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
interface Selection;
|
||||
|
||||
[OverrideBuiltins]
|
||||
interface HTMLDocument : Document {
|
||||
[Throws]
|
||||
@ -79,7 +77,7 @@ interface HTMLDocument : Document {
|
||||
|
||||
// https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#selections
|
||||
[Throws]
|
||||
Selection getSelection();
|
||||
Selection? getSelection();
|
||||
|
||||
// @deprecated These are old Netscape 4 methods. Do not use,
|
||||
// the implementation is no-op.
|
||||
|
@ -62,6 +62,7 @@ PluginArray implements LegacyQueryInterface;
|
||||
ProcessingInstruction implements LegacyQueryInterface;
|
||||
Range implements LegacyQueryInterface;
|
||||
Rect implements LegacyQueryInterface;
|
||||
Selection implements LegacyQueryInterface;
|
||||
SVGAnimatedEnumeration implements LegacyQueryInterface;
|
||||
SVGAnimatedInteger implements LegacyQueryInterface;
|
||||
SVGAnimatedNumber implements LegacyQueryInterface;
|
||||
|
85
dom/webidl/Selection.webidl
Normal file
85
dom/webidl/Selection.webidl
Normal file
@ -0,0 +1,85 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#concept-selection
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
interface Selection {
|
||||
readonly attribute Node? anchorNode;
|
||||
readonly attribute unsigned long anchorOffset;
|
||||
readonly attribute Node? focusNode;
|
||||
readonly attribute unsigned long focusOffset;
|
||||
|
||||
readonly attribute boolean isCollapsed;
|
||||
[Throws]
|
||||
void collapse(Node node, unsigned long offset);
|
||||
[Throws]
|
||||
void collapseToStart();
|
||||
[Throws]
|
||||
void collapseToEnd();
|
||||
|
||||
[Throws]
|
||||
void extend(Node node, unsigned long offset);
|
||||
|
||||
[Throws]
|
||||
void selectAllChildren(Node node);
|
||||
[Throws]
|
||||
void deleteFromDocument();
|
||||
|
||||
readonly attribute unsigned long rangeCount;
|
||||
[Throws]
|
||||
Range getRangeAt(unsigned long index);
|
||||
[Throws]
|
||||
void addRange(Range range);
|
||||
[Throws]
|
||||
void removeRange(Range range);
|
||||
[Throws]
|
||||
void removeAllRanges();
|
||||
|
||||
stringifier;
|
||||
};
|
||||
|
||||
// Additional methods not currently in the spec
|
||||
partial interface Selection {
|
||||
[Throws]
|
||||
boolean containsNode(Node? node, boolean partlyContained);
|
||||
|
||||
[Throws]
|
||||
void modify(DOMString alter, DOMString direction,
|
||||
DOMString granularity);
|
||||
};
|
||||
|
||||
// Additional chrome-only methods from nsISelectionPrivate
|
||||
interface nsISelectionListener;
|
||||
partial interface Selection {
|
||||
[ChromeOnly]
|
||||
const short ENDOFPRECEDINGLINE = 0;
|
||||
[ChromeOnly]
|
||||
const short STARTOFNEXTLINE = 1;
|
||||
|
||||
[ChromeOnly,Throws]
|
||||
attribute boolean interlinePosition;
|
||||
|
||||
[ChromeOnly,Throws]
|
||||
DOMString toStringWithFormat(DOMString formatType, unsigned long flags, long wrapColumn);
|
||||
[ChromeOnly,Throws]
|
||||
void addSelectionListener(nsISelectionListener newListener);
|
||||
[ChromeOnly,Throws]
|
||||
void removeSelectionListener(nsISelectionListener listenerToRemove);
|
||||
|
||||
[ChromeOnly]
|
||||
readonly attribute short type;
|
||||
|
||||
[ChromeOnly,Throws,Pref="dom.testing.selection.GetRangesForInterval"]
|
||||
sequence<Range> GetRangesForInterval(Node beginNode, long beginOffset, Node endNode, long endOffset,
|
||||
boolean allowAdjacent);
|
||||
|
||||
[ChromeOnly,Throws]
|
||||
void scrollIntoView(short aRegion, boolean aIsSynchronous, short aVPercent, short aHPercent);
|
||||
};
|
@ -274,6 +274,7 @@ WEBIDL_FILES = [
|
||||
'Screen.webidl',
|
||||
'ScriptProcessorNode.webidl',
|
||||
'ScrollAreaEvent.webidl',
|
||||
'Selection.webidl',
|
||||
'SettingsManager.webidl',
|
||||
'ShadowRoot.webidl',
|
||||
'SharedWorker.webidl',
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "jsfriendapi.h"
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/dom/FileReaderSyncBinding.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
@ -16,13 +17,10 @@
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsICharsetDetector.h"
|
||||
#include "nsIConverterInputStream.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
@ -34,13 +32,6 @@ using namespace mozilla;
|
||||
using mozilla::dom::Optional;
|
||||
using mozilla::dom::GlobalObject;
|
||||
|
||||
NS_IMPL_ADDREF(FileReaderSync)
|
||||
NS_IMPL_RELEASE(FileReaderSync)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(FileReaderSync)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
// static
|
||||
already_AddRefed<FileReaderSync>
|
||||
FileReaderSync::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
@ -159,37 +150,57 @@ FileReaderSync::ReadAsText(JS::Handle<JSObject*> aBlob,
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString charsetGuess;
|
||||
if (!aEncoding.WasPassed() || aEncoding.Value().IsEmpty()) {
|
||||
rv = GuessCharset(stream, charsetGuess);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(stream);
|
||||
if (!seekable) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Seek to 0 because guessing the charset advances the stream.
|
||||
rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
CopyUTF16toUTF8(aEncoding.Value(), charsetGuess);
|
||||
}
|
||||
|
||||
nsCString charset;
|
||||
if (!EncodingUtils::FindEncodingForLabel(charsetGuess, charset)) {
|
||||
aRv.Throw(NS_ERROR_DOM_ENCODING_NOT_SUPPORTED_ERR);
|
||||
nsAutoCString encoding;
|
||||
unsigned char sniffBuf[3] = { 0, 0, 0 };
|
||||
uint32_t numRead;
|
||||
rv = stream->Read(reinterpret_cast<char*>(sniffBuf),
|
||||
sizeof(sniffBuf), &numRead);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
rv = ConvertStream(stream, charset.get(), aResult);
|
||||
// The BOM sniffing is baked into the "decode" part of the Encoding
|
||||
// Standard, which the File API references.
|
||||
if (!nsContentUtils::CheckForBOM(sniffBuf, numRead, encoding)) {
|
||||
// BOM sniffing failed. Try the API argument.
|
||||
if (!aEncoding.WasPassed() ||
|
||||
!EncodingUtils::FindEncodingForLabel(aEncoding.Value(),
|
||||
encoding)) {
|
||||
// API argument failed. Try the type property of the blob.
|
||||
nsAutoString type16;
|
||||
blob->GetType(type16);
|
||||
NS_ConvertUTF16toUTF8 type(type16);
|
||||
nsAutoCString specifiedCharset;
|
||||
bool haveCharset;
|
||||
int32_t charsetStart, charsetEnd;
|
||||
NS_ExtractCharsetFromContentType(type,
|
||||
specifiedCharset,
|
||||
&haveCharset,
|
||||
&charsetStart,
|
||||
&charsetEnd);
|
||||
if (!EncodingUtils::FindEncodingForLabel(specifiedCharset, encoding)) {
|
||||
// Type property failed. Use UTF-8.
|
||||
encoding.AssignLiteral("UTF-8");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(stream);
|
||||
if (!seekable) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Seek to 0 because to undo the BOM sniffing advance. UTF-8 and UTF-16
|
||||
// decoders will swallow the BOM.
|
||||
rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
rv = ConvertStream(stream, encoding.get(), aResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
@ -283,91 +294,3 @@ FileReaderSync::ConvertStream(nsIInputStream *aStream,
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FileReaderSync::GuessCharset(nsIInputStream *aStream, nsACString &aCharset)
|
||||
{
|
||||
// First try the universal charset detector
|
||||
nsCOMPtr<nsICharsetDetector> detector
|
||||
= do_CreateInstance(NS_CHARSET_DETECTOR_CONTRACTID_BASE
|
||||
"universal_charset_detector");
|
||||
if (!detector) {
|
||||
RuntimeService* runtime = RuntimeService::GetService();
|
||||
NS_ASSERTION(runtime, "This should never be null!");
|
||||
|
||||
// No universal charset detector, try the default charset detector
|
||||
const nsACString& detectorName = runtime->GetDetectorName();
|
||||
|
||||
if (!detectorName.IsEmpty()) {
|
||||
nsAutoCString detectorContractID;
|
||||
detectorContractID.AssignLiteral(NS_CHARSET_DETECTOR_CONTRACTID_BASE);
|
||||
detectorContractID += detectorName;
|
||||
detector = do_CreateInstance(detectorContractID.get());
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
if (detector) {
|
||||
detector->Init(this);
|
||||
|
||||
bool done;
|
||||
uint32_t numRead;
|
||||
do {
|
||||
char readBuf[4096];
|
||||
rv = aStream->Read(readBuf, sizeof(readBuf), &numRead);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (numRead <= 0) {
|
||||
break;
|
||||
}
|
||||
rv = detector->DoIt(readBuf, numRead, &done);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} while (!done);
|
||||
|
||||
rv = detector->Done();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
// no charset detector available, check the BOM
|
||||
unsigned char sniffBuf[4];
|
||||
uint32_t numRead;
|
||||
rv = aStream->Read(reinterpret_cast<char*>(sniffBuf),
|
||||
sizeof(sniffBuf), &numRead);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (numRead >= 2 &&
|
||||
sniffBuf[0] == 0xfe &&
|
||||
sniffBuf[1] == 0xff) {
|
||||
mCharset = "UTF-16BE";
|
||||
} else if (numRead >= 2 &&
|
||||
sniffBuf[0] == 0xff &&
|
||||
sniffBuf[1] == 0xfe) {
|
||||
mCharset = "UTF-16LE";
|
||||
} else if (numRead >= 3 &&
|
||||
sniffBuf[0] == 0xef &&
|
||||
sniffBuf[1] == 0xbb &&
|
||||
sniffBuf[2] == 0xbf) {
|
||||
mCharset = "UTF-8";
|
||||
}
|
||||
}
|
||||
|
||||
if (mCharset.IsEmpty()) {
|
||||
RuntimeService* runtime = RuntimeService::GetService();
|
||||
mCharset = runtime->GetSystemCharset();
|
||||
}
|
||||
|
||||
if (mCharset.IsEmpty()) {
|
||||
// no sniffed or default charset, try UTF-8
|
||||
mCharset.AssignLiteral("UTF-8");
|
||||
}
|
||||
|
||||
aCharset = mCharset;
|
||||
mCharset.Truncate();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileReaderSync::Notify(const char* aCharset, nsDetectionConfident aConf)
|
||||
{
|
||||
mCharset.Assign(aCharset);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "nsICharsetDetectionObserver.h"
|
||||
|
||||
class nsIInputStream;
|
||||
class nsIDOMBlob;
|
||||
|
||||
@ -25,12 +23,12 @@ template<typename> class Optional;
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class FileReaderSync MOZ_FINAL : public nsICharsetDetectionObserver
|
||||
class FileReaderSync MOZ_FINAL
|
||||
{
|
||||
nsCString mCharset;
|
||||
NS_INLINE_DECL_REFCOUNTING(FileReaderSync)
|
||||
|
||||
nsresult ConvertStream(nsIInputStream *aStream, const char *aCharset,
|
||||
nsAString &aResult);
|
||||
nsresult GuessCharset(nsIInputStream *aStream, nsACString &aCharset);
|
||||
|
||||
public:
|
||||
static already_AddRefed<FileReaderSync>
|
||||
@ -38,8 +36,6 @@ public:
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
JSObject* ReadAsArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aScopeObj,
|
||||
JS::Handle<JSObject*> aBlob,
|
||||
ErrorResult& aRv);
|
||||
@ -50,9 +46,6 @@ public:
|
||||
nsAString& aResult, ErrorResult& aRv);
|
||||
void ReadAsDataURL(JS::Handle<JSObject*> aBlob, nsAString& aResult,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// From nsICharsetDetectionObserver
|
||||
NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
@ -4162,7 +4162,7 @@ nsEditor::DeleteSelectionAndCreateNode(const nsAString& aTag,
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCOMPtr<nsINode> node = selection->GetAnchorNode();
|
||||
int32_t offset = selection->GetAnchorOffset();
|
||||
uint32_t offset = selection->AnchorOffset();
|
||||
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
result = CreateNode(aTag, node->AsDOMNode(), offset,
|
||||
@ -4248,14 +4248,14 @@ nsEditor::DeleteSelectionAndPrepareToCreateNode()
|
||||
"fix the caller");
|
||||
NS_ENSURE_STATE(node->GetParentNode());
|
||||
|
||||
int32_t offset = selection->GetAnchorOffset();
|
||||
uint32_t offset = selection->AnchorOffset();
|
||||
|
||||
if (offset == 0) {
|
||||
res = selection->Collapse(node->GetParentNode(),
|
||||
node->GetParentNode()->IndexOf(node));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(res));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
} else if (offset == (int32_t)node->Length()) {
|
||||
} else if (offset == node->Length()) {
|
||||
res = selection->Collapse(node->GetParentNode(),
|
||||
node->GetParentNode()->IndexOf(node) + 1);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(res));
|
||||
|
@ -369,7 +369,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
|
||||
// pasting does not inherit local inline styles
|
||||
nsCOMPtr<nsIDOMNode> tmpNode =
|
||||
do_QueryInterface(selection->GetAnchorNode());
|
||||
int32_t tmpOffset = selection->GetAnchorOffset();
|
||||
int32_t tmpOffset = static_cast<int32_t>(selection->AnchorOffset());
|
||||
rv = ClearStyle(address_of(tmpNode), &tmpOffset, nullptr, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
@ -2288,7 +2288,7 @@ nsHTMLEditor::GetElementOrParentByTagName(const nsAString& aTagName, nsIDOMNode
|
||||
|
||||
// Try to get the actual selected node
|
||||
if (anchorNode->HasChildNodes() && anchorNode->IsContent()) {
|
||||
int32_t offset = selection->GetAnchorOffset();
|
||||
uint32_t offset = selection->AnchorOffset();
|
||||
current = anchorNode->GetChildAt(offset);
|
||||
}
|
||||
// anchor node is probably a text node - just use that
|
||||
|
@ -10,12 +10,6 @@ ifndef GNU_CC
|
||||
OS_CPPFLAGS += -EHsc
|
||||
endif
|
||||
|
||||
# Since we're building off in our own world, we don't want to have
|
||||
# mozilla-config.h and -DMOZILLA_CLIENT automatically included and defined, so
|
||||
# we just overwrite OS_COMPILE_C(XX)FLAGS.
|
||||
OS_COMPILE_CFLAGS = $(OS_CPPFLAGS)
|
||||
OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS)
|
||||
|
||||
# Below is a transcription of the EGL target from build_angle.gypi.
|
||||
# Target: 'libEGL'
|
||||
# Links with: 'libGLESv2'
|
||||
|
@ -10,12 +10,6 @@ ifndef GNU_CC
|
||||
OS_CPPFLAGS += -EHsc
|
||||
endif
|
||||
|
||||
# Since we're building off in our own world, we don't want to have
|
||||
#
|
||||
# we just overwrite OS_COMPILE_C(XX)FLAGS.
|
||||
OS_COMPILE_CFLAGS = $(OS_CPPFLAGS)
|
||||
OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS)
|
||||
|
||||
# The below is a rough translation of build_angle.gypi,
|
||||
# copied from src/Makefile.in.
|
||||
|
||||
@ -49,6 +43,7 @@ CXXFLAGS += -I'$(MOZ_DIRECTX_SDK_PATH)/include'
|
||||
ifdef GNU_CC
|
||||
|
||||
TextureSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
|
||||
ImageSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
|
||||
|
||||
OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions
|
||||
OS_LIBS += -ld3d9 -ldxguid
|
||||
|
@ -176,7 +176,7 @@ ClientLayerManager::CreateThebesLayerWithHint(ThebesLayerCreationHint aHint)
|
||||
#ifdef MOZ_B2G
|
||||
aHint == SCROLLABLE &&
|
||||
#endif
|
||||
Preferences::GetBool("layers.force-tiles") && AsShadowForwarder()->GetCompositorBackendType() == LAYERS_OPENGL) {
|
||||
gfxPlatform::GetPrefLayersEnableTiles() && AsShadowForwarder()->GetCompositorBackendType() == LAYERS_OPENGL) {
|
||||
nsRefPtr<ClientTiledThebesLayer> layer =
|
||||
new ClientTiledThebesLayer(this);
|
||||
CREATE_SHADOW(Thebes);
|
||||
|
@ -242,9 +242,11 @@ ContentHostBase::UseTextureHost(TextureHost* aTexture)
|
||||
if (aTexture->GetFlags() & TEXTURE_ON_WHITE) {
|
||||
mTextureHost = nullptr;
|
||||
mTextureHostOnWhite = aTexture;
|
||||
mTextureHostOnWhite->SetCompositor(GetCompositor());
|
||||
} else {
|
||||
mTextureHostOnWhite = nullptr;
|
||||
mTextureHost = aTexture;
|
||||
mTextureHost->SetCompositor(GetCompositor());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2045,6 +2045,7 @@ static bool sPrefLayersPreferOpenGL = false;
|
||||
static bool sPrefLayersPreferD3D9 = false;
|
||||
static bool sPrefLayersDump = false;
|
||||
static bool sPrefLayersScrollGraph = false;
|
||||
static bool sPrefLayersEnableTiles = false;
|
||||
static bool sLayersSupportsD3D9 = false;
|
||||
static int sPrefLayoutFrameRate = -1;
|
||||
static bool sBufferRotationEnabled = false;
|
||||
@ -2073,6 +2074,7 @@ InitLayersAccelerationPrefs()
|
||||
sPrefLayersPreferD3D9 = Preferences::GetBool("layers.prefer-d3d9", false);
|
||||
sPrefLayersDump = Preferences::GetBool("layers.dump", false);
|
||||
sPrefLayersScrollGraph = Preferences::GetBool("layers.scroll-graph", false);
|
||||
sPrefLayersEnableTiles = Preferences::GetBool("layers.enable-tiles", false);
|
||||
sPrefLayoutFrameRate = Preferences::GetInt("layout.frame_rate", -1);
|
||||
sBufferRotationEnabled = Preferences::GetBool("layers.bufferrotation.enabled", true);
|
||||
sComponentAlphaEnabled = Preferences::GetBool("layers.componentalpha.enabled", true);
|
||||
@ -2186,6 +2188,13 @@ gfxPlatform::GetPrefLayersScrollGraph()
|
||||
return sPrefLayersScrollGraph;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::GetPrefLayersEnableTiles()
|
||||
{
|
||||
InitLayersAccelerationPrefs();
|
||||
return sPrefLayersEnableTiles;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::BufferRotationEnabled()
|
||||
{
|
||||
|
@ -507,6 +507,7 @@ public:
|
||||
static int GetPrefLayoutFrameRate();
|
||||
static bool GetPrefLayersDump();
|
||||
static bool GetPrefLayersScrollGraph();
|
||||
static bool GetPrefLayersEnableTiles();
|
||||
|
||||
static bool OffMainThreadCompositionRequired();
|
||||
|
||||
|
@ -5,6 +5,9 @@
|
||||
|
||||
#include "nsUCConstructors.h"
|
||||
#include "nsCP866ToUnicode.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Global functions and data [declaration]
|
||||
@ -17,6 +20,7 @@ nsCP866ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
#include "cp866.ut"
|
||||
};
|
||||
|
||||
Telemetry::Accumulate(Telemetry::DECODER_INSTANTIATED_IBM866, true);
|
||||
return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
|
||||
aOuter, aIID, aResult);
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
|
||||
#include "nsUCConstructors.h"
|
||||
#include "nsISO88595ToUnicode.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Global functions and data [declaration]
|
||||
@ -17,6 +20,7 @@ nsISO88595ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
#include "8859-5.ut"
|
||||
};
|
||||
|
||||
Telemetry::Accumulate(Telemetry::DECODER_INSTANTIATED_ISO_8859_5, true);
|
||||
return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
|
||||
aOuter, aIID, aResult);
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
|
||||
#include "nsUCConstructors.h"
|
||||
#include "nsKOI8RToUnicode.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Global functions and data [declaration]
|
||||
@ -17,6 +20,7 @@ nsKOI8RToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
#include "koi8r.ut"
|
||||
};
|
||||
|
||||
Telemetry::Accumulate(Telemetry::DECODER_INSTANTIATED_KOI8R, true);
|
||||
return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
|
||||
aOuter, aIID, aResult);
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
|
||||
#include "nsUCConstructors.h"
|
||||
#include "nsKOI8UToUnicode.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Global functions and data [declaration]
|
||||
@ -17,6 +20,7 @@ nsKOI8UToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
#include "koi8u.ut"
|
||||
};
|
||||
|
||||
Telemetry::Accumulate(Telemetry::DECODER_INSTANTIATED_KOI8U, true);
|
||||
return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
|
||||
aOuter, aIID, aResult);
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
|
||||
#include "nsUCConstructors.h"
|
||||
#include "nsMacCyrillicToUnicode.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Global functions and data [declaration]
|
||||
@ -17,6 +20,7 @@ nsMacCyrillicToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
#include "maccyril.ut"
|
||||
};
|
||||
|
||||
Telemetry::Accumulate(Telemetry::DECODER_INSTANTIATED_MACCYRILLIC, true);
|
||||
return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
|
||||
aOuter, aIID, aResult);
|
||||
}
|
||||
|
@ -1803,6 +1803,9 @@ TypedDatum::obj_trace(JSTracer *trace, JSObject *object)
|
||||
TypeRepresentation *repr = typeRepresentation(*GetType(*object));
|
||||
if (repr->opaque()) {
|
||||
uint8_t *mem = TypedMem(*object);
|
||||
if (!mem)
|
||||
return; // unattached handle or partially constructed
|
||||
|
||||
switch (repr->kind()) {
|
||||
case TypeRepresentation::Scalar:
|
||||
case TypeRepresentation::Reference:
|
||||
|
@ -162,6 +162,42 @@ function IsObject(v) {
|
||||
(typeof v === "undefined" && v !== undefined);
|
||||
}
|
||||
|
||||
|
||||
/********** Testing code **********/
|
||||
|
||||
// This code enables testing of the custom allow-nothing wrappers used for
|
||||
// objects and functions crossing the self-hosting compartment boundaries.
|
||||
// Functions marked as wrappable won't be cloned into content compartments;
|
||||
// they're called inside the self-hosting compartment itself. Calling is the
|
||||
// only valid operation on them. In turn, the only valid way they can use their
|
||||
// object arguments is as keys in maps. Doing anything else with them throws.
|
||||
var wrappersTestMap = new WeakMap();
|
||||
function testWrappersAllowUseAsKey(o) {
|
||||
wrappersTestMap.set(o, o);
|
||||
var mappedO = wrappersTestMap.get(o);
|
||||
wrappersTestMap.clear();
|
||||
return mappedO;
|
||||
}
|
||||
function testWrappersForbidAccess(o, operation) {
|
||||
try {
|
||||
switch (operation) {
|
||||
case 'get': var result = o.prop; break;
|
||||
case 'set': o.prop2 = 'value'; break;
|
||||
case 'call': o(); break;
|
||||
case '__proto__':
|
||||
Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set.call(o, new Object());
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
// Got the expected exception.
|
||||
return /denied/.test(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MakeWrappable(testWrappersAllowUseAsKey);
|
||||
MakeWrappable(testWrappersForbidAccess);
|
||||
|
||||
#ifdef ENABLE_PARALLEL_JS
|
||||
|
||||
/**
|
||||
|
@ -96,8 +96,25 @@
|
||||
*
|
||||
* POST-BARRIER
|
||||
*
|
||||
* These are not yet implemented. Once we get generational GC, they will allow
|
||||
* us to keep track of pointers from non-nursery space into the nursery.
|
||||
* For generational GC, we want to be able to quickly collect the nursery in a
|
||||
* minor collection. Part of the way this is achieved is to only mark the
|
||||
* nursery itself; tenured things, which may form the majority of the heap, are
|
||||
* not traced through or marked. This leads to the problem of what to do about
|
||||
* tenured objects that have pointers into the nursery: if such things are not
|
||||
* marked, they may be discarded while there are still live objects which
|
||||
* reference them. The solution is to maintain information about these pointers,
|
||||
* and mark their targets when we start a minor collection.
|
||||
*
|
||||
* The pointers can be thoughs of as edges in object graph, and the set of edges
|
||||
* from the tenured generation into the nursery is know as the remembered set.
|
||||
* Post barriers are used to track this remembered set.
|
||||
*
|
||||
* Whenever a slot which could contain such a pointer is written, we use a write
|
||||
* barrier to check if the edge created is in the remembered set, and if so we
|
||||
* insert it into the store buffer, which is the collector's representation of
|
||||
* the remembered set. This means than when we come to do a minor collection we
|
||||
* can examine the contents of the store buffer and mark any edge targets that
|
||||
* are in the nursery.
|
||||
*
|
||||
* IMPLEMENTATION DETAILS
|
||||
*
|
||||
@ -116,6 +133,21 @@
|
||||
* the "obj->field.init(value)" method instead of "obj->field = value". We use
|
||||
* the init naming idiom in many places to signify that a field is being
|
||||
* assigned for the first time.
|
||||
*
|
||||
* For each of pointers, Values and jsids this file implements four classes,
|
||||
* illustrated here for the pointer (Ptr) classes:
|
||||
*
|
||||
* BarrieredPtr abstract base class which provides common operations
|
||||
* | | |
|
||||
* | | EncapsulatedPtr provides pre-barriers only
|
||||
* | |
|
||||
* | HeapPtr provides pre- and post-barriers
|
||||
* |
|
||||
* RelocatablePtr provides pre- and post-barriers and is relocatable
|
||||
*
|
||||
* These classes are designed to be used by the internals of the JS engine.
|
||||
* Barriers designed to be used externally are provided in
|
||||
* js/public/RootingAPI.h.
|
||||
*/
|
||||
|
||||
namespace js {
|
||||
|
13
js/src/jit-test/tests/TypedObject/gcunattachedhandle.js
Normal file
13
js/src/jit-test/tests/TypedObject/gcunattachedhandle.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Test that we can trace a unattached handle.
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
if (!this.hasOwnProperty("TypedObject"))
|
||||
quit();
|
||||
|
||||
var Object = TypedObject.Object;
|
||||
var handle0 = Object.handle();
|
||||
gc();
|
12
js/src/jit-test/tests/collections/WeakMap-moving-gc.js
Normal file
12
js/src/jit-test/tests/collections/WeakMap-moving-gc.js
Normal file
@ -0,0 +1,12 @@
|
||||
var wm = new WeakMap;
|
||||
var A = [];
|
||||
for (var i = 0; i < 1024; ++i) {
|
||||
var key = {i:i};
|
||||
wm.set(key, i);
|
||||
A.push(key);
|
||||
}
|
||||
gc();
|
||||
for (var i in A) {
|
||||
var key = A[i];
|
||||
assertEq(wm.has(key), true);
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
if (!this.hasOwnProperty("TypedObject"))
|
||||
quit();
|
||||
|
||||
var ArrayType = TypedObject.ArrayType;
|
||||
var StructType = TypedObject.StructType;
|
||||
var uint8 = TypedObject.uint8;
|
||||
|
36
js/src/jit-test/tests/self-hosting/makewrappable.js
Normal file
36
js/src/jit-test/tests/self-hosting/makewrappable.js
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
var testObject = {prop:'value'};
|
||||
|
||||
var testWrappersAllowUseAsKey = getSelfHostedValue('testWrappersAllowUseAsKey');
|
||||
assertEq(typeof testWrappersAllowUseAsKey, 'function');
|
||||
assertEq(testWrappersAllowUseAsKey(testObject), testObject);
|
||||
|
||||
var testWrappersForbidAccess = getSelfHostedValue('testWrappersForbidAccess');
|
||||
assertEq(typeof testWrappersForbidAccess, 'function');
|
||||
assertEq(testWrappersForbidAccess(testObject, 'get'), true);
|
||||
assertEq(testWrappersForbidAccess(testObject, 'set'), true);
|
||||
assertEq(testWrappersForbidAccess(function(){}, 'call'), true);
|
||||
assertEq(testWrappersForbidAccess(testObject, '__proto__'), true);
|
||||
|
||||
var wrappedFunction = testWrappersForbidAccess;
|
||||
function testWrappersAllowCallsOnly(fun, operation) {
|
||||
try {
|
||||
switch (operation) {
|
||||
case 'get': var result = fun.prop; break;
|
||||
case 'set': fun.prop2 = 'value'; break;
|
||||
case 'call': o(); break;
|
||||
case '__proto__':
|
||||
Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set.call(fun, new Object());
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
// Got the expected exception.
|
||||
return /denied/.test(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
assertEq(testWrappersAllowCallsOnly(wrappedFunction, 'get'), true);
|
||||
assertEq(testWrappersAllowCallsOnly(wrappedFunction, 'set'), true);
|
||||
assertEq(testWrappersAllowCallsOnly(wrappedFunction, '__proto__'), true);
|
||||
assertEq(testWrappersAllowCallsOnly(wrappedFunction, 'call'), false);
|
@ -5838,7 +5838,7 @@ StackDecrementForCall(MacroAssembler &masm, const VectorT &argTypes, unsigned ex
|
||||
return AlignBytes(alreadyPushed + extraBytes + argBytes, StackAlignment) - alreadyPushed;
|
||||
}
|
||||
|
||||
static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * STACK_SLOT_SIZE +
|
||||
static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * sizeof(intptr_t) +
|
||||
NonVolatileRegs.fpus().size() * sizeof(double);
|
||||
|
||||
static bool
|
||||
@ -5935,7 +5935,7 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
|
||||
masm.storeValue(JSVAL_TYPE_INT32, ReturnReg, Address(argv, 0));
|
||||
break;
|
||||
case RetType::Float:
|
||||
masm.convertFloatToDouble(ReturnFloatReg, ReturnFloatReg);
|
||||
masm.convertFloat32ToDouble(ReturnFloatReg, ReturnFloatReg);
|
||||
// Fall through as ReturnFloatReg now contains a Double
|
||||
case RetType::Double:
|
||||
masm.canonicalizeDouble(ReturnFloatReg);
|
||||
|
@ -161,7 +161,7 @@ BacktrackingAllocator::tryGroupRegisters(uint32_t vreg0, uint32_t vreg1)
|
||||
// already grouped with reg0 or reg1.
|
||||
BacktrackingVirtualRegister *reg0 = &vregs[vreg0], *reg1 = &vregs[vreg1];
|
||||
|
||||
if (reg0->isDouble() != reg1->isDouble())
|
||||
if (reg0->isFloatReg() != reg1->isFloatReg())
|
||||
return true;
|
||||
|
||||
VirtualRegisterGroup *group0 = reg0->group(), *group1 = reg1->group();
|
||||
@ -636,7 +636,7 @@ BacktrackingAllocator::tryAllocateGroupRegister(PhysicalRegister &r, VirtualRegi
|
||||
if (!r.allocatable)
|
||||
return true;
|
||||
|
||||
if (r.reg.isFloat() != vregs[group->registers[0]].isDouble())
|
||||
if (r.reg.isFloat() != vregs[group->registers[0]].isFloatReg())
|
||||
return true;
|
||||
|
||||
bool allocatable = true;
|
||||
@ -686,7 +686,7 @@ BacktrackingAllocator::tryAllocateRegister(PhysicalRegister &r, LiveInterval *in
|
||||
return true;
|
||||
|
||||
BacktrackingVirtualRegister *reg = &vregs[interval->vreg()];
|
||||
if (reg->isDouble() != r.reg.isFloat())
|
||||
if (reg->isFloatReg() != r.reg.isFloat())
|
||||
return true;
|
||||
|
||||
JS_ASSERT_IF(interval->requirement()->kind() == Requirement::FIXED,
|
||||
@ -862,14 +862,10 @@ BacktrackingAllocator::spill(LiveInterval *interval)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t stackSlot;
|
||||
if (reg->isDouble())
|
||||
stackSlot = stackSlotAllocator.allocateDoubleSlot();
|
||||
else
|
||||
stackSlot = stackSlotAllocator.allocateSlot();
|
||||
uint32_t stackSlot = stackSlotAllocator.allocateSlot(reg->type());
|
||||
JS_ASSERT(stackSlot <= stackSlotAllocator.stackHeight());
|
||||
|
||||
LStackSlot alloc(stackSlot, reg->isDouble());
|
||||
LStackSlot alloc(stackSlot);
|
||||
interval->setAllocation(alloc);
|
||||
|
||||
IonSpew(IonSpew_RegAlloc, " Allocating spill location %s", alloc.toString());
|
||||
@ -1130,6 +1126,7 @@ BacktrackingAllocator::populateSafepoints()
|
||||
DebugOnly<LDefinition*> def = reg->def();
|
||||
JS_ASSERT_IF(def->policy() == LDefinition::MUST_REUSE_INPUT,
|
||||
def->type() == LDefinition::GENERAL ||
|
||||
def->type() == LDefinition::INT32 ||
|
||||
def->type() == LDefinition::FLOAT32 ||
|
||||
def->type() == LDefinition::DOUBLE);
|
||||
continue;
|
||||
|
@ -2851,9 +2851,9 @@ ICBinaryArith_Double::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
break;
|
||||
case JSOP_MOD:
|
||||
masm.setupUnalignedABICall(2, R0.scratchReg());
|
||||
masm.passABIArg(FloatReg0);
|
||||
masm.passABIArg(FloatReg1);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, NumberMod), MacroAssembler::DOUBLE);
|
||||
masm.passABIArg(FloatReg0, MoveOp::DOUBLE);
|
||||
masm.passABIArg(FloatReg1, MoveOp::DOUBLE);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, NumberMod), MoveOp::DOUBLE);
|
||||
JS_ASSERT(ReturnFloatReg == FloatReg0);
|
||||
break;
|
||||
default:
|
||||
@ -2978,7 +2978,7 @@ ICBinaryArith_DoubleWithInt32::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
masm.bind(&truncateABICall);
|
||||
masm.push(intReg);
|
||||
masm.setupUnalignedABICall(1, scratchReg);
|
||||
masm.passABIArg(FloatReg0);
|
||||
masm.passABIArg(FloatReg0, MoveOp::DOUBLE);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, js::ToInt32));
|
||||
masm.storeCallResult(scratchReg);
|
||||
masm.pop(intReg);
|
||||
@ -3127,7 +3127,7 @@ ICUnaryArith_Double::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
|
||||
masm.bind(&truncateABICall);
|
||||
masm.setupUnalignedABICall(1, scratchReg);
|
||||
masm.passABIArg(FloatReg0);
|
||||
masm.passABIArg(FloatReg0, MoveOp::DOUBLE);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, js::ToInt32));
|
||||
masm.storeCallResult(scratchReg);
|
||||
|
||||
@ -5490,7 +5490,7 @@ ICSetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
if (LIRGenerator::allowFloat32Optimizations() &&
|
||||
type_ == ScalarTypeRepresentation::TYPE_FLOAT32)
|
||||
{
|
||||
masm.convertDoubleToFloat(FloatReg0, ScratchFloatReg);
|
||||
masm.convertDoubleToFloat32(FloatReg0, ScratchFloatReg);
|
||||
masm.storeToTypedFloatArray(type_, ScratchFloatReg, dest);
|
||||
} else {
|
||||
masm.storeToTypedFloatArray(type_, FloatReg0, dest);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mnde: 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
|
||||
@ -322,7 +322,7 @@ CodeGenerator::visitValueToFloat32(LValueToFloat32 *lir)
|
||||
|
||||
masm.bind(&isDouble);
|
||||
masm.unboxDouble(operand, output);
|
||||
masm.convertDoubleToFloat(output, output);
|
||||
masm.convertDoubleToFloat32(output, output);
|
||||
masm.bind(&done);
|
||||
|
||||
return true;
|
||||
@ -338,14 +338,14 @@ CodeGenerator::visitInt32ToDouble(LInt32ToDouble *lir)
|
||||
bool
|
||||
CodeGenerator::visitFloat32ToDouble(LFloat32ToDouble *lir)
|
||||
{
|
||||
masm.convertFloatToDouble(ToFloatRegister(lir->input()), ToFloatRegister(lir->output()));
|
||||
masm.convertFloat32ToDouble(ToFloatRegister(lir->input()), ToFloatRegister(lir->output()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitDoubleToFloat32(LDoubleToFloat32 *lir)
|
||||
{
|
||||
masm.convertDoubleToFloat(ToFloatRegister(lir->input()), ToFloatRegister(lir->output()));
|
||||
masm.convertDoubleToFloat32(ToFloatRegister(lir->input()), ToFloatRegister(lir->output()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -981,7 +981,7 @@ CodeGenerator::visitTableSwitch(LTableSwitch *ins)
|
||||
Label *defaultcase = mir->getDefault()->lir()->label();
|
||||
const LAllocation *temp;
|
||||
|
||||
if (ins->index()->isDouble()) {
|
||||
if (mir->getOperand(0)->type() != MIRType_Int32) {
|
||||
temp = ins->tempInt()->output();
|
||||
|
||||
// The input is a double, so try and convert it to an integer.
|
||||
@ -1188,15 +1188,30 @@ CodeGenerator::visitMoveGroup(LMoveGroup *group)
|
||||
|
||||
const LAllocation *from = move.from();
|
||||
const LAllocation *to = move.to();
|
||||
LDefinition::Type type = move.type();
|
||||
|
||||
// No bogus moves.
|
||||
JS_ASSERT(*from != *to);
|
||||
JS_ASSERT(!from->isConstant());
|
||||
JS_ASSERT(from->isDouble() == to->isDouble());
|
||||
|
||||
MoveOp::Kind kind = from->isDouble() ? MoveOp::DOUBLE : MoveOp::GENERAL;
|
||||
MoveOp::Type moveType;
|
||||
switch (type) {
|
||||
case LDefinition::OBJECT:
|
||||
case LDefinition::SLOTS:
|
||||
#ifdef JS_NUNBOX32
|
||||
case LDefinition::TYPE:
|
||||
case LDefinition::PAYLOAD:
|
||||
#else
|
||||
case LDefinition::BOX:
|
||||
#endif
|
||||
case LDefinition::GENERAL: moveType = MoveOp::GENERAL; break;
|
||||
case LDefinition::INT32: moveType = MoveOp::INT32; break;
|
||||
case LDefinition::FLOAT32: moveType = MoveOp::FLOAT32; break;
|
||||
case LDefinition::DOUBLE: moveType = MoveOp::DOUBLE; break;
|
||||
default: MOZ_ASSUME_UNREACHABLE("Unexpected move type");
|
||||
}
|
||||
|
||||
if (!resolver.addMove(toMoveOperand(from), toMoveOperand(to), kind))
|
||||
if (!resolver.addMove(toMoveOperand(from), toMoveOperand(to), moveType))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3205,9 +3220,9 @@ bool CodeGenerator::visitAtan2D(LAtan2D *lir)
|
||||
FloatRegister x = ToFloatRegister(lir->x());
|
||||
|
||||
masm.setupUnalignedABICall(2, temp);
|
||||
masm.passABIArg(y);
|
||||
masm.passABIArg(x);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ecmaAtan2), MacroAssembler::DOUBLE);
|
||||
masm.passABIArg(y, MoveOp::DOUBLE);
|
||||
masm.passABIArg(x, MoveOp::DOUBLE);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ecmaAtan2), MoveOp::DOUBLE);
|
||||
|
||||
JS_ASSERT(ToFloatRegister(lir->output()) == ReturnFloatReg);
|
||||
return true;
|
||||
@ -3220,9 +3235,9 @@ bool CodeGenerator::visitHypot(LHypot *lir)
|
||||
FloatRegister y = ToFloatRegister(lir->y());
|
||||
|
||||
masm.setupUnalignedABICall(2, temp);
|
||||
masm.passABIArg(x);
|
||||
masm.passABIArg(y);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ecmaHypot), MacroAssembler::DOUBLE);
|
||||
masm.passABIArg(x, MoveOp::DOUBLE);
|
||||
masm.passABIArg(y, MoveOp::DOUBLE);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ecmaHypot), MoveOp::DOUBLE);
|
||||
|
||||
JS_ASSERT(ToFloatRegister(lir->output()) == ReturnFloatReg);
|
||||
return true;
|
||||
@ -3961,10 +3976,10 @@ CodeGenerator::visitPowI(LPowI *ins)
|
||||
// its scratch register. We can therefore save an input register by
|
||||
// reusing the scratch register to pass constants to callWithABI.
|
||||
masm.setupUnalignedABICall(2, temp);
|
||||
masm.passABIArg(value);
|
||||
masm.passABIArg(value, MoveOp::DOUBLE);
|
||||
masm.passABIArg(power);
|
||||
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, js::powi), MacroAssembler::DOUBLE);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, js::powi), MoveOp::DOUBLE);
|
||||
JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg);
|
||||
|
||||
return true;
|
||||
@ -3978,9 +3993,9 @@ CodeGenerator::visitPowD(LPowD *ins)
|
||||
Register temp = ToRegister(ins->temp());
|
||||
|
||||
masm.setupUnalignedABICall(2, temp);
|
||||
masm.passABIArg(value);
|
||||
masm.passABIArg(power);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ecmaPow), MacroAssembler::DOUBLE);
|
||||
masm.passABIArg(value, MoveOp::DOUBLE);
|
||||
masm.passABIArg(power, MoveOp::DOUBLE);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ecmaPow), MoveOp::DOUBLE);
|
||||
|
||||
JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg);
|
||||
return true;
|
||||
@ -3996,7 +4011,7 @@ CodeGenerator::visitRandom(LRandom *ins)
|
||||
|
||||
masm.setupUnalignedABICall(1, temp2);
|
||||
masm.passABIArg(temp);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, math_random_no_outparam), MacroAssembler::DOUBLE);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, math_random_no_outparam), MoveOp::DOUBLE);
|
||||
|
||||
JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg);
|
||||
return true;
|
||||
@ -4016,7 +4031,7 @@ CodeGenerator::visitMathFunctionD(LMathFunctionD *ins)
|
||||
masm.movePtr(ImmPtr(mathCache), temp);
|
||||
masm.passABIArg(temp);
|
||||
}
|
||||
masm.passABIArg(input);
|
||||
masm.passABIArg(input, MoveOp::DOUBLE);
|
||||
|
||||
# define MAYBE_CACHED(fcn) (mathCache ? (void*)fcn ## _impl : (void*)fcn ## _uncached)
|
||||
|
||||
@ -4097,7 +4112,7 @@ CodeGenerator::visitMathFunctionD(LMathFunctionD *ins)
|
||||
|
||||
# undef MAYBE_CACHED
|
||||
|
||||
masm.callWithABI(funptr, MacroAssembler::DOUBLE);
|
||||
masm.callWithABI(funptr, MoveOp::DOUBLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4109,7 +4124,7 @@ CodeGenerator::visitMathFunctionF(LMathFunctionF *ins)
|
||||
JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg);
|
||||
|
||||
masm.setupUnalignedABICall(1, temp);
|
||||
masm.passABIArg(input);
|
||||
masm.passABIArg(input, MoveOp::FLOAT32);
|
||||
|
||||
void *funptr = nullptr;
|
||||
switch (ins->mir()->function()) {
|
||||
@ -4126,7 +4141,7 @@ CodeGenerator::visitMathFunctionF(LMathFunctionF *ins)
|
||||
MOZ_ASSUME_UNREACHABLE("Unknown or unsupported float32 math function");
|
||||
}
|
||||
|
||||
masm.callWithABI(funptr, MacroAssembler::FLOAT);
|
||||
masm.callWithABI(funptr, MoveOp::FLOAT32);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4140,13 +4155,13 @@ CodeGenerator::visitModD(LModD *ins)
|
||||
JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg);
|
||||
|
||||
masm.setupUnalignedABICall(2, temp);
|
||||
masm.passABIArg(lhs);
|
||||
masm.passABIArg(rhs);
|
||||
masm.passABIArg(lhs, MoveOp::DOUBLE);
|
||||
masm.passABIArg(rhs, MoveOp::DOUBLE);
|
||||
|
||||
if (gen->compilingAsmJS())
|
||||
masm.callWithABI(AsmJSImm_ModD, MacroAssembler::DOUBLE);
|
||||
masm.callWithABI(AsmJSImm_ModD, MoveOp::DOUBLE);
|
||||
else
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, NumberMod), MacroAssembler::DOUBLE);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, NumberMod), MoveOp::DOUBLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6153,7 +6168,7 @@ CodeGenerator::visitUnboxFloatingPoint(LUnboxFloatingPoint *lir)
|
||||
masm.branchTestDouble(Assembler::NotEqual, box, ool->entry());
|
||||
masm.unboxDouble(box, resultReg);
|
||||
if (lir->type() == MIRType_Float32)
|
||||
masm.convertDoubleToFloat(resultReg, resultReg);
|
||||
masm.convertDoubleToFloat32(resultReg, resultReg);
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
@ -7992,9 +8007,9 @@ CodeGenerator::visitAssertRangeF(LAssertRangeF *ins)
|
||||
FloatRegister temp = ToFloatRegister(ins->temp());
|
||||
const Range *r = ins->range();
|
||||
|
||||
masm.convertFloatToDouble(input, input);
|
||||
masm.convertFloat32ToDouble(input, input);
|
||||
bool success = emitAssertRangeD(r, input, temp);
|
||||
masm.convertDoubleToFloat(input, input);
|
||||
masm.convertDoubleToFloat32(input, input);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -393,7 +393,7 @@ IonCache::attachStub(MacroAssembler &masm, StubAttacher &attacher, Handle<IonCod
|
||||
|
||||
// Replace the STUB_ADDR constant by the address of the generated stub, such
|
||||
// as it can be kept alive even if the cache is flushed (see
|
||||
// MarkIonExitFrame).
|
||||
// MarkJitExitFrame).
|
||||
attacher.patchStubCodePointer(masm, code);
|
||||
}
|
||||
|
||||
|
@ -221,8 +221,7 @@ struct IonScript
|
||||
uint32_t safepointsStart_;
|
||||
uint32_t safepointsSize_;
|
||||
|
||||
// Number of STACK_SLOT_SIZE-length slots this function reserves on the
|
||||
// stack.
|
||||
// Number of bytes this function reserves on the stack.
|
||||
uint32_t frameSlots_;
|
||||
|
||||
// Frame size is the value that can be added to the StackPointer along
|
||||
|
@ -239,7 +239,6 @@ class SnapshotIterator : public SnapshotReader
|
||||
private:
|
||||
bool hasLocation(const SnapshotReader::Location &loc);
|
||||
uintptr_t fromLocation(const SnapshotReader::Location &loc);
|
||||
static Value FromTypedPayload(JSValueType type, uintptr_t payload);
|
||||
|
||||
Value slotValue(const Slot &slot);
|
||||
bool slotReadable(const Slot &slot);
|
||||
|
@ -32,6 +32,45 @@
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// Given a slot index, returns the offset, in bytes, of that slot from an
|
||||
// IonJSFrameLayout. Slot distances are uniform across architectures, however,
|
||||
// the distance does depend on the size of the frame header.
|
||||
static inline int32_t
|
||||
OffsetOfFrameSlot(int32_t slot)
|
||||
{
|
||||
return -slot;
|
||||
}
|
||||
|
||||
static inline uintptr_t
|
||||
ReadFrameSlot(IonJSFrameLayout *fp, int32_t slot)
|
||||
{
|
||||
return *(uintptr_t *)((char *)fp + OffsetOfFrameSlot(slot));
|
||||
}
|
||||
|
||||
static inline double
|
||||
ReadFrameDoubleSlot(IonJSFrameLayout *fp, int32_t slot)
|
||||
{
|
||||
return *(double *)((char *)fp + OffsetOfFrameSlot(slot));
|
||||
}
|
||||
|
||||
static inline double
|
||||
ReadFrameFloat32Slot(IonJSFrameLayout *fp, int32_t slot)
|
||||
{
|
||||
return *(float *)((char *)fp + OffsetOfFrameSlot(slot));
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
ReadFrameInt32Slot(IonJSFrameLayout *fp, int32_t slot)
|
||||
{
|
||||
return *(int32_t *)((char *)fp + OffsetOfFrameSlot(slot));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ReadFrameBooleanSlot(IonJSFrameLayout *fp, int32_t slot)
|
||||
{
|
||||
return *(bool *)((char *)fp + OffsetOfFrameSlot(slot));
|
||||
}
|
||||
|
||||
IonFrameIterator::IonFrameIterator(JSContext *cx)
|
||||
: current_(cx->mainThread().ionTop),
|
||||
type_(IonFrame_Exit),
|
||||
@ -922,7 +961,7 @@ JitActivationIterator::jitStackRange(uintptr_t *&min, uintptr_t *&end)
|
||||
}
|
||||
|
||||
static void
|
||||
MarkIonExitFrame(JSTracer *trc, const IonFrameIterator &frame)
|
||||
MarkJitExitFrame(JSTracer *trc, const IonFrameIterator &frame)
|
||||
{
|
||||
// Ignore fake exit frames created by EnsureExitFrame.
|
||||
if (frame.isFakeExitFrame())
|
||||
@ -1077,7 +1116,7 @@ MarkJitActivation(JSTracer *trc, const JitActivationIterator &activations)
|
||||
for (IonFrameIterator frames(activations); !frames.done(); ++frames) {
|
||||
switch (frames.type()) {
|
||||
case IonFrame_Exit:
|
||||
MarkIonExitFrame(trc, frames);
|
||||
MarkJitExitFrame(trc, frames);
|
||||
break;
|
||||
case IonFrame_BaselineJS:
|
||||
frames.baselineFrame()->trace(trc);
|
||||
@ -1237,8 +1276,20 @@ SnapshotIterator::fromLocation(const SnapshotReader::Location &loc)
|
||||
return machine_.read(loc.reg());
|
||||
}
|
||||
|
||||
Value
|
||||
SnapshotIterator::FromTypedPayload(JSValueType type, uintptr_t payload)
|
||||
static Value
|
||||
FromObjectPayload(uintptr_t payload)
|
||||
{
|
||||
return ObjectValue(*reinterpret_cast<JSObject *>(payload));
|
||||
}
|
||||
|
||||
static Value
|
||||
FromStringPayload(uintptr_t payload)
|
||||
{
|
||||
return StringValue(reinterpret_cast<JSString *>(payload));
|
||||
}
|
||||
|
||||
static Value
|
||||
FromTypedPayload(JSValueType type, uintptr_t payload)
|
||||
{
|
||||
switch (type) {
|
||||
case JSVAL_TYPE_INT32:
|
||||
@ -1246,9 +1297,9 @@ SnapshotIterator::FromTypedPayload(JSValueType type, uintptr_t payload)
|
||||
case JSVAL_TYPE_BOOLEAN:
|
||||
return BooleanValue(!!payload);
|
||||
case JSVAL_TYPE_STRING:
|
||||
return StringValue(reinterpret_cast<JSString *>(payload));
|
||||
return FromStringPayload(payload);
|
||||
case JSVAL_TYPE_OBJECT:
|
||||
return ObjectValue(*reinterpret_cast<JSObject *>(payload));
|
||||
return FromObjectPayload(payload);
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("unexpected type - needs payload");
|
||||
}
|
||||
@ -1276,11 +1327,6 @@ SnapshotIterator::slotReadable(const Slot &slot)
|
||||
}
|
||||
}
|
||||
|
||||
typedef union {
|
||||
double d;
|
||||
float f;
|
||||
} PunDoubleFloat;
|
||||
|
||||
Value
|
||||
SnapshotIterator::slotValue(const Slot &slot)
|
||||
{
|
||||
@ -1290,31 +1336,38 @@ SnapshotIterator::slotValue(const Slot &slot)
|
||||
|
||||
case SnapshotReader::FLOAT32_REG:
|
||||
{
|
||||
PunDoubleFloat pdf;
|
||||
pdf.d = machine_.read(slot.floatReg());
|
||||
union {
|
||||
double d;
|
||||
float f;
|
||||
} pun;
|
||||
pun.d = machine_.read(slot.floatReg());
|
||||
// The register contains the encoding of a float32. We just read
|
||||
// the bits without making any conversion.
|
||||
float asFloat = pdf.f;
|
||||
return DoubleValue(asFloat);
|
||||
return Float32Value(pun.f);
|
||||
}
|
||||
|
||||
case SnapshotReader::FLOAT32_STACK:
|
||||
{
|
||||
PunDoubleFloat pdf;
|
||||
pdf.d = ReadFrameDoubleSlot(fp_, slot.stackSlot());
|
||||
float asFloat = pdf.f; // no conversion, see comment above.
|
||||
return DoubleValue(asFloat);
|
||||
}
|
||||
return Float32Value(ReadFrameFloat32Slot(fp_, slot.stackSlot()));
|
||||
|
||||
case SnapshotReader::TYPED_REG:
|
||||
return FromTypedPayload(slot.knownType(), machine_.read(slot.reg()));
|
||||
|
||||
case SnapshotReader::TYPED_STACK:
|
||||
{
|
||||
JSValueType type = slot.knownType();
|
||||
if (type == JSVAL_TYPE_DOUBLE)
|
||||
switch (slot.knownType()) {
|
||||
case JSVAL_TYPE_DOUBLE:
|
||||
return DoubleValue(ReadFrameDoubleSlot(fp_, slot.stackSlot()));
|
||||
return FromTypedPayload(type, ReadFrameSlot(fp_, slot.stackSlot()));
|
||||
case JSVAL_TYPE_INT32:
|
||||
return Int32Value(ReadFrameInt32Slot(fp_, slot.stackSlot()));
|
||||
case JSVAL_TYPE_BOOLEAN:
|
||||
return BooleanValue(ReadFrameBooleanSlot(fp_, slot.stackSlot()));
|
||||
case JSVAL_TYPE_STRING:
|
||||
return FromStringPayload(ReadFrameSlot(fp_, slot.stackSlot()));
|
||||
case JSVAL_TYPE_OBJECT:
|
||||
return FromObjectPayload(ReadFrameSlot(fp_, slot.stackSlot()));
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Unexpected type");
|
||||
}
|
||||
}
|
||||
|
||||
case SnapshotReader::UNTYPED:
|
||||
@ -1727,5 +1780,26 @@ IonFrameIterator::dump() const
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
IonJSFrameLayout *
|
||||
InvalidationBailoutStack::fp() const
|
||||
{
|
||||
return (IonJSFrameLayout *) (sp() + ionScript_->frameSize());
|
||||
}
|
||||
|
||||
void
|
||||
InvalidationBailoutStack::checkInvariants() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
IonJSFrameLayout *frame = fp();
|
||||
CalleeToken token = frame->calleeToken();
|
||||
JS_ASSERT(token);
|
||||
|
||||
uint8_t *rawBase = ionScript()->method()->raw();
|
||||
uint8_t *rawLimit = rawBase + ionScript()->method()->instructionsSize();
|
||||
uint8_t *osiPoint = osiPointReturnAddress();
|
||||
JS_ASSERT(rawBase <= osiPoint && osiPoint <= rawLimit);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user