Merge inbound to m-c.

This commit is contained in:
Ryan VanderMeulen 2013-12-17 15:58:24 -05:00
commit 88bb9aa85f
204 changed files with 4230 additions and 3234 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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.

View File

@ -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>

View File

@ -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);

View File

@ -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.

View File

@ -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

View File

@ -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();

View File

@ -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();
}

View 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>

View 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">

View File

@ -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);
});
}

View File

@ -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();

View File

@ -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*)

View File

@ -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);

View File

@ -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); }

View File

@ -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.
*/

View File

@ -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);
};

View File

@ -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.

View File

@ -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>.

View File

@ -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)
{

View File

@ -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);

View File

@ -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);

View File

@ -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")

View File

@ -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())

View File

@ -52,6 +52,7 @@ public:
mNumCols(0),
mCurrentRowColHint(NS_STYLE_HINT_REFLOW)
{
SetHasWeirdParserInsertionMode();
}
virtual ~HTMLFrameSetElement();

View File

@ -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;
}

View File

@ -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

View File

@ -32,6 +32,10 @@ public:
HTMLSharedElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
if (mNodeInfo->Equals(nsGkAtoms::head) ||
mNodeInfo->Equals(nsGkAtoms::html)) {
SetHasWeirdParserInsertionMode();
}
}
virtual ~HTMLSharedElement();

View File

@ -19,6 +19,7 @@ public:
HTMLTableCaptionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetHasWeirdParserInsertionMode();
}
virtual ~HTMLTableCaptionElement();

View File

@ -23,6 +23,7 @@ public:
HTMLTableCellElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetHasWeirdParserInsertionMode();
}
virtual ~HTMLTableCellElement();

View File

@ -17,6 +17,7 @@ public:
HTMLTableColElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetHasWeirdParserInsertionMode();
}
virtual ~HTMLTableColElement();

View File

@ -286,6 +286,7 @@ HTMLTableElement::HTMLTableElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo),
mTableInheritedAttributes(TABLE_ATTRS_DIRTY)
{
SetHasWeirdParserInsertionMode();
}
HTMLTableElement::~HTMLTableElement()

View File

@ -22,6 +22,7 @@ public:
HTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetHasWeirdParserInsertionMode();
}
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLTableRowElement, tr)

View File

@ -18,6 +18,7 @@ public:
HTMLTableSectionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetHasWeirdParserInsertionMode();
}
// nsISupports

View File

@ -33,6 +33,7 @@ namespace dom {
HTMLTemplateElement::HTMLTemplateElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetHasWeirdParserInsertionMode();
}
nsresult

View File

@ -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;
}

View File

@ -1,3 +1,6 @@
[DEFAULT]
support-files =
file_anchor_ping.html
[test_allowMedia.html]
[test_anchor_ping.html]

View 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>

View File

@ -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

View 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>

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -680,6 +680,7 @@ protected:
void SetTitlebarColor(nscolor aColor, bool aActive);
void SetDrawsInTitlebar(bool aState);
void SetDrawsTitle(bool aState);
void RemoveBroadcaster(const nsAString & broadcasterId);

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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')

View File

@ -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.

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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)

View File

@ -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
}

View File

@ -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]

View File

@ -22,7 +22,6 @@ XPIDL_SOURCES += [
'nsIDOMHistory.idl',
'nsIDOMJSWindow.idl',
'nsIDOMLocation.idl',
'nsIDOMMediaQueryList.idl',
'nsIDOMModalContentWindow.idl',
'nsIDOMNavigator.idl',
'nsIDOMPkcs11.idl',

View File

@ -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);
};

View File

@ -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;

View File

@ -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.

View File

@ -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;

View 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);
};

View File

@ -274,6 +274,7 @@ WEBIDL_FILES = [
'Screen.webidl',
'ScriptProcessorNode.webidl',
'ScrollAreaEvent.webidl',
'Selection.webidl',
'SettingsManager.webidl',
'ShadowRoot.webidl',
'SharedWorker.webidl',

View File

@ -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;
}

View File

@ -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

View File

@ -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));

View File

@ -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);
}

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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);

View File

@ -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());
}
}

View File

@ -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()
{

View File

@ -507,6 +507,7 @@ public:
static int GetPrefLayoutFrameRate();
static bool GetPrefLayersDump();
static bool GetPrefLayersScrollGraph();
static bool GetPrefLayersEnableTiles();
static bool OffMainThreadCompositionRequired();

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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:

View File

@ -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
/**

View File

@ -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 {

View 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();

View 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);
}

View File

@ -1,3 +1,6 @@
if (!this.hasOwnProperty("TypedObject"))
quit();
var ArrayType = TypedObject.ArrayType;
var StructType = TypedObject.StructType;
var uint8 = TypedObject.uint8;

View 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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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