Merge mozilla-central and inbound

This commit is contained in:
Ed Morley 2013-11-20 12:44:07 +00:00
commit 6c3a904be0
115 changed files with 2011 additions and 960 deletions

View File

@ -0,0 +1,159 @@
# vim: set ts=8 sts=4 et sw=4 tw=79:
# 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/.
#----------------------------------------------------------------------------
# All heap allocations in SpiderMonkey must go through js_malloc, js_calloc,
# js_realloc, and js_free. This is so that any embedder who uses a custom
# allocator (by defining JS_USE_CUSTOM_ALLOCATOR) will see all heap allocation
# go through that custom allocator.
#
# Therefore, the presence of any calls to "vanilla" allocation/free functions
# (e.g. malloc(), free()) is a bug.
#
# This script checks for the presence of such disallowed vanilla
# allocation/free function in SpiderMonkey when it's built as a library. It
# relies on |nm| from the GNU binutils, and so only works on Linux, but one
# platform is good enough to catch almost all violations.
#
# This checking is only 100% reliable in a JS_USE_CUSTOM_ALLOCATOR build in
# which the default definitions of js_malloc et al (in Utility.h) -- which call
# malloc et al -- are replaced with empty definitions. This is because the
# presence and possible inlining of the default js_malloc et al can cause
# malloc/calloc/realloc/free calls show up in unpredictable places.
#
# Unfortunately, that configuration cannot be tested on Mozilla's standard
# testing infrastructure. Instead, by default this script only tests that none
# of the other vanilla allocation/free functions (operator new, memalign, etc)
# are present. If given the --aggressive flag, it will also check for
# malloc/calloc/realloc/free.
#
# Note: We don't check for |operator delete| and |operator delete[]|. These
# can be present somehow due to virtual destructors, but this is not too
# because vanilla delete/delete[] calls don't make sense without corresponding
# vanilla new/new[] calls, and any explicit calls will be caught by Valgrind's
# mismatched alloc/free checking.
#----------------------------------------------------------------------------
from __future__ import print_function
import argparse
import re
import subprocess
import sys
# The obvious way to implement this script is to search for occurrences of
# malloc et al, succeed if none are found, and fail is some are found.
# However, "none are found" does not necessarily mean "none are present" --
# this script could be buggy. (Or the output format of |nm| might change in
# the future.)
#
# So jsutil.cpp deliberately contains a (never-called) function that contains a
# single use of all the vanilla allocation/free functions. And this script
# fails if it (a) finds uses of those functions in files other than jsutil.cpp,
# *or* (b) fails to find them in jsutil.cpp.
# Tracks overall success of the test.
has_failed = False
def fail(msg):
print('TEST-UNEXPECTED-FAIL | check_vanilla_allocations.py |', msg)
global has_failed
has_failed = True
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--aggressive', action='store_true',
help='also check for malloc, calloc, realloc and free')
parser.add_argument('file', type=str,
help='name of the file to check')
args = parser.parse_args()
# Run |nm|. Options:
# -u: show only undefined symbols
# -C: demangle symbol names
# -l: show a filename and line number for each undefined symbol
cmd = ['nm', '-u', '-C', '-l', args.file]
lines = subprocess.check_output(cmd, universal_newlines=True,
stderr=subprocess.PIPE).split('\n')
# alloc_fns contains all the vanilla allocation/free functions that we look
# for. Regexp chars are escaped appropriately.
alloc_fns = [
# Matches |operator new(unsigned T)|, where |T| is |int| or |long|.
r'operator new\(unsigned',
# Matches |operator new[](unsigned T)|, where |T| is |int| or |long|.
r'operator new\[\]\(unsigned',
r'memalign',
# These two aren't available on all Linux configurations.
#r'posix_memalign',
#r'aligned_alloc',
r'valloc',
r'strdup'
]
if args.aggressive:
alloc_fns += [
r'malloc',
r'calloc',
r'realloc',
r'free'
]
# This is like alloc_fns, but regexp chars are not escaped.
alloc_fns_unescaped = [fn.translate(None, r'\\') for fn in alloc_fns]
# This regexp matches the relevant lines in the output of |nm|, which look
# like the following.
#
# U malloc /path/to/objdir/dist/include/js/Utility.h:142
#
alloc_fns_re = r'U (' + r'|'.join(alloc_fns) + r').*\/([\w\.]+):(\d+)$'
# This tracks which allocation/free functions have been seen in jsutil.cpp.
jsutil_cpp = set([])
for line in lines:
m = re.search(alloc_fns_re, line)
if m is None:
continue
fn = m.group(1)
filename = m.group(2)
linenum = m.group(3)
if filename == 'jsutil.cpp':
jsutil_cpp.add(fn)
else:
# An allocation is present in a non-special file. Fail!
fail("'" + fn + "' present at " + filename + ':' + linenum)
# Check that all functions we expect are used in jsutil.cpp. (This will
# fail if the function-detection code breaks at any point.)
for fn in alloc_fns_unescaped:
if fn not in jsutil_cpp:
fail("'" + fn + "' isn't used as expected in jsutil.cpp")
else:
jsutil_cpp.remove(fn)
# This should never happen, but check just in case.
if jsutil_cpp:
fail('unexpected allocation fns used in jsutil.cpp: ' +
', '.join(jsutil_cpp))
if has_failed:
sys.exit(1)
print('TEST-PASS | check_vanilla_allocations.py | ok')
sys.exit(0)
if __name__ == '__main__':
main()

View File

@ -1,80 +0,0 @@
# /bin/bash
#----------------------------------------------------------------------------
# We must avoid using the vanilla new/new[] operators (and consequently, the
# vanilla delete/delete[] operators) in SpiderMonkey, see bug 624878 for why.
#
# This script:
# - Detects if any of the vanilla new/new[] operators are used in a file.
# Its exit code is 1 if it found some, and 0 if it didn't.
# - Doesn't detect delete/delete[] because it appears they can be present
# somehow due to virtual destructors, but this is ok because vanilla
# delete/delete[] calls don't make sense without corresponding new/new[]
# calls, and any explicit calls will be caught by Valgrind's mismatched
# alloc/free checking.
# - Doesn't detect the 'nothrow' variants, which are ok but probably still
# best avoided.
# - Is designed to only run on Linux (though it may also work on Mac); one
# platform will be enough to catch any violations.
#
# If this script fails:
# - You need to find the uses of vanilla new/delete and replace them with
# {js::OffTheBooks,JSContext,JSRuntime}::{new_,/array_new}.
# - Run this script on each of the .o files, that should narrow it down.
# - After that, one way to find them is to run 'objdump -r -C' on the
# relevant .o files. For example, you might search for 'operator new' and
# find a record like this:
#
# RELOCATION RECORDS FOR [.text._ZN3JSC14ExecutablePool6createEj]:
# OFFSET TYPE VALUE
# 00000009 R_386_PC32 __i686.get_pc_thunk.bx
# 0000000f R_386_GOTPC _GLOBAL_OFFSET_TABLE_
# 0000001b R_386_PLT32 operator new(unsigned int)
# 0000002e R_386_PC32 JSC::ExecutablePool::ExecutablePool(unsigned int)
# 0000004a R_386_PC32 JSC::ExecutablePool::~ExecutablePool()
# 00000052 R_386_PLT32 operator delete(void*)
#
# This says that vanilla 'new' and 'delete' are both used in
# JSC::ExecutablePool::create(unsigned int). This doesn't always work,
# though. (Nb: use 'c++filt' to demangle names like
# _ZN3JSC14ExecutablePool6createEj.)
#
# If that doesn't work, use grep.
#----------------------------------------------------------------------------
if [ -z $1 ] ; then
echo "usage: find_vanilla_new_calls <file>"
exit 1
fi
file=$1
if [ ! -f $file ] ; then
echo "TEST-UNEXPECTED-FAIL | find_vanilla_new_calls | file '$file' not found"
exit 1
fi
tmpfile1=`mktemp`
tmpfile2=`mktemp`
nm -C $file > $tmpfile1
# Need to double-escape '[' and ']' to stop grep from interpreting them
# specially.
grep '^operator new(unsigned int)' $tmpfile1 >> $tmpfile2
grep '^operator new(unsigned long)' $tmpfile1 >> $tmpfile2
grep '^operator new\\[\\](unsigned int)' $tmpfile1 >> $tmpfile2
grep '^operator new\\[\\](unsigned long)' $tmpfile1 >> $tmpfile2
rm -f $tmpfile1
if [ -s $tmpfile2 ] ; then
echo "TEST-UNEXPECTED-FAIL | find_vanilla_new_calls | found calls are listed below"
cat $tmpfile2
echo
rm -f $tmpfile2
exit 1
fi
echo "TEST-PASS | find_vanilla_new_calls | ok"
echo
exit 0

View File

