Merge mozilla-central and inbound
159
config/check_vanilla_allocations.py
Normal 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()
|
||||
|
@ -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
|
@ -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)
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -668,6 +668,8 @@ public:
|
||||
|
||||
void MozSetFileNameArray(const Sequence< nsString >& aFileNames);
|
||||
|
||||
HTMLInputElement* GetOwnerNumberControl();
|
||||
|
||||
bool MozIsTextField(bool aExcludePassword);
|
||||
|
||||
nsIEditor* GetEditor();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
10
content/html/content/test/file_ignoreuserfocus.html
Normal 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>
|
@ -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 ],
|
||||
|
@ -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]
|
||||
|
146
content/html/content/test/test_ignoreuserfocus.html
Normal 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>
|
18
content/html/document/reftests/bug917595-1-ref.html
Normal 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>
|
BIN
content/html/document/reftests/bug917595-exif-rotated.jpg
Normal file
After Width: | Height: | Size: 89 KiB |
18
content/html/document/reftests/bug917595-iframe-1.html
Normal 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>
|
BIN
content/html/document/reftests/bug917595-pixel-rotated.jpg
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
content/html/document/reftests/bug917595-unrotated.jpg
Normal file
After Width: | Height: | Size: 89 KiB |
@ -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
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -94,6 +94,8 @@ protected:
|
||||
void ResetZoomLevel();
|
||||
float GetZoomLevel();
|
||||
|
||||
void UpdateSizeFromLayout();
|
||||
|
||||
enum eModeClasses {
|
||||
eNone,
|
||||
eShrinkToFit,
|
||||
|
@ -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))) {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -1057,7 +1057,7 @@ protected:
|
||||
{
|
||||
MOZ_COUNT_CTOR(MediaStreamGraph);
|
||||
}
|
||||
~MediaStreamGraph()
|
||||
virtual ~MediaStreamGraph()
|
||||
{
|
||||
MOZ_COUNT_DTOR(MediaStreamGraph);
|
||||
}
|
||||
|
@ -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.
|
||||
/**
|
||||
|
@ -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))) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -47,7 +47,7 @@ EXPORTS.mozilla += [
|
||||
'LoadContext.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'LoadContext.cpp',
|
||||
'nsAboutRedirector.cpp',
|
||||
'nsDefaultURIFixup.cpp',
|
||||
|
@ -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___
|
||||
|
@ -8,7 +8,7 @@ EXPORTS += [
|
||||
'nsSHEntryShared.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'nsSHEntry.cpp',
|
||||
'nsSHEntryShared.cpp',
|
||||
'nsSHistory.cpp',
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
|
@ -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 || "";
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
BIN
image/test/mochitest/bug900200-ref.png
Normal file
After Width: | Height: | Size: 660 B |
BIN
image/test/mochitest/bug900200.png
Normal file
After Width: | Height: | Size: 840 B |
BIN
image/test/mochitest/clear.gif
Normal file
After Width: | Height: | Size: 321 B |
BIN
image/test/mochitest/clear.png
Normal file
After Width: | Height: | Size: 622 B |
BIN
image/test/mochitest/clear2-results.gif
Normal file
After Width: | Height: | Size: 177 B |
BIN
image/test/mochitest/clear2.gif
Normal file
After Width: | Height: | Size: 219 B |
28
image/test/mochitest/green-background.html
Normal 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>
|
BIN
image/test/mochitest/green.png
Normal file
After Width: | Height: | Size: 255 B |
BIN
image/test/mochitest/grey.png
Normal file
After Width: | Height: | Size: 256 B |
BIN
image/test/mochitest/keep.gif
Normal file
After Width: | Height: | Size: 321 B |
BIN
image/test/mochitest/keep.png
Normal file
After Width: | Height: | Size: 622 B |
@ -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]
|
||||
|
BIN
image/test/mochitest/over.png
Normal file
After Width: | Height: | Size: 525 B |
BIN
image/test/mochitest/restore-previous.gif
Normal file
After Width: | Height: | Size: 457 B |
BIN
image/test/mochitest/restore-previous.png
Normal file
After Width: | Height: | Size: 622 B |
BIN
image/test/mochitest/source.png
Normal file
After Width: | Height: | Size: 525 B |
157
image/test/mochitest/test_animation_operators.html
Normal 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>
|
@ -38,7 +38,7 @@ function forceDecode() {
|
||||
}
|
||||
|
||||
function startTimer() {
|
||||
const delay = 1000;
|
||||
const delay = 10000;
|
||||
setTimeout("document.documentElement.className = '';", delay);
|
||||
}
|
||||
</script>
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
])
|
159
js/src/config/check_vanilla_allocations.py
Normal 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()
|
||||
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -251,6 +251,9 @@ BaselineCompiler::compile()
|
||||
bytecodeMap[script->nTypeSets] = 0;
|
||||
}
|
||||
|
||||
if (script->compartment()->debugMode())
|
||||
baselineScript->setDebugMode();
|
||||
|
||||
return Method_Compiled;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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',
|
||||
]
|
||||
|
||||
|
@ -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',
|
||||
]
|
||||
|
||||
|
@ -32,7 +32,7 @@ if CONFIG['WRAP_STL_INCLUDES']:
|
||||
'msvc_throw_wrapper.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'mozalloc.cpp',
|
||||
'mozalloc_abort.cpp',
|
||||
'mozalloc_oom.cpp',
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|