@ -1886,6 +1886,15 @@ public:
*/
static bool IsSubDocumentTabbable(nsIContent* aContent);
/**
* Returns if aNode ignores user focus.
*
* @param aNode node to test
*
* @return Whether the node ignores user focus.
*/
static bool IsUserFocusIgnored(nsINode* aNode);
/**
* Flushes the layout tree (recursively)
*

View File

@ -34,8 +34,8 @@ enum nsLinkState {
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
{ 0x976f4cd1, 0xbdfc, 0x4a1e, \
{ 0x82, 0x46, 0x1c, 0x13, 0x9c, 0xd3, 0x73, 0x7f } }
{ 0x34117ca3, 0x45d0, 0x479e, \
{ 0x91, 0x30, 0x54, 0x49, 0xa9, 0x5f, 0x25, 0x99 } }
/**
* A node of content in a document's content model. This interface
@ -557,12 +557,8 @@ public:
* > 0 can be tabbed to in the order specified by this value
* @return whether the content is focusable via mouse, kbd or script.
*/
virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false)
{
if (aTabIndex)
*aTabIndex = -1; // Default, not tabbable
return false;
}
bool IsFocusable(int32_t* aTabIndex = nullptr, bool aWithMouse = false);
virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse);
/**
* The method focuses (or activates) element that accesskey is bound to. It is

View File

@ -838,6 +838,33 @@ nsIContent::AttrValueIs(int32_t aNameSpaceID,
AsElement()->AttrValueIs(aNameSpaceID, aName, aValue, aCaseSensitive);
}
bool
nsIContent::IsFocusable(int32_t* aTabIndex, bool aWithMouse)
{
bool focusable = IsFocusableInternal(aTabIndex, aWithMouse);
// Ensure that the return value and aTabIndex are consistent in the case
// we're in userfocusignored context.
if (focusable || (aTabIndex && *aTabIndex != -1)) {
if (nsContentUtils::IsUserFocusIgnored(this)) {
if (aTabIndex) {
*aTabIndex = -1;
}
return false;
}
return focusable;
}
return false;
}
bool
nsIContent::IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse)
{
if (aTabIndex) {
*aTabIndex = -1; // Default, not tabbable
}
return false;
}
const nsAttrValue*
FragmentOrElement::DoGetClasses() const
{

View File

@ -74,6 +74,7 @@
#include "nsEventStateManager.h"
#include "nsFocusManager.h"
#include "nsGenericHTMLElement.h"
#include "nsGenericHTMLFrameElement.h"
#include "nsGkAtoms.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsHtml5Module.h"
@ -5898,6 +5899,30 @@ nsContentUtils::IsSubDocumentTabbable(nsIContent* aContent)
return !zombieViewer;
}
bool
nsContentUtils::IsUserFocusIgnored(nsINode* aNode)
{
if (!nsGenericHTMLFrameElement::BrowserFramesEnabled()) {
return false;
}
// Check if our mozbrowser iframe ancestors has ignoreuserfocus attribute.
while (aNode) {
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(aNode);
if (browserFrame &&
aNode->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::ignoreuserfocus) &&
browserFrame->GetReallyIsBrowserOrApp()) {
return true;
}
nsPIDOMWindow* win = aNode->OwnerDoc()->GetWindow();
if (win) {
aNode = win->GetFrameElementInternal();
}
}
return false;
}
void
nsContentUtils::FlushLayoutForTree(nsIDOMWindow* aWindow)
{

View File

@ -433,6 +433,7 @@ GK_ATOM(_if, "if")
GK_ATOM(iframe, "iframe")
GK_ATOM(ignorecase, "ignorecase")
GK_ATOM(ignorekeys, "ignorekeys")
GK_ATOM(ignoreuserfocus, "ignoreuserfocus")
GK_ATOM(ilayer, "ilayer")
GK_ATOM(image, "image")
GK_ATOM(imageClickedPoint, "image-clicked-point")

View File

@ -3221,6 +3221,10 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
}
}
if (!suppressBlur) {
suppressBlur = nsContentUtils::IsUserFocusIgnored(activeContent);
}
nsIFrame* currFrame = mCurrentTarget;
// When a root content which isn't editable but has an editable HTML

View File

@ -5,6 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIMEStateManager.h"
#include "HTMLInputElement.h"
#include "nsCOMPtr.h"
#include "nsIPresShell.h"
#include "nsISupports.h"
@ -35,6 +37,7 @@
#include "nsAsyncDOMEvent.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::widget;
// nsTextStateManager notifies widget of any text and selection changes
@ -457,8 +460,22 @@ nsIMEStateManager::SetIMEState(const IMEState &aState,
(aContent->Tag() == nsGkAtoms::input ||
aContent->Tag() == nsGkAtoms::textarea)) {
if (aContent->Tag() != nsGkAtoms::textarea) {
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
context.mHTMLInputType);
// <input type=number> has an anonymous <input type=text> descendant
// that gets focus whenever anyone tries to focus the number control. We
// need to check if aContent is one of those anonymous text controls and,
// if so, use the number control instead:
nsIContent* content = aContent;
HTMLInputElement* inputElement =
HTMLInputElement::FromContentOrNull(aContent);
if (inputElement) {
HTMLInputElement* ownerNumberControl =
inputElement->GetOwnerNumberControl();
if (ownerNumberControl) {
content = ownerNumberControl; // an <input type=number>
}
}
content->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
context.mHTMLInputType);
} else {
context.mHTMLInputType.Assign(nsGkAtoms::textarea->GetUTF16String());
}

View File

@ -2061,7 +2061,7 @@ HTMLInputElement::ApplyStep(int32_t aStep)
Decimal value = GetValueAsDecimal();
if (value.isNaN()) {
return NS_OK;
value = 0;
}
Decimal minimum = GetMinimum();
@ -2244,6 +2244,21 @@ HTMLInputElement::MozIsTextField(bool aExcludePassword)
return IsSingleLineTextControl(aExcludePassword);
}
HTMLInputElement*
HTMLInputElement::GetOwnerNumberControl()
{
if (IsInNativeAnonymousSubtree() &&
mType == NS_FORM_INPUT_TEXT &&
GetParent() && GetParent()->GetParent()) {
HTMLInputElement* grandparent =
HTMLInputElement::FromContentOrNull(GetParent()->GetParent());
if (grandparent && grandparent->mType == NS_FORM_INPUT_NUMBER) {
return grandparent;
}
}
return nullptr;
}
NS_IMETHODIMP
HTMLInputElement::MozIsTextField(bool aExcludePassword, bool* aResult)
{

View File

@ -668,6 +668,8 @@ public:
void MozSetFileNameArray(const Sequence< nsString >& aFileNames);
HTMLInputElement* GetOwnerNumberControl();
bool MozIsTextField(bool aExcludePassword);
nsIEditor* GetEditor();

View File

@ -558,7 +558,7 @@ public:
bool aNotify) MOZ_OVERRIDE;
virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
bool aNotify) MOZ_OVERRIDE;
virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false) MOZ_OVERRIDE
virtual bool IsFocusableInternal(int32_t *aTabIndex, bool aWithMouse) MOZ_OVERRIDE
{
bool isFocusable = false;
IsHTMLFocusable(aWithMouse, &isFocusable, aTabIndex);

View File

@ -323,6 +323,21 @@ nsGenericHTMLFrameElement::IsHTMLFocusable(bool aWithMouse,
return false;
}
bool
nsGenericHTMLFrameElement::BrowserFramesEnabled()
{
static bool sMozBrowserFramesEnabled = false;
static bool sBoolVarCacheInitialized = false;
if (!sBoolVarCacheInitialized) {
sBoolVarCacheInitialized = true;
Preferences::AddBoolVarCache(&sMozBrowserFramesEnabled,
"dom.mozBrowserFramesEnabled");
}
return sMozBrowserFramesEnabled;
}
/**
* Return true if this frame element really is a mozbrowser or mozapp. (It
* needs to have the right attributes, and its creator must have the right
@ -334,7 +349,7 @@ nsGenericHTMLFrameElement::GetReallyIsBrowserOrApp(bool *aOut)
*aOut = false;
// Fail if browser frames are globally disabled.
if (!Preferences::GetBool("dom.mozBrowserFramesEnabled")) {
if (!nsGenericHTMLFrameElement::BrowserFramesEnabled()) {
return NS_OK;
}

View File

@ -72,6 +72,7 @@ public:
void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aError);
static bool BrowserFramesEnabled();
protected:
// This doesn't really ensure a frame loade in all cases, only when
// it makes sense.

View File

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html>
<body>
<map name=a>
<area shape=rect coords=0,0,100,100 href=#fail>
</map>
<img usemap=#a src=image.png>
<input><iframe></iframe>
</body>
</html>

View File

@ -169,7 +169,7 @@ function checkStepDown()
[ '10', '2', '0', '4', '10', '0', false ],
[ '10', '2', '0', '4', '5', '0', false ],
// value = "" (NaN).
[ '', null, null, null, null, '', false ],
[ '', null, null, null, null, '-1', false ],
// With step = 'any'.
[ '0', 'any', null, null, 1, null, true ],
[ '0', 'ANY', null, null, 1, null, true ],
@ -304,7 +304,7 @@ function checkStepDown()
[ '1970-03-08', '3', '1970-02-01', '1970-02-07', 15, '1970-02-01', false ],
[ '1970-01-10', '3', '1970-01-01', '1970-01-06', 2, '1970-01-04', false ],
// value = "" (NaN).
[ '', null, null, null, null, '', false ],
[ '', null, null, null, null, '1969-12-31', false ],
// With step = 'any'.
[ '2012-01-01', 'any', null, null, 1, null, true ],
[ '2012-01-01', 'ANY', null, null, 1, null, true ],
@ -368,7 +368,7 @@ function checkStepDown()
[ '17:22', '180', '17:00', '17:20', 15, '17:00', false ],
[ '17:22', '180', '17:10', '17:20', 2, '17:16', false ],
// value = "" (NaN).
[ '', null, null, null, null, '', false ],
[ '', null, null, null, null, '23:59', false ],
// With step = 'any'.
[ '17:26', 'any', null, null, 1, null, true ],
[ '17:26', 'ANY', null, null, 1, null, true ],
@ -484,7 +484,7 @@ function checkStepUp()
[ '-3', '2', '-6', '-2', null, '-2', false ],
[ '-3', '2', '-6', '-1', null, '-2', false ],
// value = "" (NaN).
[ '', null, null, null, null, '', false ],
[ '', null, null, null, null, '1', false ],
// With step = 'any'.
[ '0', 'any', null, null, 1, null, true ],
[ '0', 'ANY', null, null, 1, null, true ],
@ -619,7 +619,7 @@ function checkStepUp()
[ '1970-01-01', '3', '1970-02-01', '1970-02-07', 15, '1970-02-07', false ],
[ '1970-01-01', '3', '1970-01-01', '1970-01-06', 2, '1970-01-04', false ],
// value = "" (NaN).
[ '', null, null, null, null, '', false ],
[ '', null, null, null, null, '1970-01-02', false ],
// With step = 'any'.
[ '2012-01-01', 'any', null, null, 1, null, true ],
[ '2012-01-01', 'ANY', null, null, 1, null, true ],
@ -683,7 +683,7 @@ function checkStepUp()
[ '17:22', '180', '17:00', '17:20', 15, '17:22', false ],
[ '17:22', '180', '17:10', '17:20', 2, '17:22', false ],
// value = "" (NaN).
[ '', null, null, null, null, '', false ],
[ '', null, null, null, null, '00:01', false ],
// With step = 'any'.
[ '17:26', 'any', null, null, 1, null, true ],
[ '17:26', 'ANY', null, null, 1, null, true ],

View File

@ -154,6 +154,7 @@ support-files =
reflect.js
wakelock.ogg
wakelock.ogv
file_ignoreuserfocus.html
[test_a_text.html]
[test_anchor_href_cache_invalidation.html]
@ -416,3 +417,4 @@ support-files =
[test_undoManager.html]
[test_video_wakelock.html]
[test_input_files_not_nsIFile.html]
[test_ignoreuserfocus.html]

View File

@ -0,0 +1,146 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7">
"use strict";
SimpleTest.waitForExplicitFinish();
// Copied from EventUtils.js, but we want *ToWindow methods.
function synthesizeMouseAtPoint(left, top, aEvent, aWindow) {
var utils = _getDOMWindowUtils(aWindow);
var defaultPrevented = false;
if (utils) {
var button = aEvent.button || 0;
var clickCount = aEvent.clickCount || 1;
var modifiers = _parseModifiers(aEvent);
var pressure = ("pressure" in aEvent) ? aEvent.pressure : 0;
var inputSource = ("inputSource" in aEvent) ? aEvent.inputSource : 0;
if (("type" in aEvent) && aEvent.type) {
defaultPrevented = utils.sendMouseEventToWindow(aEvent.type, left, top, button, clickCount, modifiers, false, pressure, inputSource);
}
else {
utils.sendMouseEventToWindow("mousedown", left, top, button, clickCount, modifiers, false, pressure, inputSource);
utils.sendMouseEventToWindow("mouseup", left, top, button, clickCount, modifiers, false, pressure, inputSource);
}
}
}
function runTest() {
var witness = document.createElement("input");
witness.setAttribute("type", "text");
var witness2 = document.createElement("input");
witness2.setAttribute("type", "text");
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
iframe.setAttribute("ignoreuserfocus", "true");
iframe.setAttribute("height", "500px");
iframe.setAttribute("src", "file_ignoreuserfocus.html");
iframe.addEventListener('load', function (e) {
// Get privileged iframe because mozbrowser iframe is not same origin
// with the parent. We need to access its content through the wrapper.
var privilegedIframe = SpecialPowers.wrap(iframe);
privilegedIframe.contentWindow.addEventListener("MozAfterPaint", function afterPaint(e) {
privilegedIframe.contentWindow.removeEventListener("MozAfterPaint", afterPaint);
privilegedIframe.contentWindow.addEventListener("focus",
function(e) {
ok(!iframe.hasAttribute("ignoreuserfocus"), "Shouldn't get a focus event in ignoreuserfocus iframe!");
},
true);
privilegedIframe.contentWindow.addEventListener("blur",
function(e) {
ok(!iframe.hasAttribute("ignoreuserfocus"), "Shouldn't get a blur event in ignoreuserfocus iframe!");
},
true);
// Sanity check
witness.focus();
is(document.activeElement, witness, "witness should have the focus");
iframe.focus();
isnot(document.activeElement, iframe, "[explicit iframe.focus()] iframe should not get the focus");
iframe.removeAttribute("ignoreuserfocus");
iframe.focus();
is(document.activeElement, iframe, "[explicit iframe.focus()] iframe should get the focus");
iframe.setAttribute("ignoreuserfocus", "true");
// Test the case when iframe contains <input> and .focus()
// is called and explicit focus using mouse
witness.focus();
var innerInput = privilegedIframe.contentDocument.getElementsByTagName("input")[0];
innerInput.focus();
isnot(document.activeElement, iframe, "[explicit innerInput.focus()] iframe should not have the focus");
var iframeWindow = SpecialPowers.unwrap(privilegedIframe.contentWindow);
witness.focus();
synthesizeMouseAtCenter(innerInput, {}, iframeWindow);
is(document.activeElement, witness, "[synthesize mouse click] witness should have the focus");
// Test the case when iframe contains <iframe> and .focus()
// is called and explicit focus using mouse
witness.focus();
var innerIframe = privilegedIframe.contentDocument.getElementsByTagName("iframe")[0];
innerIframe.focus();
isnot(document.activeElement, iframe, "[explicit innerIframe.focus()] iframe should not have the focus");
witness.focus();
synthesizeMouseAtCenter(innerIframe, {}, iframeWindow);
is(document.activeElement, witness, "[synthesize mouse click inner iframe] witness should have the focus");
// Test the case when iframe contains <area> and .focus()
// is called and explicit focus using mouse
witness.focus();
// Wait for paint to setup frame for area. Currently the area frame
// map is reset for each paint. If we are in the middle of a paint
// then the area will not be focusable.
privilegedIframe.contentWindow.addEventListener("MozAfterPaint", function afterPaintArea(e) {
privilegedIframe.contentWindow.removeEventListener("MozAfterPaint", afterPaintArea);
var innerArea = privilegedIframe.contentDocument.getElementsByTagName("area")[0];
innerArea.focus();
isnot(document.activeElement, iframe, "[explicit innerArea.focus()] iframe should not have the focus");
witness.focus();
synthesizeMouseAtCenter(innerArea, {}, iframeWindow);
is(document.activeElement, witness, "[synthesize mouse click] witness should have the focus");
// Test tabindex
witness.focus();
is(document.activeElement, witness, "witness should have the focus");
synthesizeKey("VK_TAB", {});
isnot(document.activeElement, iframe, "[synthesize tab key] iframe should not have the focus");
is(document.activeElement, witness2, "witness2 should have the focus");
SimpleTest.finish();
});
});
});
document.body.appendChild(witness);
document.body.appendChild(iframe);
document.body.appendChild(witness2);
}
addEventListener("load", function() {
SpecialPowers.addPermission("browser", true, document);
SpecialPowers.pushPrefEnv({
"set": [
["dom.mozBrowserFramesEnabled", true]
]
}, runTest);
});
</script>
</body>
</html>

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html class="reftest-wait">
<style>
iframe {
width: 100%;
height: 100%;
border: 0px;
}
</style>
<script>
document.addEventListener('MozReftestInvalidate',
() => document.documentElement.removeAttribute('class'),
false);
</script>
<body>
<iframe src="bug917595-unrotated.jpg" scrolling="no" marginwidth="0" marginheight="0"></iframe>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html class="reftest-wait">
<style>
iframe {
width: 100%;
height: 100%;
border: 0px;
}
</style>
<script>
document.addEventListener('MozReftestInvalidate',
() => document.documentElement.removeAttribute('class'),
false);
</script>
<body>
<iframe src="bug917595-exif-rotated.jpg" scrolling="no" marginwidth="0" marginheight="0"></iframe>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View File

@ -3,3 +3,10 @@
== bug448564-4a.html bug448564-4b.html
== bug502168-1_malformed.html bug502168-1_well-formed.html
# Test that image documents taken into account CSS properties like
# image-orientation when determining the size of the image.
# (Fuzzy necessary due to pixel-wise comparison of different JPEGs.
# The vast majority of the fuzziness comes from Linux and WinXP.)
fuzzy(1,149) == bug917595-iframe-1.html bug917595-1-ref.html
fuzzy(2,446) == bug917595-exif-rotated.jpg bug917595-pixel-rotated.jpg

View File

@ -15,6 +15,7 @@
#include "nsIDOMKeyEvent.h"
#include "nsIDOMMouseEvent.h"
#include "nsIDOMEventListener.h"
#include "nsIFrame.h"
#include "nsGkAtoms.h"
#include "imgIRequest.h"
#include "imgILoader.h"
@ -209,6 +210,7 @@ ImageDocument::Destroy()
if (mImageContent) {
// Remove our event listener from the image content.
nsCOMPtr<EventTarget> target = do_QueryInterface(mImageContent);
target->RemoveEventListener(NS_LITERAL_STRING("load"), this, false);
target->RemoveEventListener(NS_LITERAL_STRING("click"), this, false);
// Break reference cycle with mImageContent, if we have one
@ -253,6 +255,7 @@ ImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject)
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic document");
target = do_QueryInterface(mImageContent);
target->AddEventListener(NS_LITERAL_STRING("load"), this, false);
target->AddEventListener(NS_LITERAL_STRING("click"), this, false);
}
@ -509,8 +512,11 @@ ImageDocument::SetModeClass(eModeClasses mode)
nsresult
ImageDocument::OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage)
{
// Styles have not yet been applied, so we don't know the final size. For now,
// default to the image's intrinsic size.
aImage->GetWidth(&mImageWidth);
aImage->GetHeight(&mImageHeight);
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &ImageDocument::DefaultCheckOverflowing);
nsContentUtils::AddScriptRunner(runnable);
@ -573,11 +579,44 @@ ImageDocument::HandleEvent(nsIDOMEvent* aEvent)
else if (mImageIsOverflowing) {
ShrinkToFit();
}
} else if (eventType.EqualsLiteral("load")) {
UpdateSizeFromLayout();
}
return NS_OK;
}
void
ImageDocument::UpdateSizeFromLayout()
{
// Pull an updated size from the content frame to account for any size
// change due to CSS properties like |image-orientation|.
Element* contentElement = mImageContent->AsElement();
if (!contentElement) {
return;
}
nsIFrame* contentFrame = contentElement->GetPrimaryFrame(Flush_Frames);
if (!contentFrame) {
return;
}
nsIntSize oldSize(mImageWidth, mImageHeight);
IntrinsicSize newSize = contentFrame->GetIntrinsicSize();
if (newSize.width.GetUnit() == eStyleUnit_Coord) {
mImageWidth = nsPresContext::AppUnitsToFloatCSSPixels(newSize.width.GetCoordValue());
}
if (newSize.height.GetUnit() == eStyleUnit_Coord) {
mImageHeight = nsPresContext::AppUnitsToFloatCSSPixels(newSize.height.GetCoordValue());
}
// Ensure that our information about overflow is up-to-date if needed.
if (mImageWidth != oldSize.width || mImageHeight != oldSize.height) {
CheckOverflowing(false);
}
}
nsresult
ImageDocument::CreateSyntheticDocument()
{

View File

@ -94,6 +94,8 @@ protected:
void ResetZoomLevel();
float GetZoomLevel();
void UpdateSizeFromLayout();
enum eModeClasses {
eNone,
eShrinkToFit,

View File

@ -815,7 +815,7 @@ nsMathMLElement::SetIncrementScriptLevel(bool aIncrementScriptLevel,
}
bool
nsMathMLElement::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
nsMathMLElement::IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse)
{
nsCOMPtr<nsIURI> uri;
if (IsLink(getter_AddRefs(uri))) {

View File

@ -80,8 +80,7 @@ public:
return mIncrementScriptLevel;
}
virtual bool IsFocusable(int32_t *aTabIndex = nullptr,
bool aWithMouse = false) MOZ_OVERRIDE;
virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) MOZ_OVERRIDE;
virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
virtual void GetLinkTarget(nsAString& aTarget) MOZ_OVERRIDE;
virtual already_AddRefed<nsIURI> GetHrefURI() const MOZ_OVERRIDE;

View File

@ -32,6 +32,9 @@ namespace mozilla {
#ifdef PR_LOGGING
PRLogModuleInfo* gMediaStreamGraphLog;
#define LOG(type, msg) PR_LOG(gMediaStreamGraphLog, type, msg)
#else
#define LOG(type, msg)
#endif
/**
@ -39,6 +42,14 @@ PRLogModuleInfo* gMediaStreamGraphLog;
*/
static MediaStreamGraphImpl* gGraph;
MediaStreamGraphImpl::~MediaStreamGraphImpl()
{
NS_ASSERTION(IsEmpty(),
"All streams should have been destroyed by messages from the main thread");
LOG(PR_LOG_DEBUG, ("MediaStreamGraph %p destroyed", this));
}
StreamTime
MediaStreamGraphImpl::GetDesiredBufferEnd(MediaStream* aStream)
{

View File

@ -1057,7 +1057,7 @@ protected:
{
MOZ_COUNT_CTOR(MediaStreamGraph);
}
~MediaStreamGraph()
virtual ~MediaStreamGraph()
{
MOZ_COUNT_DTOR(MediaStreamGraph);
}

View File

@ -19,13 +19,6 @@ namespace mozilla {
template <typename T>
class LinkedList;
#ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaStreamGraphLog;
#define LOG(type, msg) PR_LOG(gMediaStreamGraphLog, type, msg)
#else
#define LOG(type, msg)
#endif
/**
* Assume we can run an iteration of the MediaStreamGraph loop in this much time
* or less.
@ -120,12 +113,7 @@ public:
* implement OfflineAudioContext. They do not support MediaStream inputs.
*/
explicit MediaStreamGraphImpl(bool aRealtime);
~MediaStreamGraphImpl()
{
NS_ASSERTION(IsEmpty(),
"All streams should have been destroyed by messages from the main thread");
LOG(PR_LOG_DEBUG, ("MediaStreamGraph %p destroyed", this));
}
virtual ~MediaStreamGraphImpl();
// Main thread only.
/**

View File

@ -161,7 +161,7 @@ SVGAElement::IsAttributeMapped(const nsIAtom* name) const
}
bool
SVGAElement::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
SVGAElement::IsFocusableInternal(int32_t *aTabIndex, bool aWithMouse)
{
nsCOMPtr<nsIURI> uri;
if (IsLink(getter_AddRefs(uri))) {

View File

@ -43,7 +43,7 @@ public:
virtual void UnbindFromTree(bool aDeep = true,
bool aNullParent = true) MOZ_OVERRIDE;
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false) MOZ_OVERRIDE;
virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) MOZ_OVERRIDE;
virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
virtual void GetLinkTarget(nsAString& aTarget) MOZ_OVERRIDE;
virtual already_AddRefed<nsIURI> GetHrefURI() const MOZ_OVERRIDE;

View File

@ -511,7 +511,7 @@ static bool IsNonList(nsINodeInfo* aNodeInfo)
}
bool
nsXULElement::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
nsXULElement::IsFocusableInternal(int32_t *aTabIndex, bool aWithMouse)
{
/*
* Returns true if an element may be focused, and false otherwise. The inout

View File

@ -396,7 +396,7 @@ public:
virtual nsIContent *GetBindingParent() const MOZ_OVERRIDE;
virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false) MOZ_OVERRIDE;
virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) MOZ_OVERRIDE;
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) MOZ_OVERRIDE;
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,

View File

@ -47,7 +47,7 @@ EXPORTS.mozilla += [
'LoadContext.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'LoadContext.cpp',
'nsAboutRedirector.cpp',
'nsDefaultURIFixup.cpp',

View File

@ -4,13 +4,15 @@
* 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/. */
#ifndef nsDocShellEnumerator_h___
#define nsDocShellEnumerator_h___
#include "nsISimpleEnumerator.h"
#include "nsTArray.h"
#include "nsIWeakReferenceUtils.h"
class nsIDocShellTreeItem;
/*
// {13cbc281-35ae-11d5-be5b-bde0edece43c}
#define NS_DOCSHELL_FORWARDS_ENUMERATOR_CID \
@ -105,5 +107,6 @@ public:
protected:
virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray);
};
#endif // nsDocShellEnumerator_h___

View File

@ -8,7 +8,7 @@ EXPORTS += [
'nsSHEntryShared.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'nsSHEntry.cpp',
'nsSHEntryShared.cpp',
'nsSHistory.cpp',

View File

@ -1396,10 +1396,12 @@ nsFocusManager::IsNonFocusableRoot(nsIContent* aContent)
// focusable.
// Also, if aContent is not editable but it isn't in designMode, it's not
// focusable.
// And in userfocusignored context nothing is focusable.
nsIDocument* doc = aContent->GetCurrentDoc();
NS_ASSERTION(doc, "aContent must have current document");
return aContent == doc->GetRootElement() &&
(doc->HasFlag(NODE_IS_EDITABLE) || !aContent->IsEditable());
(doc->HasFlag(NODE_IS_EDITABLE) || !aContent->IsEditable() ||
nsContentUtils::IsUserFocusIgnored(aContent));
}
nsIContent*
@ -1428,9 +1430,10 @@ nsFocusManager::CheckIfFocusable(nsIContent* aContent, uint32_t aFlags)
if (!shell)
return nullptr;
// the root content can always be focused
// the root content can always be focused,
// except in userfocusignored context.
if (aContent == doc->GetRootElement())
return aContent;
return nsContentUtils::IsUserFocusIgnored(aContent) ? nullptr : aContent;
// cannot focus content in print preview mode. Only the root can be focused.
nsPresContext* presContext = shell->GetPresContext();
@ -1881,10 +1884,18 @@ nsFocusManager::SendFocusOrBlurEvent(uint32_t aType,
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
nsCOMPtr<nsINode> n = do_QueryInterface(aTarget);
if (!n) {
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aTarget);
n = win ? win->GetExtantDoc() : nullptr;
}
bool dontDispatchEvent = n && nsContentUtils::IsUserFocusIgnored(n);
// for focus events, if this event was from a mouse or key and event
// handling on the document is suppressed, queue the event and fire it
// later. For blur events, a non-zero value would be set for aFocusMethod.
if (aFocusMethod && aDocument && aDocument->EventHandlingSuppressed()) {
if (aFocusMethod && !dontDispatchEvent &&
aDocument && aDocument->EventHandlingSuppressed()) {
// aFlags is always 0 when aWindowRaised is true so this won't be called
// on a window raise.
NS_ASSERTION(!aWindowRaised, "aWindowRaised should not be set");
@ -1914,9 +1925,11 @@ nsFocusManager::SendFocusOrBlurEvent(uint32_t aType,
}
#endif
nsContentUtils::AddScriptRunner(
new FocusBlurEvent(aTarget, aType, aPresShell->GetPresContext(),
aWindowRaised, aIsRefocus));
if (!dontDispatchEvent) {
nsContentUtils::AddScriptRunner(
new FocusBlurEvent(aTarget, aType, aPresShell->GetPresContext(),
aWindowRaised, aIsRefocus));
}
}
void

View File

@ -1117,7 +1117,7 @@ ResolvePrototypeOrConstructor(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Rooted<JSObject*> global(cx, js::GetGlobalForObjectCrossCompartment(obj));
{
JSAutoCompartment ac(cx, global);
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(global);
ProtoAndIfaceArray& protoAndIfaceArray = *GetProtoAndIfaceArray(global);
JSObject* protoOrIface = protoAndIfaceArray[protoAndIfaceArrayIndex];
if (!protoOrIface) {
return false;

View File

@ -10,6 +10,7 @@
#include "jsfriendapi.h"
#include "jswrapper.h"
#include "mozilla/Alignment.h"
#include "mozilla/Array.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/CallbackObject.h"
#include "mozilla/dom/DOMJSClass.h"
@ -280,21 +281,28 @@ static_assert((size_t)constructors::id::_ID_Start ==
"Overlapping or discontiguous indexes.");
const size_t kProtoAndIfaceCacheCount = constructors::id::_ID_Count;
class ProtoAndIfaceArray : public Array<JS::Heap<JSObject*>, kProtoAndIfaceCacheCount>
{
public:
ProtoAndIfaceArray() {
MOZ_COUNT_CTOR(ProtoAndIfaceArray);
}
~ProtoAndIfaceArray() {
MOZ_COUNT_DTOR(ProtoAndIfaceArray);
}
};
inline void
AllocateProtoAndIfaceCache(JSObject* obj)
{
MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
MOZ_ASSERT(js::GetReservedSlot(obj, DOM_PROTOTYPE_SLOT).isUndefined());
JS::Heap<JSObject*>* protoAndIfaceArray = new JS::Heap<JSObject*>[kProtoAndIfaceCacheCount];
ProtoAndIfaceArray* protoAndIfaceArray = new ProtoAndIfaceArray();
js::SetReservedSlot(obj, DOM_PROTOTYPE_SLOT,
JS::PrivateValue(protoAndIfaceArray));
#ifdef NS_BUILD_REFCNT_LOGGING
NS_LogCtor((void*)protoAndIfaceArray, "ProtoAndIfaceArray",
sizeof(JS::Heap<JSObject*>) * kProtoAndIfaceCacheCount);
#endif
}
inline void
@ -304,8 +312,8 @@ TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj)
if (!HasProtoAndIfaceArray(obj))
return;
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(obj);
for (size_t i = 0; i < kProtoAndIfaceCacheCount; ++i) {
ProtoAndIfaceArray& protoAndIfaceArray = *GetProtoAndIfaceArray(obj);
for (size_t i = 0; i < ArrayLength(protoAndIfaceArray); ++i) {
if (protoAndIfaceArray[i]) {
JS_CallHeapObjectTracer(trc, &protoAndIfaceArray[i], "protoAndIfaceArray[i]");
}
@ -317,14 +325,9 @@ DestroyProtoAndIfaceCache(JSObject* obj)
{
MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(obj);
ProtoAndIfaceArray* protoAndIfaceArray = GetProtoAndIfaceArray(obj);
#ifdef NS_BUILD_REFCNT_LOGGING
NS_LogDtor((void*)protoAndIfaceArray, "ProtoAndIfaceArray",
sizeof(JS::Heap<JSObject*>) * kProtoAndIfaceCacheCount);
#endif
delete [] protoAndIfaceArray;
delete protoAndIfaceArray;
}
/**
@ -2066,7 +2069,7 @@ ReportLenientThisUnwrappingFailure(JSContext* cx, JSObject* obj);
inline JSObject*
GetUnforgeableHolder(JSObject* aGlobal, prototypes::ID aId)
{
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
ProtoAndIfaceArray& protoAndIfaceArray = *GetProtoAndIfaceArray(aGlobal);
JSObject* interfaceProto = protoAndIfaceArray[aId];
return &js::GetReservedSlot(interfaceProto,
DOM_INTERFACE_PROTO_SLOTS_BASE).toObject();

View File

@ -1800,7 +1800,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
def __init__(self, descriptor, properties):
args = [Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'aGlobal'),
Argument('JS::Heap<JSObject*>*', 'aProtoAndIfaceArray'),
Argument('ProtoAndIfaceArray&', 'aProtoAndIfaceArray'),
Argument('bool', 'aDefineOnGlobal')]
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
self.properties = properties
@ -2012,7 +2012,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
return JS::NullPtr();
}
/* Check to see whether the interface objects are already installed */
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
ProtoAndIfaceArray& protoAndIfaceArray = *GetProtoAndIfaceArray(aGlobal);
if (!protoAndIfaceArray[%s]) {
CreateInterfaceObjects(aCx, aGlobal, protoAndIfaceArray, aDefineOnGlobal);
}
@ -9068,6 +9068,7 @@ class CGForwardDeclarations(CGWrapper):
# We just about always need NativePropertyHooks
builder.addInMozillaDom("NativePropertyHooks")
builder.addInMozillaDom("ProtoAndIfaceArray")
for callback in mainCallbacks:
forwardDeclareForType(callback)

View File

@ -216,6 +216,8 @@ struct DOMIfaceAndProtoJSClass
const JSClass* ToJSClass() const { return &mBase; }
};
class ProtoAndIfaceArray;
inline bool
HasProtoAndIfaceArray(JSObject* global)
{
@ -224,11 +226,11 @@ HasProtoAndIfaceArray(JSObject* global)
return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined();
}
inline JS::Heap<JSObject*>*
inline ProtoAndIfaceArray*
GetProtoAndIfaceArray(JSObject* global)
{
MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
return static_cast<JS::Heap<JSObject*>*>(
return static_cast<ProtoAndIfaceArray*>(
js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).toPrivate());
}

View File

@ -55,6 +55,7 @@ using namespace mozilla::dom;
using namespace mozilla::dom::indexedDB::ipc;
using mozilla::dom::quota::FileOutputStream;
using mozilla::ErrorResult;
using mozilla::fallible_t;
BEGIN_INDEXEDDB_NAMESPACE
@ -1220,6 +1221,8 @@ IDBObjectStore::GetStructuredCloneReadInfoFromStatement(
const char* compressed = reinterpret_cast<const char*>(blobData);
size_t compressedLength = size_t(blobDataLength);
static const fallible_t fallible = fallible_t();
size_t uncompressedLength;
if (!snappy::GetUncompressedLength(compressed, compressedLength,
&uncompressedLength)) {
@ -1227,7 +1230,8 @@ IDBObjectStore::GetStructuredCloneReadInfoFromStatement(
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
nsAutoArrayPtr<char> uncompressed(new char[uncompressedLength]);
nsAutoArrayPtr<char> uncompressed(new (fallible) char[uncompressedLength]);
NS_ENSURE_TRUE(uncompressed, NS_ERROR_OUT_OF_MEMORY);
if (!snappy::RawUncompress(compressed, compressedLength,
uncompressed.get())) {
@ -1409,7 +1413,7 @@ StructuredCloneReadString(JSStructuredCloneReader* aReader,
}
length = SwapBytes(length);
if (!aString.SetLength(length, mozilla::fallible_t())) {
if (!aString.SetLength(length, fallible_t())) {
NS_WARNING("Out of memory?");
return false;
}
@ -3213,10 +3217,12 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
reinterpret_cast<const char*>(mCloneWriteInfo.mCloneBuffer.data());
size_t uncompressedLength = mCloneWriteInfo.mCloneBuffer.nbytes();
static const fallible_t fallible = fallible_t();
size_t compressedLength = snappy::MaxCompressedLength(uncompressedLength);
// This will hold our compressed data until the end of the method. The
// BindBlobByName function will copy it.
nsAutoArrayPtr<char> compressed(new char[compressedLength]);
nsAutoArrayPtr<char> compressed(new (fallible) char[compressedLength]);
NS_ENSURE_TRUE(compressed, NS_ERROR_OUT_OF_MEMORY);
snappy::RawCompress(uncompressed, uncompressedLength, compressed.get(),
&compressedLength);

View File

@ -881,8 +881,10 @@ public:
rv = aArguments->GetSharedBlob(0, &uncompressedLength, &uncompressed);
NS_ENSURE_SUCCESS(rv, rv);
static const fallible_t fallible = fallible_t();
size_t compressedLength = snappy::MaxCompressedLength(uncompressedLength);
nsAutoArrayPtr<char> compressed(new char[compressedLength]);
nsAutoArrayPtr<char> compressed(new (fallible) char[compressedLength]);
NS_ENSURE_TRUE(compressed, NS_ERROR_OUT_OF_MEMORY);
snappy::RawCompress(reinterpret_cast<const char*>(uncompressed),
uncompressedLength, compressed.get(),

View File

@ -767,6 +767,12 @@ function isPlainTextField(element) {
}
function getJSON(element, focusCounter) {
// <input type=number> has a nested anonymous <input type=text> element that
// takes focus on behalf of the number control when someone tries to focus
// the number control. If |element| is such an anonymous text control then we
// need it's number control here in order to get the correct 'type' etc.:
element = element.ownerNumberControl || element;
let type = element.type || "";
let value = element.value || "";
let max = element.max || "";

View File

@ -320,7 +320,7 @@ Promise::Constructor(const GlobalObject& aGlobal,
/* static */ already_AddRefed<Promise>
Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
JS::Handle<JS::Value> aValue, ErrorResult& aRv)
const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
if (!window) {
@ -330,13 +330,14 @@ Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
nsRefPtr<Promise> promise = new Promise(window);
promise->MaybeResolveInternal(aCx, aValue);
promise->MaybeResolveInternal(aCx,
aValue.WasPassed() ? aValue.Value() : JS::UndefinedHandleValue);
return promise.forget();
}
/* static */ already_AddRefed<Promise>
Promise::Reject(const GlobalObject& aGlobal, JSContext* aCx,
JS::Handle<JS::Value> aValue, ErrorResult& aRv)
const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
if (!window) {
@ -346,27 +347,28 @@ Promise::Reject(const GlobalObject& aGlobal, JSContext* aCx,
nsRefPtr<Promise> promise = new Promise(window);
promise->MaybeRejectInternal(aCx, aValue);
promise->MaybeRejectInternal(aCx,
aValue.WasPassed() ? aValue.Value() : JS::UndefinedHandleValue);
return promise.forget();
}
already_AddRefed<Promise>
Promise::Then(const Optional<OwningNonNull<AnyCallback> >& aResolveCallback,
const Optional<OwningNonNull<AnyCallback> >& aRejectCallback)
Promise::Then(const Optional<nsRefPtr<AnyCallback>>& aResolveCallback,
const Optional<nsRefPtr<AnyCallback>>& aRejectCallback)
{
nsRefPtr<Promise> promise = new Promise(GetParentObject());
nsRefPtr<PromiseCallback> resolveCb =
PromiseCallback::Factory(promise,
aResolveCallback.WasPassed()
? &aResolveCallback.Value()
? aResolveCallback.Value()
: nullptr,
PromiseCallback::Resolve);
nsRefPtr<PromiseCallback> rejectCb =
PromiseCallback::Factory(promise,
aRejectCallback.WasPassed()
? &aRejectCallback.Value()
? aRejectCallback.Value()
: nullptr,
PromiseCallback::Reject);
@ -376,9 +378,9 @@ Promise::Then(const Optional<OwningNonNull<AnyCallback> >& aResolveCallback,
}
already_AddRefed<Promise>
Promise::Catch(const Optional<OwningNonNull<AnyCallback> >& aRejectCallback)
Promise::Catch(const Optional<nsRefPtr<AnyCallback>>& aRejectCallback)
{
Optional<OwningNonNull<AnyCallback> > resolveCb;
Optional<nsRefPtr<AnyCallback>> resolveCb;
return Then(resolveCb, aRejectCallback);
}

View File

@ -66,19 +66,19 @@ public:
static already_AddRefed<Promise>
Resolve(const GlobalObject& aGlobal, JSContext* aCx,
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
static already_AddRefed<Promise>
Reject(const GlobalObject& aGlobal, JSContext* aCx,
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
already_AddRefed<Promise>
Then(const Optional<OwningNonNull<AnyCallback> >& aResolveCallback,
const Optional<OwningNonNull<AnyCallback> >& aRejectCallback);
Then(const Optional<nsRefPtr<AnyCallback>>& aResolveCallback,
const Optional<nsRefPtr<AnyCallback>>& aRejectCallback);
already_AddRefed<Promise>
Catch(const Optional<OwningNonNull<AnyCallback> >& aRejectCallback);
Catch(const Optional<nsRefPtr<AnyCallback>>& aRejectCallback);
void AppendNativeHandler(PromiseNativeHandler* aRunnable);

View File

@ -34,6 +34,22 @@ function promiseResolve() {
});
}
function promiseResolveNoArg() {
var promise = new Promise(function(resolve, reject) {
ok(resolve, "Promise.resolve exists");
ok(reject, "Promise.reject exists");
resolve();
}).then(function(what) {
ok(true, "Then - resolveCb has been called");
is(what, undefined, "ResolveCb received undefined");
runTest();
}, function() {
ok(false, "Then - rejectCb has been called");
runTest();
});
}
function promiseReject() {
var promise = new Promise(function(resolve, reject) {
reject(42);
@ -47,6 +63,19 @@ function promiseReject() {
});
}
function promiseRejectNoArg() {
var promise = new Promise(function(resolve, reject) {
reject();
}).then(function(what) {
ok(false, "Then - resolveCb has been called");
runTest();
}, function(what) {
ok(true, "Then - rejectCb has been called");
is(what, undefined, "RejectCb received undefined");
runTest();
});
}
function promiseException() {
var promise = new Promise(function(resolve, reject) {
throw 42;
@ -164,6 +193,51 @@ function promiseThenCatchThen() {
});
}
function promiseThenNoArg() {
var promise = new Promise(function(resolve, reject) {
resolve(42);
});
var clone = promise.then();
isnot(promise, clone, "These 2 promise objs are different");
promise.then(function(v) {
clone.then(function(cv) {
is(v, cv, "Both resolve to the same value");
runTest();
});
});
}
function promiseThenUndefinedResolveFunction() {
var promise = new Promise(function(resolve, reject) {
reject(42);
});
try {
promise.then(undefined, function(v) {
is(v, 42, "Promise rejected with 42");
runTest();
});
} catch (e) {
ok(false, "then should not throw on undefined resolve function");
}
}
function promiseThenNullResolveFunction() {
var promise = new Promise(function(resolve, reject) {
reject(42);
});
try {
promise.then(null, function(v) {
is(v, 42, "Promise rejected with 42");
runTest();
});
} catch (e) {
ok(false, "then should not throw on null resolve function");
}
}
function promiseRejectThenCatchThen() {
var promise = new Promise(function(resolve, reject) {
reject(42);
@ -280,6 +354,21 @@ function promiseThenCatchOrderingReject() {
});
}
function promiseCatchNoArg() {
var promise = new Promise(function(resolve, reject) {
reject(42);
});
var clone = promise.catch();
isnot(promise, clone, "These 2 promise objs are different");
promise.catch(function(v) {
clone.catch(function(cv) {
is(v, cv, "Both reject to the same value");
runTest();
});
});
}
function promiseNestedPromise() {
new Promise(function(resolve, reject) {
resolve(new Promise(function(resolve, reject) {
@ -380,6 +469,12 @@ var tests = [ promiseResolve, promiseReject,
promiseWrongNestedPromise, promiseLoop,
promiseStaticReject, promiseStaticResolve,
promiseResolveNestedPromise,
promiseResolveNoArg,
promiseRejectNoArg,
promiseThenNoArg,
promiseThenUndefinedResolveFunction,
promiseThenNullResolveFunction,
promiseCatchNoArg
];
function runTest() {

View File

@ -154,6 +154,18 @@ partial interface HTMLInputElement {
[ChromeOnly]
void mozSetFileNameArray(sequence<DOMString> fileNames);
// Number controls (<input type=number>) have an anonymous text control
// (<input type=text>) in the anonymous shadow tree that they contain. On
// such an anonymous text control this property provides access to the
// number control that owns the text control. This is useful, for example,
// in code that looks at the currently focused element to make decisions
// about which IME to bring up. Such code needs to be able to check for any
// owning number control since it probably wants to bring up a number pad
// instead of the standard keyboard, even when the anonymous text control has
// focus.
[ChromeOnly]
readonly attribute HTMLInputElement? ownerNumberControl;
boolean mozIsTextField(boolean aExcludePassword);
};

View File

@ -23,14 +23,14 @@ interface Promise {
// Promise object in this scope without having resolved the interface object
// first.
[NewObject, Throws, Func="mozilla::dom::Promise::EnabledForScope"]
static Promise resolve(any value); // same as any(value)
static Promise resolve(optional any value);
[NewObject, Throws, Func="mozilla::dom::Promise::EnabledForScope"]
static Promise reject(any value);
static Promise reject(optional any value);
[NewObject]
Promise then(optional AnyCallback fulfillCallback,
optional AnyCallback rejectCallback);
Promise then(optional AnyCallback? fulfillCallback,
optional AnyCallback? rejectCallback);
[NewObject]
Promise catch(optional AnyCallback rejectCallback);
Promise catch(optional AnyCallback? rejectCallback);
};

View File

@ -18,7 +18,7 @@ namespace gl {
GLLibraryEGL sEGLLibrary;
// should match the order of EGLExtensions, and be null-terminated.
static const char *sExtensionNames[] = {
static const char *sEGLExtensionNames[] = {
"EGL_KHR_image_base",
"EGL_KHR_image_pixmap",
"EGL_KHR_gl_texture_2D_image",
@ -321,7 +321,7 @@ GLLibraryEGL::InitExtensions()
const bool firstRun = false;
#endif
GLContext::InitializeExtensionsBitSet(mAvailableExtensions, extensions, sExtensionNames, firstRun && debugMode);
GLContext::InitializeExtensionsBitSet(mAvailableExtensions, extensions, sEGLExtensionNames, firstRun && debugMode);
#ifdef DEBUG
firstRun = false;

View File

@ -59,36 +59,48 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'SharedSurfaceANGLE.h',
'WGLLibrary.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'GLContextProviderEGL.cpp',
'SharedSurfaceANGLE.cpp',
]
if CONFIG['MOZ_ENABLE_SKIA_GPU']:
EXPORTS += ['GLContextSkia.h']
SOURCES += [
UNIFIED_SOURCES += [
'GLContextSkia.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
SOURCES += ['SharedSurfaceGralloc.cpp']
UNIFIED_SOURCES += ['SharedSurfaceGralloc.cpp']
EXPORTS += ['SharedSurfaceGralloc.h']
if gl_provider == 'CGL':
# This file includes Mac headers that are unfriendly to unified builds,
# and we have only one .mm file here anyway.
SOURCES += [
"GLContextProvider%s.mm" % (gl_provider),
]
EXPORTS += [
'SharedSurfaceIO.h',
]
# SharedSurfaceIO.cpp includes MacIOSurface.h which include Mac headers
# which define Size and Point types in root namespace with often conflict with
# our own types. While I haven't actually hit this issue in the present case,
# it's been an issue in gfx/layers so let's not risk it.
SOURCES += [
'SharedSurfaceIO.cpp',
]
else:
elif gl_provider == 'GLX':
# GLContextProviderGLX.cpp needs to be kept out of UNIFIED_SOURCES
# as it includes X11 headers which cause conflicts.
SOURCES += [
'GLContextProviderGLX.cpp',
]
else:
UNIFIED_SOURCES += [
'GLContextProvider%s.cpp' % gl_provider,
]
SOURCES += [
UNIFIED_SOURCES += [
'GfxTexturesReporter.cpp',
'GLContext.cpp',
'GLContextFeatures.cpp',

View File

@ -168,10 +168,11 @@ LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget)
bool
LayerManagerComposite::EndEmptyTransaction(EndTransactionFlags aFlags)
{
mInTransaction = false;
if (!mRoot)
NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
if (!mRoot) {
mInTransaction = false;
return false;
}
EndTransaction(nullptr, nullptr);
return true;
@ -182,6 +183,7 @@ LayerManagerComposite::EndTransaction(DrawThebesLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags)
{
NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
mInTransaction = false;
#ifdef MOZ_LAYERS_HAVE_LOG

View File

@ -500,6 +500,15 @@ CompositorParent::ScheduleComposition()
void
CompositorParent::Composite()
{
if (CanComposite()) {
mLayerManager->BeginTransaction();
}
CompositeInTransaction();
}
void
CompositorParent::CompositeInTransaction()
{
profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START);
PROFILER_LABEL("CompositorParent", "Composite");
@ -564,7 +573,7 @@ CompositorParent::ComposeToTarget(DrawTarget* aTarget)
mLayerManager->BeginTransactionWithDrawTarget(aTarget);
// Since CanComposite() is true, Composite() must end the layers txn
// we opened above.
Composite();
CompositeInTransaction();
}
bool
@ -629,10 +638,7 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
}
}
ScheduleComposition();
LayerManagerComposite *layerComposite = mLayerManager->AsLayerManagerComposite();
if (layerComposite) {
layerComposite->NotifyShadowTreeTransaction();
}
mLayerManager->NotifyShadowTreeTransaction();
}
void

View File

@ -230,7 +230,8 @@ protected:
bool* aSuccess);
virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers);
virtual void ScheduleTask(CancelableTask*, int);
virtual void Composite();
void Composite();
void CompositeInTransaction();
virtual void ComposeToTarget(gfx::DrawTarget* aTarget);
void SetEGLSurfaceSize(int width, int height);

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

View File

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Background color wrapper for clear image tests</title>
<style>
img {
background-color: rgb(0, 255, 0);
}
</style>
</head>
<body>
<img id="image1">
<script>
// Loads an externally specified image and displays it
// with a green background. Intended for use with tests
// involving clear images.
// Use as "green-background.html?image.png".
// Get the image URL.
var imgURL = document.location.search.substr(1);
// Load it.
var img = document.images[0];
img.src = imgURL;
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

View File

@ -28,16 +28,31 @@ support-files =
bug767779.sjs
bug89419-iframe.html
bug89419.sjs
bug900200.png
bug900200-ref.png
clear.gif
clear.png
clear2.gif
clear2-results.gif
damon.jpg
error-early.png
green.png
green-background.html
grey.png
imgutils.js
invalid.jpg
keep.gif
keep.png
lime100x100.svg
red.png
restore-previous.gif
restore-previous.png
rillybad.jpg
schrep.png
shaver.png
short_header.gif
source.png
over.png
[test_ImageContentLoaded.html]
[test_bug399925.html]
@ -63,6 +78,7 @@ support-files =
[test_bug865919.html]
[test_bug89419-1.html]
[test_bug89419-2.html]
[test_animation_operators.html]
[test_drawDiscardedImage.html]
[test_error_events.html]
[test_short_gif_header.html]

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

View File

@ -0,0 +1,157 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=936720
-->
<head>
<title>Test for Bug 936720</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=936720">Mozilla Bug 936720</a>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 936720 **/
// Because there is no event telling us when an animated image finishes
// animating, tests for the operators used by animated GIFs and PNGs
// require that we poll until we get the correct result. A fixed timeout
// can easily result in intermittent failures on tests running in VMs.
// (Note that we do _not_ poll the reference, so it must not be animated.)
var gTests = [
// IMPORTANT NOTE: For these tests, the test and reference are not
// snapshotted in the same way. The REFERENCE (second file) is
// assumed to be complete when loaded, but we poll the TEST
// (first file) until the test passes.
// Tests of the allowed disposal operators for both GIF and APNG: keep, clear,
// and restore previous.
"== green-background.html?clear.gif green.png",
"== green-background.html?clear.png green.png",
"== keep.gif green.png",
"== keep.png green.png",
"== restore-previous.gif green.png",
"== restore-previous.png green.png",
// Tests of the blending/compositing operators that only APNG supports.
"== over.png grey.png",
"!= source.png grey.png",
"== bug900200.png bug900200-ref.png",
// Test of subframe updates.
"== clear2.gif clear2-results.gif",
];
// Maintain a reference count of how many things we're waiting for until
// we can say the tests are done.
var gDelayCount = 0;
function AddFinishDependency()
{ ++gDelayCount; }
function RemoveFinishDependency()
{ if (--gDelayCount == 0) SimpleTest.finish(); }
// We record the maximum number of times we had to look at a test before
// it switched to the passing state (though we assume it's 10 to start
// rather than 0 so that we have a reasonable default). Then we make a
// test "time out" if it takes more than gTimeoutFactor times that
// amount of time. This allows us to report a test failure rather than
// making a test failure just show up as a timeout.
var gMaxPassingTries = 10;
var gTimeoutFactor = 10;
function takeSnapshot(iframe_element)
{
return snapshotWindow(iframe_element.contentWindow, false);
}
function passes(op, shot1, shot2)
{
var [correct, s1, s2] = compareSnapshots(shot1, shot2, op == "==");
return correct;
}
function startTest(i)
{
var testLine = gTests[i];
var splitData = testLine.split(" ");
var testData =
{ op: splitData[0], test: splitData[1], reference: splitData[2] };
var tries = 0;
// Maintain state specific to this test in the closure exposed to all
// the functions nested inside this one.
function startIframe(url)
{
var element = document.createElement("iframe");
element.addEventListener("load", handleLoad, false);
// Smaller than normal reftests, but enough for these.
element.setAttribute("style", "width: 100px; height: 100px");
element.setAttribute("frameborder", "0");
element.setAttribute("scrolling", "no");
element.src = url;
document.body.appendChild(element);
function handleLoad(event)
{
iframe.loaded = true;
if (iframe == reference) {
reference.snapshot = takeSnapshot(element);
}
var other = (iframe == test) ? reference : test;
if (other.loaded) {
setTimeout(checkTest, 100);
}
}
function checkTest()
{
var test_snapshot = takeSnapshot(test.element);
if (passes(testData.op, test_snapshot, reference.snapshot)) {
if (tries > gMaxPassingTries) {
gMaxPassingTries = tries;
}
report(true);
} else {
++tries;
if (tries > gMaxPassingTries * gTimeoutFactor) {
info("Giving up after " + tries + " tries, " +
"maxp=" + gMaxPassingTries +
"fact=" + gTimeoutFactor);
report(false);
} else {
// The animation might not have finished. Try again in 100ms.
setTimeout(checkTest, 100);
}
}
}
function report(result)
{
ok(result, "(" + i + ") " +
testData.op + " " + testData.test + " " + testData.reference);
RemoveFinishDependency();
}
var iframe = { element: element, loaded: false };
return iframe;
}
AddFinishDependency();
var test = startIframe(testData.test);
var reference = startIframe(testData.reference);
}
SimpleTest.waitForExplicitFinish();
// Run the tests.
for (var i = 0; i < gTests.length; ++i) {
startTest(i);
}
</script>
</pre>
</body>
</html>

View File

@ -38,7 +38,7 @@ function forceDecode() {
}
function startTimer() {
const delay = 1000;
const delay = 10000;
setTimeout("document.documentElement.className = '';", delay);
}
</script>

View File

@ -272,7 +272,6 @@ struct NotableStringInfo : public StringInfo
{
NotableStringInfo();
NotableStringInfo(JSString *str, const StringInfo &info);
NotableStringInfo(const NotableStringInfo& info);
NotableStringInfo(NotableStringInfo &&info);
NotableStringInfo &operator=(NotableStringInfo &&info);
@ -286,10 +285,10 @@ struct NotableStringInfo : public StringInfo
return js::MemoryReportingSundriesThreshold();
}
// The amount of memory we requested for |buffer|; i.e.
// buffer = malloc(bufferSize).
size_t bufferSize;
char *buffer;
private:
NotableStringInfo(const NotableStringInfo& info) MOZ_DELETE;
};
// These measurements relate directly to the JSRuntime, and not to zones and

View File

@ -238,7 +238,7 @@ ifeq ($(OS_ARCH),WINNT)
ICU_LIB_SUFFIX=d
endif
ICU_LIB_RENAME = $(foreach libname,$(ICU_LIB_NAMES),\
cp -p intl/icu/target/lib/s$(libname)$(ICU_LIB_SUFFIX).lib intl/icu/target/lib/$(libname).lib;)
cp -p intl/icu/lib/s$(libname)$(ICU_LIB_SUFFIX).lib intl/icu/lib/$(libname).lib;)
endif
ifdef .PYMAKE
@ -254,17 +254,11 @@ endif
# - Options for genrb: -k strict parsing; -R omit collation tailoring rules.
buildicu:
# ICU's build system is full of races, so force non-parallel build.
ifdef CROSS_COMPILE
+$(ICU_MAKE) -j1 -C intl/icu/host STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-k -R -C'
endif
+$(ICU_MAKE) -j1 -C intl/icu/target STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-k -R'
+$(ICU_MAKE) -j1 -C intl/icu STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-k -R'
$(ICU_LIB_RENAME)
distclean clean::
ifdef CROSS_COMPILE
$(call SUBMAKE,$@,intl/icu/host)
endif
$(call SUBMAKE,$@,intl/icu/target)
$(call SUBMAKE,$@,intl/icu)
endif
endif
@ -274,14 +268,18 @@ endif
#############################################
# The "find any vanilla new/new[] calls" script is tailored to Linux, so
# only run it there. That should be enough to catch any such calls that
# creep in.
check-vanilla-new:
$(srcdir)/config/find_vanilla_new_calls $(LIBRARY)
# check_vanilla_allocations.py is tailored to Linux, so only run it there.
# That should be enough to catch any problems.
check-vanilla-allocations:
$(PYTHON) $(srcdir)/config/check_vanilla_allocations.py $(REAL_LIBRARY)
# The "aggressive" variant will likely fail on some compiler/platform
# combinations, but is worth running by hand every once in a while.
check-vanilla-allocations-aggressive:
$(PYTHON) $(srcdir)/config/check_vanilla_allocations.py --aggressive $(REAL_LIBRARY)
ifeq ($(OS_ARCH),Linux)
check:: check-vanilla-new
check:: check-vanilla-allocations
endif
# Help ensure that the number of OOM errors in SpiderMonkey doesn't increase.

1
js/src/aclocal.m4 vendored
View File

@ -11,7 +11,6 @@ builtin(include, build/autoconf/ccache.m4)dnl
builtin(include, build/autoconf/wrapper.m4)dnl
builtin(include, build/autoconf/pkg.m4)dnl
builtin(include, build/autoconf/nspr.m4)dnl
builtin(include, build/autoconf/codeset.m4)dnl
builtin(include, build/autoconf/altoptions.m4)dnl
builtin(include, build/autoconf/mozprog.m4)dnl
builtin(include, build/autoconf/mozheader.m4)dnl

View File

@ -1,24 +0,0 @@
# codeset.m4 serial AM1 (gettext-0.10.40)
dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License. As a special exception to the GNU General
dnl Public License, this file may be distributed as part of a program
dnl that contains a configuration script generated by Autoconf, under
dnl the same distribution terms as the rest of that program.
dnl From Bruno Haible.
AC_DEFUN([AM_LANGINFO_CODESET],
[
AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset,
[AC_TRY_LINK([#include <langinfo.h>],
[char* cs = nl_langinfo(CODESET);],
am_cv_langinfo_codeset=yes,
am_cv_langinfo_codeset=no)
])
if test $am_cv_langinfo_codeset = yes; then
AC_DEFINE(HAVE_LANGINFO_CODESET, 1,
[Define if you have <langinfo.h> and nl_langinfo(CODESET).])
HAVE_LANGINFO_CODESET=1
fi
])

View File

@ -0,0 +1,159 @@
# vim: set ts=8 sts=4 et sw=4 tw=79:
# 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/.
#----------------------------------------------------------------------------
# All heap allocations in SpiderMonkey must go through js_malloc, js_calloc,
# js_realloc, and js_free. This is so that any embedder who uses a custom
# allocator (by defining JS_USE_CUSTOM_ALLOCATOR) will see all heap allocation
# go through that custom allocator.
#
# Therefore, the presence of any calls to "vanilla" allocation/free functions
# (e.g. malloc(), free()) is a bug.
#
# This script checks for the presence of such disallowed vanilla
# allocation/free function in SpiderMonkey when it's built as a library. It
# relies on |nm| from the GNU binutils, and so only works on Linux, but one
# platform is good enough to catch almost all violations.
#
# This checking is only 100% reliable in a JS_USE_CUSTOM_ALLOCATOR build in
# which the default definitions of js_malloc et al (in Utility.h) -- which call
# malloc et al -- are replaced with empty definitions. This is because the
# presence and possible inlining of the default js_malloc et al can cause
# malloc/calloc/realloc/free calls show up in unpredictable places.
#
# Unfortunately, that configuration cannot be tested on Mozilla's standard
# testing infrastructure. Instead, by default this script only tests that none
# of the other vanilla allocation/free functions (operator new, memalign, etc)
# are present. If given the --aggressive flag, it will also check for
# malloc/calloc/realloc/free.
#
# Note: We don't check for |operator delete| and |operator delete[]|. These
# can be present somehow due to virtual destructors, but this is not too
# because vanilla delete/delete[] calls don't make sense without corresponding
# vanilla new/new[] calls, and any explicit calls will be caught by Valgrind's
# mismatched alloc/free checking.
#----------------------------------------------------------------------------
from __future__ import print_function
import argparse
import re
import subprocess
import sys
# The obvious way to implement this script is to search for occurrences of
# malloc et al, succeed if none are found, and fail is some are found.
# However, "none are found" does not necessarily mean "none are present" --
# this script could be buggy. (Or the output format of |nm| might change in
# the future.)
#
# So jsutil.cpp deliberately contains a (never-called) function that contains a
# single use of all the vanilla allocation/free functions. And this script
# fails if it (a) finds uses of those functions in files other than jsutil.cpp,
# *or* (b) fails to find them in jsutil.cpp.
# Tracks overall success of the test.
has_failed = False
def fail(msg):
print('TEST-UNEXPECTED-FAIL | check_vanilla_allocations.py |', msg)
global has_failed
has_failed = True
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--aggressive', action='store_true',
help='also check for malloc, calloc, realloc and free')
parser.add_argument('file', type=str,
help='name of the file to check')
args = parser.parse_args()
# Run |nm|. Options:
# -u: show only undefined symbols
# -C: demangle symbol names
# -l: show a filename and line number for each undefined symbol
cmd = ['nm', '-u', '-C', '-l', args.file]
lines = subprocess.check_output(cmd, universal_newlines=True,
stderr=subprocess.PIPE).split('\n')
# alloc_fns contains all the vanilla allocation/free functions that we look
# for. Regexp chars are escaped appropriately.
alloc_fns = [
# Matches |operator new(unsigned T)|, where |T| is |int| or |long|.
r'operator new\(unsigned',
# Matches |operator new[](unsigned T)|, where |T| is |int| or |long|.
r'operator new\[\]\(unsigned',
r'memalign',
# These two aren't available on all Linux configurations.
#r'posix_memalign',
#r'aligned_alloc',
r'valloc',
r'strdup'
]
if args.aggressive:
alloc_fns += [
r'malloc',
r'calloc',
r'realloc',
r'free'
]
# This is like alloc_fns, but regexp chars are not escaped.
alloc_fns_unescaped = [fn.translate(None, r'\\') for fn in alloc_fns]
# This regexp matches the relevant lines in the output of |nm|, which look
# like the following.
#
# U malloc /path/to/objdir/dist/include/js/Utility.h:142
#
alloc_fns_re = r'U (' + r'|'.join(alloc_fns) + r').*\/([\w\.]+):(\d+)$'
# This tracks which allocation/free functions have been seen in jsutil.cpp.
jsutil_cpp = set([])
for line in lines:
m = re.search(alloc_fns_re, line)
if m is None:
continue
fn = m.group(1)
filename = m.group(2)
linenum = m.group(3)
if filename == 'jsutil.cpp':
jsutil_cpp.add(fn)
else:
# An allocation is present in a non-special file. Fail!
fail("'" + fn + "' present at " + filename + ':' + linenum)
# Check that all functions we expect are used in jsutil.cpp. (This will
# fail if the function-detection code breaks at any point.)
for fn in alloc_fns_unescaped:
if fn not in jsutil_cpp:
fail("'" + fn + "' isn't used as expected in jsutil.cpp")
else:
jsutil_cpp.remove(fn)
# This should never happen, but check just in case.
if jsutil_cpp:
fail('unexpected allocation fns used in jsutil.cpp: ' +
', '.join(jsutil_cpp))
if has_failed:
sys.exit(1)
print('TEST-PASS | check_vanilla_allocations.py | ok')
sys.exit(0)
if __name__ == '__main__':
main()

View File

@ -1,80 +0,0 @@
# /bin/bash
#----------------------------------------------------------------------------
# We must avoid using the vanilla new/new[] operators (and consequently, the
# vanilla delete/delete[] operators) in SpiderMonkey, see bug 624878 for why.
#
# This script:
# - Detects if any of the vanilla new/new[] operators are used in a file.
# Its exit code is 1 if it found some, and 0 if it didn't.
# - Doesn't detect delete/delete[] because it appears they can be present
# somehow due to virtual destructors, but this is ok because vanilla
# delete/delete[] calls don't make sense without corresponding new/new[]
# calls, and any explicit calls will be caught by Valgrind's mismatched
# alloc/free checking.
# - Doesn't detect the 'nothrow' variants, which are ok but probably still
# best avoided.
# - Is designed to only run on Linux (though it may also work on Mac); one
# platform will be enough to catch any violations.
#
# If this script fails:
# - You need to find the uses of vanilla new/delete and replace them with
# {js::OffTheBooks,JSContext,JSRuntime}::{new_,/array_new}.
# - Run this script on each of the .o files, that should narrow it down.
# - After that, one way to find them is to run 'objdump -r -C' on the
# relevant .o files. For example, you might search for 'operator new' and
# find a record like this:
#
# RELOCATION RECORDS FOR [.text._ZN3JSC14ExecutablePool6createEj]:
# OFFSET TYPE VALUE
# 00000009 R_386_PC32 __i686.get_pc_thunk.bx
# 0000000f R_386_GOTPC _GLOBAL_OFFSET_TABLE_
# 0000001b R_386_PLT32 operator new(unsigned int)
# 0000002e R_386_PC32 JSC::ExecutablePool::ExecutablePool(unsigned int)
# 0000004a R_386_PC32 JSC::ExecutablePool::~ExecutablePool()
# 00000052 R_386_PLT32 operator delete(void*)
#
# This says that vanilla 'new' and 'delete' are both used in
# JSC::ExecutablePool::create(unsigned int). This doesn't always work,
# though. (Nb: use 'c++filt' to demangle names like
# _ZN3JSC14ExecutablePool6createEj.)
#
# If that doesn't work, use grep.
#----------------------------------------------------------------------------
if [ -z $1 ] ; then
echo "usage: find_vanilla_new_calls <file>"
exit 1
fi
file=$1
if [ ! -f $file ] ; then
echo "TEST-UNEXPECTED-FAIL | find_vanilla_new_calls | file '$file' not found"
exit 1
fi
tmpfile1=`mktemp`
tmpfile2=`mktemp`
nm -C $file > $tmpfile1
# Need to double-escape '[' and ']' to stop grep from interpreting them
# specially.
grep '^operator new(unsigned int)' $tmpfile1 >> $tmpfile2
grep '^operator new(unsigned long)' $tmpfile1 >> $tmpfile2
grep '^operator new\\[\\](unsigned int)' $tmpfile1 >> $tmpfile2
grep '^operator new\\[\\](unsigned long)' $tmpfile1 >> $tmpfile2
rm -f $tmpfile1
if [ -s $tmpfile2 ] ; then
echo "TEST-UNEXPECTED-FAIL | find_vanilla_new_calls | found calls are listed below"
cat $tmpfile2
echo
rm -f $tmpfile2
exit 1
fi
echo "TEST-PASS | find_vanilla_new_calls | ok"
echo
exit 0

View File

@ -2573,8 +2573,6 @@ dnl AC_CHECK_LIB(bind, res_ninit, AC_DEFINE(HAVE_RES_NINIT),
dnl AC_CHECK_LIB(resolv, res_ninit, AC_DEFINE(HAVE_RES_NINIT)))
fi
AM_LANGINFO_CODESET
AC_LANG_C
dnl **********************
@ -4198,7 +4196,7 @@ if test -n "$ENABLE_INTL_API"; then
*)
AC_MSG_ERROR([ECMAScript Internationalization API is not yet supported on this platform])
esac
MOZ_ICU_LIBS='$(call EXPAND_LIBNAME_PATH,$(ICU_LIB_NAMES),$(DEPTH)/intl/icu/target/lib)'
MOZ_ICU_LIBS='$(call EXPAND_LIBNAME_PATH,$(ICU_LIB_NAMES),$(DEPTH)/intl/icu/lib)'
fi
fi
@ -4228,94 +4226,33 @@ if test -n "$ENABLE_INTL_API" -a -z "$MOZ_NATIVE_ICU"; then
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_REGULAR_EXPRESSIONS"
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_BREAK_ITERATION"
ICU_CROSS_BUILD_OPT=""
ICU_SRCDIR=""
if test "$HOST_OS_ARCH" = "WINNT"; then
ICU_SRCDIR="--srcdir=$(cd $srcdir/../../intl/icu/source; pwd -W)"
fi
if test "$CROSS_COMPILE"; then
# Building host tools. It is necessary to build target binary.
case "$HOST_OS_ARCH" in
Darwin)
ICU_TARGET=MacOSX
;;
Linux)
ICU_TARGET=Linux
;;
WINNT)
ICU_TARGET=MSYS/MSVC
;;
*bsd*|dragonfly*)
ICU_TARGET=BSD
;;
esac
# Remove _DEPEND_CFLAGS from HOST_FLAGS to avoid configure error
HOST_ICU_CFLAGS="$HOST_CFLAGS"
HOST_ICU_CXXFLAGS="$HOST_CXXFLAGS"
HOST_ICU_CFLAGS=`echo $HOST_ICU_CFLAGS | sed "s|$_DEPEND_CFLAGS||g"`
HOST_ICU_CXXFLAGS=`echo $HOST_ICU_CFXXLAGS | sed "s|$_DEPEND_CFLAGS||g"`
# ICU requires RTTI
if test "$GNU_CC"; then
HOST_ICU_CXXFLAGS=`echo $HOST_ICU_CXXFLAGS | sed 's|-fno-rtti|-frtti|g'`
elif test "$_MSC_VER"; then
HOST_ICU_CXXFLAGS=`echo $HOST_ICU_CXXFLAGS | sed 's|-GR-|-GR|g'`
fi
HOST_ICU_BUILD_OPTS=""
if test -n "$MOZ_DEBUG"; then
HOST_ICU_BUILD_OPTS="$HOST_ICU_BUILD_OPTS --enable-debug"
fi
abs_srcdir=`(cd $srcdir; pwd)`
mkdir -p $_objdir/intl/icu/host
(cd $_objdir/intl/icu/host
MOZ_SUBCONFIGURE_WRAP([.],[
CC="$HOST_CC" CXX="$HOST_CXX" LD="$HOST_LD" \
CFLAGS="$HOST_ICU_CFLAGS $HOST_OPTIMIZE_FLAGS" \
CPPFLAGS="$ICU_CPPFLAGS" \
CXXFLAGS="$HOST_ICU_CXXFLAGS $HOST_OPTIMZIE_FLAGS" \
$SHELL $abs_srcdir/../../intl/icu/source/runConfigureICU \
$HOST_ICU_BUILD_OPTS \
$ICU_TARGET \
dnl Shell quoting is fun.
${ICU_SRCDIR+"$ICU_SRCDIR"} \
--enable-static --disable-shared \
--enable-extras=no --enable-icuio=no --enable-layout=no \
--enable-tests=no --enable-samples=no || exit 1
])
) || exit 1
# generate config/icucross.mk
$GMAKE -C $_objdir/intl/icu/host/ config/icucross.mk
# --with-cross-build requires absolute path
ICU_HOST_PATH=`cd $_objdir/intl/icu/host && pwd`
ICU_CROSS_BUILD_OPT="--with-cross-build=$ICU_HOST_PATH"
fi
# Set OS dependent options for ICU
case "$OS_TARGET" in
Darwin)
ICU_TARGET=MacOSX
;;
Linux)
ICU_TARGET=Linux
;;
WINNT)
ICU_TARGET=MSYS/MSVC
ICU_SRCDIR="--srcdir=$(cd $srcdir/../../intl/icu/source; pwd -W)"
;;
DragonFly|FreeBSD|NetBSD|OpenBSD)
ICU_TARGET=BSD
;;
esac
# To reduce library size, use static linking
ICU_LINK_OPTS="--enable-static --disable-shared"
# Force the ICU static libraries to be position independent code
ICU_CFLAGS="$DSO_PIC_CFLAGS $CFLAGS"
ICU_CXXFLAGS="$DSO_PIC_CFLAGS $CXXFLAGS"
ICU_CFLAGS="$DSO_PIC_CFLAGS"
ICU_CXXFLAGS="$DSO_PIC_CFLAGS"
ICU_BUILD_OPTS=""
if test -n "$MOZ_DEBUG" -o "MOZ_DEBUG_SYMBOLS"; then
ICU_CFLAGS="$ICU_CFLAGS $MOZ_DEBUG_FLAGS"
ICU_CXXFLAGS="$ICU_CXXFLAGS $MOZ_DEBUG_FLAGS"
ICU_LDFLAGS="$MOZ_DEBUG_LDFLAGS"
if test -z "$MOZ_DEBUG"; then
# To generate debug symbols, it requires MOZ_DEBUG_FLAGS.
# But, not debug build.
ICU_CFLAGS="$ICU_CFLAGS -UDEBUG -DNDEBUG"
ICU_CXXFLAGS="$ICU_CXXFLAGS -UDEBUG -DNDEBUG"
else
ICU_BUILD_OPTS="$ICU_BUILD_OPTS --enable-debug"
fi
if test -n "$MOZ_DEBUG"; then
ICU_BUILD_OPTS="$ICU_BUILD_OPTS --enable-debug"
fi
if test -z "$MOZ_OPTIMIZE"; then
ICU_BUILD_OPTS="$ICU_BUILD_OPTS --disable-release"
@ -4324,43 +4261,21 @@ if test -n "$ENABLE_INTL_API" -a -z "$MOZ_NATIVE_ICU"; then
ICU_CXXFLAGS="$ICU_CXXFLAGS $MOZ_OPTIMIZE_FLAGS"
fi
if test "$am_cv_langinfo_codeset" = "no"; then
# ex. Android
ICU_CPPFLAGS="$ICU_CPPFLAGS -DU_HAVE_NL_LANGINFO_CODESET=0"
fi
# ICU requires RTTI
if test "$GNU_CC"; then
ICU_CXXFLAGS=`echo $ICU_CXXFLAGS | sed 's|-fno-rtti|-frtti|g'`
else
if test "$_MSC_VER"; then
ICU_CXXFLAGS=`echo $ICU_CXXFLAGS | sed 's|-GR-|-GR|g'`
fi
fi
# We cannot use AC_OUTPUT_SUBDIRS since ICU tree is out of spidermonkey.
# When using AC_OUTPUT_SUBDIRS, objdir of ICU is out of objdir
# due to relative path.
# If building ICU moves into root of mozilla tree, we can use
# AC_OUTPUT_SUBDIR instead.
mkdir -p $_objdir/intl/icu/target
(cd $_objdir/intl/icu/target
abs_srcdir=`(cd $srcdir; pwd)`
mkdir -p $_objdir/intl/icu
(cd $_objdir/intl/icu
MOZ_SUBCONFIGURE_WRAP([.],[
AR="$AR" CC="$CC" CXX="$CXX" LD="$LD" \
ARFLAGS="$ARFLAGS" \
CPPFLAGS="$ICU_CPPFLAGS $CPPFLAGS" \
CFLAGS="$ICU_CFLAGS" \
CXXFLAGS="$ICU_CXXFLAGS" \
LDFLAGS="$ICU_LDFLAGS $LDFLAGS" \
$SHELL $_topsrcdir/../../intl/icu/source/configure \
$ICU_BUILD_OPTS \
$ICU_CROSS_BUILD_OPT \
$ICU_LINK_OPTS \
${ICU_SRCDIR+"$ICU_SRCDIR"} \
--build=$build --host=$target \
--disable-extras --disable-icuio --disable-layout \
--disable-tests --disable-samples || exit 1
])
CC="$CC" CXX="$CXX" \
CFLAGS="$ICU_CFLAGS" CPPFLAGS="$ICU_CPPFLAGS" CXXFLAGS="$ICU_CXXFLAGS" \
$SHELL $abs_srcdir/../../intl/icu/source/runConfigureICU \
$ICU_BUILD_OPTS \
$ICU_TARGET \
$ICU_LINK_OPTS \
dnl Shell quoting is fun.
${ICU_SRCDIR+"$ICU_SRCDIR"} \
--enable-extras=no --enable-icuio=no --enable-layout=no \
--enable-tests=no --enable-samples=no || exit 1
])
) || exit 1
fi

View File

@ -251,6 +251,9 @@ BaselineCompiler::compile()
bytecodeMap[script->nTypeSets] = 0;
}
if (script->compartment()->debugMode())
baselineScript->setDebugMode();
return Method_Compiled;
}

View File

@ -746,6 +746,10 @@ BaselineScript::toggleDebugTraps(JSScript *script, jsbytecode *pc)
{
JS_ASSERT(script->baselineScript() == this);
// Only scripts compiled for debug mode have toggled calls.
if (!debugMode())
return;
SrcNoteLineScanner scanner(script->notes(), script->lineno);
JSRuntime *rt = script->runtimeFromMainThread();

View File

@ -132,7 +132,11 @@ struct BaselineScript
// Flag set when the script contains any writes to its on-stack
// (rather than call object stored) arguments.
MODIFIES_ARGUMENTS = 1 << 2
MODIFIES_ARGUMENTS = 1 << 2,
// Flag set when compiled for use for debug mode. Handles various
// Debugger hooks and compiles toggled calls for traps.
DEBUG_MODE = 1 << 3
};
private:
@ -201,6 +205,13 @@ struct BaselineScript
return flags_ & MODIFIES_ARGUMENTS;
}
void setDebugMode() {
flags_ |= DEBUG_MODE;
}
bool debugMode() const {
return flags_ & DEBUG_MODE;
}
uint32_t prologueOffset() const {
return prologueOffset_;
}

View File

@ -1560,7 +1560,7 @@ ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind)
cx->asJSContext()->runtime()->gcHelperThread.waitBackgroundSweepEnd();
}
} else {
#ifdef JS_THREADSAFE
#ifdef JS_WORKER_THREADS
/*
* If we're off the main thread, we try to allocate once and return
* whatever value we get. First, though, we need to ensure the main
@ -4149,7 +4149,7 @@ AutoTraceSession::AutoTraceSession(JSRuntime *rt, js::HeapState heapState)
if (rt->exclusiveThreadsPresent()) {
// Lock the worker thread state when changing the heap state in the
// presence of exclusive threads, to avoid racing with refillFreeList.
#ifdef JS_THREADSAFE
#ifdef JS_WORKER_THREADS
AutoLockWorkerThreadState lock(*rt->workerThreadState);
rt->heapState = heapState;
#else
@ -4165,7 +4165,7 @@ AutoTraceSession::~AutoTraceSession()
JS_ASSERT(runtime->isHeapBusy());
if (runtime->exclusiveThreadsPresent()) {
#ifdef JS_THREADSAFE
#ifdef JS_WORKER_THREADS
AutoLockWorkerThreadState lock(*runtime->workerThreadState);
runtime->heapState = prevState;

View File

@ -603,9 +603,11 @@ class types::CompilerConstraintList
public:
CompilerConstraintList(jit::TempAllocator &alloc)
: constraints(alloc),
frozenScripts(alloc),
failed_(false)
: failed_(false)
#ifdef JS_ION
, constraints(alloc)
, frozenScripts(alloc)
#endif
{}
void add(CompilerConstraint *constraint) {

View File

@ -161,6 +161,49 @@ JS_Assert(const char *s, const char *file, int ln)
MOZ_CRASH();
}
#ifdef __linux__
#include <malloc.h>
#include <stdlib.h>
namespace js {
// This function calls all the vanilla heap allocation functions. It is never
// called, and exists purely to help config/check_vanilla_allocations.py. See
// that script for more details.
extern void
AllTheNonBasicVanillaNewAllocations()
{
// posix_memalign and aligned_alloc aren't available on all Linux
// configurations.
//char *q;
//posix_memalign((void**)&q, 16, 16);
intptr_t p =
intptr_t(malloc(16)) +
intptr_t(calloc(1, 16)) +
intptr_t(realloc(nullptr, 16)) +
intptr_t(new char) +
intptr_t(new char) +
intptr_t(new char) +
intptr_t(new char[16]) +
intptr_t(memalign(16, 16)) +
//intptr_t(q) +
//intptr_t(aligned_alloc(16, 16)) +
intptr_t(valloc(4096)) +
intptr_t(strdup("dummy"));
printf("%u\n", uint32_t(p)); // make sure |p| is not optimized away
free((int*)p); // this would crash if ever actually called
MOZ_CRASH();
}
} // namespace js
#endif // __linux__
#ifdef JS_BASIC_STATS
#include <math.h>

View File

@ -94,14 +94,13 @@ InefficientNonFlatteningStringHashPolicy::match(const JSString *const &k, const
namespace JS {
NotableStringInfo::NotableStringInfo()
: bufferSize(0),
buffer(0)
: buffer(0)
{}
NotableStringInfo::NotableStringInfo(JSString *str, const StringInfo &info)
: StringInfo(info)
{
bufferSize = Min(str->length() + 1, size_t(4096));
size_t bufferSize = Min(str->length() + 1, size_t(4096));
buffer = js_pod_malloc<char>(bufferSize);
if (!buffer) {
MOZ_CRASH("oom");
@ -123,17 +122,6 @@ NotableStringInfo::NotableStringInfo(JSString *str, const StringInfo &info)
PutEscapedString(buffer, bufferSize, chars, str->length(), /* quote */ 0);
}
NotableStringInfo::NotableStringInfo(const NotableStringInfo& info)
: StringInfo(info),
bufferSize(info.bufferSize)
{
buffer = js_pod_malloc<char>(bufferSize);
if (!buffer)
MOZ_CRASH("oom");
strcpy(buffer, info.buffer);
}
NotableStringInfo::NotableStringInfo(NotableStringInfo &&info)
: StringInfo(Move(info))
{

View File

@ -847,7 +847,7 @@ js::CurrentThreadCanAccessZone(Zone *zone)
void
JSRuntime::assertCanLock(RuntimeLock which)
{
#ifdef JS_THREADSAFE
#ifdef JS_WORKER_THREADS
// In the switch below, each case falls through to the one below it. None
// of the runtime locks are reentrant, and when multiple locks are acquired
// it must be done in the order below.

View File

@ -8525,6 +8525,16 @@ CSSParserImpl::ParseCounterData(nsCSSProperty aPropID)
nsCSSValuePairList *cur = value.SetPairListValue();
for (;;) {
// check for "none", "default" and the CSS-wide keywords,
// which can't be used as counter names
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
if (keyword == eCSSKeyword_inherit ||
keyword == eCSSKeyword_default ||
keyword == eCSSKeyword_none ||
keyword == eCSSKeyword_unset ||
keyword == eCSSKeyword_initial) {
return false;
}
cur->mXValue.SetStringValue(mToken.mIdent, eCSSUnit_Ident);
if (!GetToken(true)) {
break;

View File

@ -672,10 +672,15 @@ nsComputedDOMStyle::GetPropertyCSSValue(const nsAString& aPropertyName, ErrorRes
while (topWithPseudoElementData->GetParent()->HasPseudoElementData()) {
topWithPseudoElementData = topWithPseudoElementData->GetParent();
}
NS_ASSERTION(nsCSSPseudoElements::PseudoElementContainsElements(
topWithPseudoElementData->GetPseudoType()),
"we should be in a pseudo-element that is expected to "
"contain elements");
nsCSSPseudoElements::Type pseudo =
topWithPseudoElementData->GetPseudoType();
nsIAtom* pseudoAtom = nsCSSPseudoElements::GetPseudoAtom(pseudo);
nsAutoString assertMsg(
NS_LITERAL_STRING("we should be in a pseudo-element that is expected to contain elements ("));
assertMsg.Append(nsDependentString(pseudoAtom->GetUTF16String()));
assertMsg.Append(NS_LITERAL_STRING(")"));
NS_ASSERTION(nsCSSPseudoElements::PseudoElementContainsElements(pseudo),
NS_LossyConvertUTF16toASCII(assertMsg).get());
}
#endif
// Need to resolve a style context

View File

@ -2321,7 +2321,7 @@ var gCSSProperties = {
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "foo 1", "bar", "foo 3 bar baz 2", "\\32 1", "-\\32 1", "-c 1", "\\32 1", "-\\32 1", "\\2 1", "-\\2 1", "-c 1", "\\2 1", "-\\2 1", "-\\7f \\9e 1" ],
invalid_values: []
invalid_values: [ "none foo", "none foo 3", "foo none", "foo 3 none" ]
},
"counter-reset": {
domProp: "counterReset",
@ -2329,7 +2329,7 @@ var gCSSProperties = {
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "foo 1", "bar", "foo 3 bar baz 2", "\\32 1", "-\\32 1", "-c 1", "\\32 1", "-\\32 1", "\\2 1", "-\\2 1", "-c 1", "\\2 1", "-\\2 1", "-\\7f \\9e 1" ],
invalid_values: []
invalid_values: [ "none foo", "none foo 3", "foo none", "foo 3 none" ]
},
"cursor": {
domProp: "cursor",

View File

@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system.
The nestegg git repository is: git://github.com/kinetiknz/nestegg.git
The git commit ID used was 26d262114af191b6654cbd5d24ec02e4b6bdb1cd.
The git commit ID used was 0851279ab11f5b2e9e8154ce7880b687b564c760.

View File

@ -140,6 +140,8 @@ typedef struct {
double rate; /**< Sampling rate in Hz. */
unsigned int channels; /**< Number of audio channels. */
unsigned int depth; /**< Bits per sample. */
uint64_t codec_delay; /**< Nanoseconds that must be discarded from the start. */
uint64_t seek_preroll;/**< Nanoseconds that must be discarded after a seek. */
} nestegg_audio_params;
/** Logging callback function pointer. */
@ -321,6 +323,14 @@ int nestegg_packet_count(nestegg_packet * packet, unsigned int * count);
int nestegg_packet_data(nestegg_packet * packet, unsigned int item,
unsigned char ** data, size_t * length);
/** Returns discard_padding for given packet
@param packet Packet initialized by #nestegg_read_packet.
@param discard_padding pointer to store discard padding in.
@retval 0 Success.
@retval -1 Error. */
int nestegg_packet_discard_padding(nestegg_packet * packet,
int64_t * discard_padding);
/** Query the presence of cues.
@param context Stream context initialized by #nestegg_init.
@retval 0 The media has no cues.

View File

@ -49,6 +49,7 @@
#define ID_BLOCK 0xa1
#define ID_BLOCK_DURATION 0x9b
#define ID_REFERENCE_BLOCK 0xfb
#define ID_DISCARD_PADDING 0x75a2
/* Tracks Elements */
#define ID_TRACKS 0x1654ae6b
@ -63,6 +64,8 @@
#define ID_LANGUAGE 0x22b59c
#define ID_CODEC_ID 0x86
#define ID_CODEC_PRIVATE 0x63a2
#define ID_CODEC_DELAY 0x56aa
#define ID_SEEK_PREROLL 0x56bb
/* Video Elements */
#define ID_VIDEO 0xe0
@ -194,6 +197,7 @@ struct info {
struct block_group {
struct ebml_type duration;
struct ebml_type reference_block;
struct ebml_type discard_padding;
};
struct cluster {
@ -230,6 +234,8 @@ struct track_entry {
struct ebml_type language;
struct ebml_type codec_id;
struct ebml_type codec_private;
struct ebml_type codec_delay;
struct ebml_type seek_preroll;
struct video video;
struct audio audio;
};
@ -305,6 +311,7 @@ struct nestegg_packet {
uint64_t track;
uint64_t timecode;
struct frame * frame;
int64_t discard_padding;
};
/* Element Descriptor */
@ -368,6 +375,7 @@ static struct ebml_element_desc ne_block_group_elements[] = {
E_SUSPEND(ID_BLOCK, TYPE_BINARY),
E_FIELD(ID_BLOCK_DURATION, TYPE_UINT, struct block_group, duration),
E_FIELD(ID_REFERENCE_BLOCK, TYPE_INT, struct block_group, reference_block),
E_FIELD(ID_DISCARD_PADDING, TYPE_INT, struct block_group, discard_padding),
E_LAST
};
@ -409,6 +417,8 @@ static struct ebml_element_desc ne_track_entry_elements[] = {
E_FIELD(ID_LANGUAGE, TYPE_STRING, struct track_entry, language),
E_FIELD(ID_CODEC_ID, TYPE_STRING, struct track_entry, codec_id),
E_FIELD(ID_CODEC_PRIVATE, TYPE_BINARY, struct track_entry, codec_private),
E_FIELD(ID_CODEC_DELAY, TYPE_UINT, struct track_entry, codec_delay),
E_FIELD(ID_SEEK_PREROLL, TYPE_UINT, struct track_entry, seek_preroll),
E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video),
E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio),
E_LAST
@ -1365,6 +1375,35 @@ ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_pac
return 1;
}
static int
ne_read_discard_padding(nestegg * ctx, nestegg_packet * pkt)
{
int r;
uint64_t id, size;
struct ebml_element_desc * element;
struct ebml_type * storage;
r = ne_peek_element(ctx, &id, &size);
if (r != 1)
return r;
if (id != ID_DISCARD_PADDING)
return 1;
element = ne_find_element(id, ctx->ancestor->node);
if (!element)
return 1;
r = ne_read_simple(ctx, element, size);
if (r != 1)
return r;
storage = (struct ebml_type *) (ctx->ancestor->data + element->offset);
pkt->discard_padding = storage->v.i;
return 1;
}
static uint64_t
ne_buf_read_id(unsigned char const * p, size_t length)
{
@ -1994,34 +2033,40 @@ nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
if (!entry)
return -1;
if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS)
if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS
&& nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
return -1;
if (ne_get_binary(entry->codec_private, &codec_private) != 0)
return -1;
p = codec_private.data;
count = *p++ + 1;
if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS) {
p = codec_private.data;
count = *p++ + 1;
if (count > 3)
return -1;
if (count > 3)
return -1;
i = 0;
total = 0;
while (--count) {
sizes[i] = ne_xiph_lace_value(&p);
total += sizes[i];
i += 1;
i = 0;
total = 0;
while (--count) {
sizes[i] = ne_xiph_lace_value(&p);
total += sizes[i];
i += 1;
}
sizes[i] = codec_private.length - total - (p - codec_private.data);
for (i = 0; i < item; ++i) {
if (sizes[i] > LIMIT_FRAME)
return -1;
p += sizes[i];
}
*data = p;
*length = sizes[item];
} else {
*data = codec_private.data;
*length = codec_private.length;
}
sizes[i] = codec_private.length - total - (p - codec_private.data);
for (i = 0; i < item; ++i) {
if (sizes[i] > LIMIT_FRAME)
return -1;
p += sizes[i];
}
*data = p;
*length = sizes[item];
return 0;
}
@ -2110,6 +2155,14 @@ nestegg_track_audio_params(nestegg * ctx, unsigned int track,
ne_get_uint(entry->audio.bit_depth, &value);
params->depth = value;
value = 0;
ne_get_uint(entry->codec_delay, &value);
params->codec_delay = value;
value = 0;
ne_get_uint(entry->seek_preroll, &value);
params->seek_preroll = value;
return 0;
}
@ -2135,6 +2188,13 @@ nestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt)
/* The only DESC_FLAG_SUSPEND fields are Blocks and SimpleBlocks, which we
handle directly. */
r = ne_read_block(ctx, id, size, pkt);
if (r != 1)
return r;
r = ne_read_discard_padding(ctx, *pkt);
if (r != 1)
return r;
return r;
}
@ -2175,6 +2235,13 @@ nestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp)
return 0;
}
int
nestegg_packet_discard_padding(nestegg_packet * pkt, int64_t * discard_padding)
{
*discard_padding = pkt->discard_padding;
return 0;
}
int
nestegg_packet_count(nestegg_packet * pkt, unsigned int * count)
{

View File

@ -14,18 +14,18 @@ if CONFIG['MOZ_REPLACE_MALLOC']:
'malloc_decls.h',
'replace_malloc.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'jemalloc_config.c',
'mozmemory_wrap.c',
]
if CONFIG['MOZ_JEMALLOC3']:
SOURCES += [
UNIFIED_SOURCES += [
'mozjemalloc_compat.c',
]
if CONFIG['MOZ_REPLACE_MALLOC']:
SOURCES += [
UNIFIED_SOURCES += [
'replace_malloc.c',
]

View File

@ -4,7 +4,7 @@
# 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/.
SOURCES += [
UNIFIED_SOURCES += [
'src/src/arena.c',
'src/src/atomic.c',
'src/src/base.c',
@ -32,7 +32,7 @@ SOURCES += [
# Only OSX needs the zone allocation implementation,
# but only if replace-malloc is not enabled.
if CONFIG['OS_TARGET'] == 'Darwin' and not CONFIG['MOZ_REPLACE_MALLOC']:
SOURCES += [
UNIFIED_SOURCES += [
'src/src/zone.c',
]

View File

@ -32,7 +32,7 @@ if CONFIG['WRAP_STL_INCLUDES']:
'msvc_throw_wrapper.cpp',
]
SOURCES += [
UNIFIED_SOURCES += [
'mozalloc.cpp',
'mozalloc_abort.cpp',
'mozalloc_oom.cpp',

View File

@ -29,8 +29,6 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.UUID;
import java.util.regex.Pattern;
@ -48,12 +46,8 @@ public final class ANRReporter extends BroadcastReceiver
private static final int TRACES_LINE_SIZE = 100;
// Size of block to use when processing traces.txt
private static final int TRACES_BLOCK_SIZE = 2000;
// we use us-ascii here because when telemetry calculates checksum
// for the ping file, it lossily converts utf-16 to ascii. therefore,
// we have to treat characters in the traces file as ascii rather than
// say utf-8. otherwise, we will get a wrong checksum
private static final String TRACES_CHARSET = "us-ascii";
private static final String PING_CHARSET = "us-ascii";
private static final String TRACES_CHARSET = "utf-8";
private static final String PING_CHARSET = "utf-8";
private static final ANRReporter sInstance = new ANRReporter();
private static int sRegisteredCount;
@ -266,11 +260,11 @@ public final class ANRReporter extends BroadcastReceiver
/*
a saved telemetry ping file consists of JSON in the following format,
{
"reason": "android-anr-report",
"slug": "<uuid-string>",
"payload": "<escaped-json-data-string>",
"checksum": "<base64-sha-256-string>"
"payload": <json-object>
}
for Android ANR, our unescaped JSON payload should look like,
for Android ANR, our JSON payload should look like,
{
"ver": 1,
"simpleMeasurements": {
@ -287,32 +281,27 @@ public final class ANRReporter extends BroadcastReceiver
*/
private static int writePingPayload(OutputStream ping,
MessageDigest checksum,
String payload) throws IOException {
byte [] data = payload.getBytes(PING_CHARSET);
checksum.update(data);
data = JSONObject.quote(payload).getBytes(PING_CHARSET);
// first and last bytes are quotes inserted by JSONObject.quote; discard them
ping.write(data, 1, data.length - 2);
return data.length - 2;
ping.write(data);
return data.length;
}
private static void fillPingHeader(OutputStream ping, MessageDigest checksum, String slug)
private static void fillPingHeader(OutputStream ping, String slug)
throws IOException {
// ping file header
byte [] data = ("{" +
"\"reason\":\"android-anr-report\"," +
"\"slug\":" + JSONObject.quote(slug) + "," +
"\"payload\":\"").getBytes(PING_CHARSET);
"\"payload\":").getBytes(PING_CHARSET);
ping.write(data);
if (DEBUG) {
Log.d(LOGTAG, "wrote ping header, size = " + String.valueOf(data.length));
}
// payload start
int size = writePingPayload(ping, checksum, ("{" +
int size = writePingPayload(ping, ("{" +
"\"ver\":1," +
"\"simpleMeasurements\":{" +
"\"uptime\":" + String.valueOf(getUptimeMins()) +
@ -392,9 +381,9 @@ public final class ANRReporter extends BroadcastReceiver
return 0;
}
// Copy the content of reader to ping and update checksum;
// Copy the content of reader to ping;
// copying stops when endPattern is found in the input stream
private static int fillPingBlock(OutputStream ping, MessageDigest checksum,
private static int fillPingBlock(OutputStream ping,
Reader reader, String endPattern)
throws IOException {
@ -409,7 +398,7 @@ public final class ANRReporter extends BroadcastReceiver
stringBlock = stringBlock.substring(0, endIndex);
}
String quoted = JSONObject.quote(stringBlock);
total += writePingPayload(ping, checksum, quoted.substring(1, quoted.length() - 1));
total += writePingPayload(ping, quoted.substring(1, quoted.length() - 1));
if (endIndex > 0) {
// End pattern already found; return now
break;
@ -418,13 +407,13 @@ public final class ANRReporter extends BroadcastReceiver
return total;
}
private static void fillPingFooter(OutputStream ping, MessageDigest checksum,
private static void fillPingFooter(OutputStream ping,
boolean haveNativeStack)
throws IOException {
// We are at the end of ANR data
int total = writePingPayload(ping, checksum, ("\"," +
int total = writePingPayload(ping, ("\"," +
"\"androidLogcat\":\""));
try {
@ -435,7 +424,7 @@ public final class ANRReporter extends BroadcastReceiver
.start();
try {
Reader procOut = new InputStreamReader(proc.getInputStream(), TRACES_CHARSET);
int size = fillPingBlock(ping, checksum, procOut, null);
int size = fillPingBlock(ping, procOut, null);
if (DEBUG) {
Log.d(LOGTAG, "wrote logcat, size = " + String.valueOf(size));
}
@ -448,25 +437,20 @@ public final class ANRReporter extends BroadcastReceiver
}
if (haveNativeStack) {
total += writePingPayload(ping, checksum, ("\"," +
"\"androidNativeStack\":\""));
total += writePingPayload(ping, ("\"," +
"\"androidNativeStack\":"));
String nativeStack = String.valueOf(getNativeStack());
int size = fillPingBlock(ping, checksum, new StringReader(nativeStack), null);
int size = writePingPayload(ping, nativeStack);
if (DEBUG) {
Log.d(LOGTAG, "wrote native stack, size = " + String.valueOf(size));
}
total += size + writePingPayload(ping, "}");
} else {
total += writePingPayload(ping, "\"}");
}
total += writePingPayload(ping, checksum, "\"}");
String base64Checksum = Base64.encodeToString(checksum.digest(), Base64.NO_WRAP);
if (DEBUG) {
Log.d(LOGTAG, "checksum: " + base64Checksum);
}
byte [] data = (
"\"," +
"\"checksum\":" + JSONObject.quote(base64Checksum) +
"}").getBytes(PING_CHARSET);
ping.write(data);
if (DEBUG) {
@ -481,8 +465,7 @@ public final class ANRReporter extends BroadcastReceiver
OutputStream ping = new BufferedOutputStream(
new FileOutputStream(pingFile), TRACES_BLOCK_SIZE);
try {
MessageDigest checksum = MessageDigest.getInstance("SHA-256");
fillPingHeader(ping, checksum, pingFile.getName());
fillPingHeader(ping, pingFile.getName());
// Traces file has the format
// ----- pid xxx at xxx -----
// Cmd line: org.mozilla.xxx
@ -494,11 +477,11 @@ public final class ANRReporter extends BroadcastReceiver
// ...
// If we end the stack dump at the first end marker,
// only Fennec stacks will be dumped
int size = fillPingBlock(ping, checksum, traces, "\n----- end");
int size = fillPingBlock(ping, traces, "\n----- end");
if (DEBUG) {
Log.d(LOGTAG, "wrote traces, size = " + String.valueOf(size));
}
fillPingFooter(ping, checksum, haveNativeStack);
fillPingFooter(ping, haveNativeStack);
if (DEBUG) {
Log.d(LOGTAG, "finished creating ping file");
}
@ -509,8 +492,6 @@ public final class ANRReporter extends BroadcastReceiver
releaseNativeStack();
}
}
} catch (GeneralSecurityException e) {
Log.w(LOGTAG, e);
} catch (IOException e) {
Log.w(LOGTAG, e);
}

View File

@ -3407,8 +3407,8 @@ pref("font.alias-list", "sans,sans-serif,serif,monospace");
// ar
pref("font.name.serif.el", "Droid Serif");
pref("font.name.sans-serif.el", "Fira Sans OT");
pref("font.name.monospace.el", "Fira Mono OT");
pref("font.name.sans-serif.el", "Roboto"); // To be updated once the Greek letters in Fira are revised
pref("font.name.monospace.el", "Droid Sans Mono");
pref("font.name.serif.he", "Charis SIL Compact");
pref("font.name.sans-serif.he", "Fira Sans OT");

Some files were not shown because too many files have changed in this diff Show More