Merge mozilla-central to autoland

--HG--
extra : rebase_source : dcccfd463c74743c692814695c9a7f0cba61e3ee
This commit is contained in:
Carsten "Tomcat" Book 2017-03-09 11:26:20 +01:00
Родитель 8eb76e20d9 6d06361383
Коммит 45b510057b
63 изменённых файлов: 1103 добавлений и 1415 удалений

Просмотреть файл

@ -76,6 +76,7 @@ FormAutofillParent.prototype = {
this._profileStore.initialize();
Services.obs.addObserver(this, "advanced-pane-loaded", false);
Services.ppmm.addMessageListener("FormAutofill:SaveProfile", this);
// Observing the pref and storage changes
Services.prefs.addObserver(ENABLED_PREF, this, false);
@ -178,9 +179,18 @@ FormAutofillParent.prototype = {
*/
receiveMessage({name, data, target}) {
switch (name) {
case "FormAutofill:GetProfiles":
case "FormAutofill:GetProfiles": {
this._getProfiles(data, target);
break;
}
case "FormAutofill:SaveProfile": {
if (data.guid) {
this.getProfileStore().update(data.guid, data.profile);
} else {
this.getProfileStore().add(data.profile);
}
break;
}
}
},
@ -207,6 +217,7 @@ FormAutofillParent.prototype = {
}
Services.ppmm.removeMessageListener("FormAutofill:GetProfiles", this);
Services.ppmm.removeMessageListener("FormAutofill:SaveProfile", this);
Services.obs.removeObserver(this, "advanced-pane-loaded");
Services.prefs.removeObserver(ENABLED_PREF, this);
},

Просмотреть файл

@ -15,6 +15,11 @@ const PREF_AUTOFILL_ENABLED = "browser.formautofill.enabled";
const BUNDLE_URI = "chrome://formautofill/locale/formautofill.properties";
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://formautofill/FormAutofillUtils.jsm");
this.log = null;
FormAutofillUtils.defineLazyLogGetter(this, this.EXPORTED_SYMBOLS[0]);
function FormAutofillPreferences() {
this.bundle = Services.strings.createBundle(BUNDLE_URI);
@ -46,6 +51,26 @@ FormAutofillPreferences.prototype = {
* @returns {XULElement}
*/
init(document) {
this.createPreferenceGroup(document);
this.attachEventListeners();
return this.refs.formAutofillGroup;
},
/**
* Remove event listeners and the preference group.
*/
uninit() {
this.detachEventListeners();
this.refs.formAutofillGroup.remove();
},
/**
* Create Form Autofill preference group
*
* @param {XULDocument} document
*/
createPreferenceGroup(document) {
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let formAutofillGroup = document.createElementNS(XUL_NS, "groupbox");
@ -85,18 +110,6 @@ FormAutofillPreferences.prototype = {
hbox.appendChild(enabledCheckbox);
hbox.appendChild(spacer);
hbox.appendChild(savedProfilesBtn);
this.attachEventListeners();
return formAutofillGroup;
},
/**
* Remove event listeners and the preference group.
*/
uninit() {
this.detachEventListeners();
this.refs.formAutofillGroup.remove();
},
/**

Просмотреть файл

@ -31,8 +31,8 @@ function insertStyleSheet(domWindow, url) {
}
let windowListener = {
onOpenWindow(aWindow) {
let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
onOpenWindow(window) {
let domWindow = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
domWindow.addEventListener("load", function onWindowLoaded() {
insertStyleSheet(domWindow, STYLESHEET_URI);

Просмотреть файл

@ -0,0 +1,92 @@
/* 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/. */
body {
font-size: 1rem;
}
form,
label,
div {
display: flex;
}
form {
flex-wrap: wrap;
}
label {
margin: 0 0 0.5em;
}
label > span {
flex: 0 0 8em;
padding-inline-end: 0.5em;
align-self: center;
text-align: end;
}
input,
select {
flex: 1 0 auto;
width: 9em;
}
option {
padding: 6px;
}
textarea {
resize: none;
}
button {
padding: 3px 2em;
}
#country-container {
width: 15em;
}
#first-name-container,
#middle-name-container,
#address-level1-container,
#postal-code-container,
#country-container {
flex: 0 1 50%;
}
#last-name-container,
#organization-container,
#street-address-container,
#address-level2-container,
#email-container,
#tel-container,
#controls-container {
flex: 0 1 100%;
}
#controls-container {
justify-content: end;
}
#last-name,
#organization,
#address-level2,
#tel{
flex: 0 0 auto;
width: calc(50% - 10em);
}
#street-address,
#email {
flex: 1 0 auto;
}
#first-name-container,
#middle-name-container,
#last-name-container {
/* Hide until we support names */
display: none;
}

Просмотреть файл

@ -0,0 +1,140 @@
/* 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/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://formautofill/FormAutofillUtils.jsm");
function EditDialog(profile) {
this._profile = profile;
window.addEventListener("DOMContentLoaded", this, {once: true});
}
EditDialog.prototype = {
init() {
this.refs = {
controlsContainer: document.getElementById("controls-container"),
cancel: document.getElementById("cancel"),
save: document.getElementById("save"),
};
this.attachEventListeners();
},
/**
* Asks FormAutofillParent to save or update a profile.
* @param {object} data
* {
* {string} guid [optional]
* {object} profile
* }
*/
saveProfile(data) {
Services.cpmm.sendAsyncMessage("FormAutofill:SaveProfile", data);
},
/**
* Fill the form with a profile object.
* @param {object} profile
*/
loadInitialValues(profile) {
for (let field in profile) {
let input = document.getElementById(field);
if (input) {
input.value = profile[field];
}
}
},
/**
* Get inputs from the form.
* @returns {object}
*/
buildProfileObject() {
return Array.from(document.forms[0].elements).reduce((obj, input) => {
if (input.value) {
obj[input.id] = input.value;
}
return obj;
}, {});
},
/**
* Handle events
*
* @param {DOMEvent} event
*/
handleEvent(event) {
switch (event.type) {
case "DOMContentLoaded": {
this.init();
if (this._profile) {
this.loadInitialValues(this._profile);
}
break;
}
case "click": {
this.handleClick(event);
break;
}
case "input": {
// Toggle disabled attribute on the save button based on
// whether the form is filled or empty.
if (Object.keys(this.buildProfileObject()).length == 0) {
this.refs.save.setAttribute("disabled", true);
} else {
this.refs.save.removeAttribute("disabled");
}
break;
}
}
},
/**
* Handle click events
*
* @param {DOMEvent} event
*/
handleClick(event) {
if (event.target == this.refs.cancel) {
this.detachEventListeners();
window.close();
}
if (event.target == this.refs.save) {
if (this._profile) {
this.saveProfile({
guid: this._profile.guid,
profile: this.buildProfileObject(),
});
} else {
this.saveProfile({
profile: this.buildProfileObject(),
});
}
this.detachEventListeners();
window.close();
}
},
/**
* Attach event listener
*/
attachEventListeners() {
this.refs.controlsContainer.addEventListener("click", this);
document.addEventListener("input", this);
},
/**
* Remove event listener
*/
detachEventListeners() {
this.refs.controlsContainer.removeEventListener("click", this);
document.removeEventListener("input", this);
},
};
// Pass in argument from openDialog
new EditDialog(window.arguments[0]);

Просмотреть файл

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 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/. -->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Profile Autofill - Edit Profile</title>
<link rel="stylesheet" href="chrome://formautofill/content/editProfile.css" />
<script src="chrome://formautofill/content/editProfile.js"></script>
</head>
<body>
<form>
<label id="first-name-container">
<span>First Name</span>
<input id="first-name" type="text"/>
</label>
<label id="middle-name-container">
<span>Middle Name</span>
<input id="middle-name" type="text"/>
</label>
<label id="last-name-container">
<span>Last Name</span>
<input id="last-name" type="text"/>
</label>
<label id="organization-container">
<span>Company</span>
<input id="organization" type="text"/>
</label>
<label id="street-address-container">
<span>Street Address</span>
<textarea id="street-address"/>
</label>
<label id="address-level2-container">
<span>City/Town</span>
<input id="address-level2" type="text"/>
</label>
<label id="address-level1-container">
<span>State/Province</span>
<input id="address-level1" type="text"/>
</label>
<label id="postal-code-container">
<span>Zip/Postal</span>
<input id="postal-code" type="text"/>
</label>
<label id="country-container">
<span>Country</span>
<select id="country">
<option/>
<option value="US">United States</option>
</select>
</label>
<label id="email-container">
<span>Email</span>
<input id="email" type="email"/>
</label>
<label id="tel-container">
<span>Phone</span>
<input id="tel" type="tel"/>
</label>
</form>
<div id="controls-container">
<button id="cancel">Cancel</button>
<button id="save" disabled="disabled">Save</button>
</div>
</body>
</html>

Просмотреть файл

@ -89,15 +89,28 @@ option(env='OLD_CONFIGURE', nargs=1, help='Path to the old configure script')
option(env='MOZ_CURRENT_PROJECT', nargs=1, help='Current build project')
option(env='MOZCONFIG', nargs=1, help='Mozconfig location')
option('--with-external-source-dir', env='EXTERNAL_SOURCE_DIR', nargs=1,
help='External directory containing additional build files')
@depends('--with-external-source-dir')
def external_source_dir(value):
if value:
return value[0]
set_config('EXTERNAL_SOURCE_DIR', external_source_dir)
add_old_configure_assignment('EXTERNAL_SOURCE_DIR', external_source_dir)
# Read user mozconfig
# ==============================================================
# Note: the dependency on --help is only there to always read the mozconfig,
# even when --help is passed. Without this dependency, the function wouldn't
# be called when --help is passed, and the mozconfig wouldn't be read.
@depends('MOZ_CURRENT_PROJECT', 'MOZCONFIG', 'OLD_CONFIGURE',
check_build_environment, '--help')
check_build_environment, '--with-external-source-dir',
'--help')
@imports(_from='mozbuild.mozconfig', _import='MozconfigLoader')
def mozconfig(current_project, mozconfig, old_configure, build_env, help):
def mozconfig(current_project, mozconfig, old_configure, build_env,
external_source_dir, help):
if not old_configure:
die('The OLD_CONFIGURE environment variable must be set')
@ -120,7 +133,10 @@ def mozconfig(current_project, mozconfig, old_configure, build_env, help):
if os.path.dirname(os.path.abspath(old_configure[0])).endswith('/js/src'):
return {'path': None}
loader = MozconfigLoader(build_env.topsrcdir)
topsrcdir = build_env.topsrcdir
if external_source_dir:
topsrcdir = external_source_dir[0]
loader = MozconfigLoader(topsrcdir)
current_project = current_project[0] if current_project else None
mozconfig = mozconfig[0] if mozconfig else None
mozconfig = loader.find_mozconfig(env={'MOZCONFIG': mozconfig})
@ -632,9 +648,6 @@ def default_project(build_env, help):
option('--enable-project', nargs=1, default=default_project,
help='Project to build')
option('--with-external-source-dir', env='EXTERNAL_SOURCE_DIR', nargs=1,
help='External directory containing additional build files')
@depends('--enable-project', '--with-external-source-dir',
check_build_environment, '--help')
@imports(_from='os.path', _import='exists')
@ -651,14 +664,6 @@ def include_project_configure(project, external_source_dir, build_env, help):
die('Cannot find project %s', project[0])
return path
@depends('--with-external-source-dir')
def external_source_dir(value):
if value:
return value[0]
set_config('EXTERNAL_SOURCE_DIR', external_source_dir)
add_old_configure_assignment('EXTERNAL_SOURCE_DIR', external_source_dir)
@depends(include_project_configure, check_build_environment, '--help')
def build_project(include_project_configure, build_env, help):

Просмотреть файл

@ -151,6 +151,8 @@ for f in files:
log(3, ' pretty printed code:')
ipdl.genipdl(ast, codedir)
ipdl.checkFixedSyncMessages(parser)
# Second pass: generate code
for f in files:
# Read from parser cache

Просмотреть файл

@ -2,7 +2,8 @@
# 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__ = [ 'gencxx', 'genipdl', 'parse', 'typecheck', 'writeifmodified', 'checkSyncMessage' ]
__all__ = [ 'gencxx', 'genipdl', 'parse', 'typecheck', 'writeifmodified',
'checkSyncMessage', 'checkFixedSyncMessages' ]
import os, sys
from cStringIO import StringIO
@ -11,7 +12,7 @@ from ipdl.cgen import IPDLCodeGen
from ipdl.lower import LowerToCxx, msgenums
from ipdl.parser import Parser, ParseError
from ipdl.type import TypeCheck
from ipdl.checker import checkSyncMessage
from ipdl.checker import checkSyncMessage, checkFixedSyncMessages
from ipdl.cxx.cgen import CxxCodeGen

Просмотреть файл

@ -7,8 +7,11 @@ import sys
from ipdl.ast import Visitor, ASYNC
class SyncMessageChecker(Visitor):
syncMsgList = []
seenProtocols = []
seenSyncMessages = []
def __init__(self, syncMsgList):
self.syncMsgList = syncMsgList
SyncMessageChecker.syncMsgList = syncMsgList
self.errors = []
def prettyMsgName(self, msg):
@ -23,16 +26,24 @@ class SyncMessageChecker(Visitor):
(str(loc), msg))
def visitProtocol(self, p):
self.errors = []
self.currentProtocol = p.name
SyncMessageChecker.seenProtocols.append(p.name)
Visitor.visitProtocol(self, p)
def visitMessageDecl(self, md):
pn = self.prettyMsgName(md.name)
if md.sendSemantics is not ASYNC and pn not in self.syncMsgList:
self.errorUnknownSyncMessage(md.loc, pn)
if md.sendSemantics is ASYNC and pn in self.syncMsgList:
if md.sendSemantics is not ASYNC:
if pn not in SyncMessageChecker.syncMsgList:
self.errorUnknownSyncMessage(md.loc, pn)
SyncMessageChecker.seenSyncMessages.append(pn)
elif pn in SyncMessageChecker.syncMsgList:
self.errorAsyncMessageCanRemove(md.loc, pn)
@staticmethod
def getFixedSyncMessages():
return set(SyncMessageChecker.syncMsgList) - set(SyncMessageChecker.seenSyncMessages)
def checkSyncMessage(tu, syncMsgList, errout=sys.stderr):
checker = SyncMessageChecker(syncMsgList)
tu.accept(checker)
@ -41,3 +52,14 @@ def checkSyncMessage(tu, syncMsgList, errout=sys.stderr):
print >>errout, error
return False
return True
def checkFixedSyncMessages(config, errout=sys.stderr):
fixed = SyncMessageChecker.getFixedSyncMessages()
for item in fixed:
protocol = item.split('::')[0]
# Ignore things like sync messages in test protocols we didn't compile.
# Also, ignore platform-specific IPC messages.
if protocol in SyncMessageChecker.seenProtocols and \
'platform' not in config.options(item):
print >>errout, 'Error: Sync IPC message %s not found, it appears to be fixed.\n' \
'Please remove it from sync-messages.ini.' % item

Просмотреть файл

@ -473,6 +473,7 @@ description =
description =
[PDocAccessible::GetWindowedPluginIAccessible]
description =
platform = win
# CPOWs
[PBrowser::RpcMessage]
@ -537,8 +538,6 @@ description =
description =
[PPluginInstance::NPP_GetValue_NPPVpluginWantsAllNetworkStreams]
description =
[PPluginInstance::NPP_GetValue_NPPVpluginNeedsXEmbed]
description =
[PPluginInstance::NPP_GetValue_NPPVpluginScriptableNPObject]
description =
[PPluginInstance::NPP_SetValue_NPNVprivateModeBool]
@ -619,8 +618,6 @@ description =
description =
[PPluginInstance::NPN_ConvertPoint]
description =
[PPluginInstance::NegotiatedCarbon]
description =
[PPluginInstance::GetCompositionString]
description =
[PPluginInstance::NPP_NewStream]
@ -645,8 +642,6 @@ description =
description =
[PPluginModule::OptionalFunctionsSupported]
description =
[PPluginModule::PCrashReporter]
description =
[PPluginModule::ProcessSomeEvents]
description =
[PPluginModule::NPN_SetException]
@ -759,8 +754,6 @@ description =
description =
[PContent::FindPlugins]
description =
[PContent::PCrashReporter]
description =
[PContent::NSSU2FTokenIsCompatibleVersion]
description =
[PContent::NSSU2FTokenIsRegistered]
@ -801,8 +794,6 @@ description =
description =
[PContent::AllocateLayerTreeId]
description =
[PContent::GetGfxInfoFeatureStatus]
description =
[PContent::BeginDriverCrashGuard]
description =
[PContent::EndDriverCrashGuard]
@ -915,10 +906,13 @@ description =
description =
[PCompositorWidget::EnterPresentLock]
description =
platform = win
[PCompositorWidget::LeavePresentLock]
description =
platform = win
[PCompositorWidget::ClearTransparentWindow]
description =
platform = win
[PImageBridge::WillClose]
description =
[PImageBridge::NewCompositable]
@ -939,8 +933,6 @@ description =
description =
[PLayerTransaction::RequestProperty]
description =
[PTexture::DestroySync]
description =
[PUiCompositorController::Pause]
description =
[PUiCompositorController::Resume]

Просмотреть файл

@ -15,10 +15,14 @@ template <typename T> class WeakCache;
namespace shadow {
JS_PUBLIC_API(void)
RegisterWeakCache(JS::Zone* zone, JS::WeakCache<void*>* cachep);
JS_PUBLIC_API(void)
RegisterWeakCache(JSRuntime* rt, JS::WeakCache<void*>* cachep);
} // namespace shadow
// A WeakCache stores the given Sweepable container and links itself into a
// list of such caches that are swept during each GC.
// list of such caches that are swept during each GC. A WeakCache can be
// specific to a zone, or across a whole runtime, depending on which
// constructor is used.
template <typename T>
class WeakCache : public js::MutableWrappedPtrOperations<T, WeakCache<T>>,
private mozilla::LinkedListElement<WeakCache<T>>
@ -43,6 +47,13 @@ class WeakCache : public js::MutableWrappedPtrOperations<T, WeakCache<T>>,
sweeper = GCPolicy<T>::sweep;
shadow::RegisterWeakCache(zone, reinterpret_cast<WeakCache<void*>*>(this));
}
template <typename U>
WeakCache(JSRuntime* rt, U&& initial)
: cache(mozilla::Forward<U>(initial))
{
sweeper = GCPolicy<T>::sweep;
shadow::RegisterWeakCache(rt, reinterpret_cast<WeakCache<void*>*>(this));
}
WeakCache(WeakCache&& other)
: sweeper(other.sweeper),
cache(mozilla::Move(other.cache))

Просмотреть файл

@ -533,6 +533,8 @@ class OrderedHashTable
return offsetof(OrderedHashTable, data);
}
static constexpr size_t offsetOfDataElement() {
static_assert(offsetof(Data, element) == 0,
"RangeFront and RangePopFront depend on offsetof(Data, element) being 0");
return offsetof(Data, element);
}
static constexpr size_t sizeofData() {

Просмотреть файл

@ -6465,7 +6465,7 @@ RangeFront<ValueMap>(MacroAssembler& masm, Register range, Register i, Register
masm.loadPtr(Address(range, ValueMap::Range::offsetOfHashTable()), front);
masm.loadPtr(Address(front, ValueMap::offsetOfImplData()), front);
static_assert(ValueMap::offsetOfImplDataElement() == 0, "offsetof(Data, element) is 0");
MOZ_ASSERT(ValueMap::offsetOfImplDataElement() == 0, "offsetof(Data, element) is 0");
static_assert(ValueMap::sizeofImplData() == 24, "sizeof(Data) is 24");
masm.mulBy3(i, i);
masm.lshiftPtr(Imm32(3), i);
@ -6479,7 +6479,7 @@ RangeFront<ValueSet>(MacroAssembler& masm, Register range, Register i, Register
masm.loadPtr(Address(range, ValueSet::Range::offsetOfHashTable()), front);
masm.loadPtr(Address(front, ValueSet::offsetOfImplData()), front);
static_assert(ValueSet::offsetOfImplDataElement() == 0, "offsetof(Data, element) is 0");
MOZ_ASSERT(ValueSet::offsetOfImplDataElement() == 0, "offsetof(Data, element) is 0");
static_assert(ValueSet::sizeofImplData() == 16, "sizeof(Data) is 16");
masm.lshiftPtr(Imm32(4), i);
masm.addPtr(i, front);
@ -6503,7 +6503,7 @@ RangePopFront(MacroAssembler& masm, Register range, Register front, Register dat
// We can add sizeof(Data) to |front| to select the next element, because
// |front| and |range.ht.data[i]| point to the same location.
static_assert(OrderedHashTable::offsetOfImplDataElement() == 0, "offsetof(Data, element) is 0");
MOZ_ASSERT(OrderedHashTable::offsetOfImplDataElement() == 0, "offsetof(Data, element) is 0");
masm.addPtr(Imm32(OrderedHashTable::sizeofImplData()), front);
masm.branchTestMagic(Assembler::NotEqual, Address(front, OrderedHashTable::offsetOfEntryKey()),

Просмотреть файл

@ -126,6 +126,7 @@ MSG_DEF(JSMSG_CANT_DECLARE_GLOBAL_BINDING, 2, JSEXN_TYPEERR, "cannot declare glo
// Date
MSG_DEF(JSMSG_INVALID_DATE, 0, JSEXN_RANGEERR, "invalid date")
MSG_DEF(JSMSG_BAD_TOISOSTRING_PROP, 0, JSEXN_TYPEERR, "toISOString property is not callable")
MSG_DEF(JSMSG_DEPRECATED_TOLOCALEFORMAT, 0, JSEXN_WARN, "Date.prototype.toLocaleFormat is deprecated; consider using Intl.DateTimeFormat instead")
// String
MSG_DEF(JSMSG_BAD_URI, 0, JSEXN_URIERR, "malformed URI sequence")

Просмотреть файл

@ -54,6 +54,7 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
isAtomsCompartment_(false),
isSelfHosting(false),
marked(true),
warnedAboutDateToLocaleFormat(false),
warnedAboutExprClosure(false),
warnedAboutForEach(false),
warnedAboutStringGenericsMethods(0),

Просмотреть файл

@ -406,6 +406,7 @@ struct JSCompartment
public:
bool isSelfHosting;
bool marked;
bool warnedAboutDateToLocaleFormat;
bool warnedAboutExprClosure;
bool warnedAboutForEach;
uint32_t warnedAboutStringGenericsMethods;

Просмотреть файл

@ -2822,6 +2822,17 @@ date_toLocaleFormat_impl(JSContext* cx, const CallArgs& args)
{
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
#if EXPOSE_INTL_API
if (!cx->compartment()->warnedAboutDateToLocaleFormat) {
if (!JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_WARNING, GetErrorMessage, nullptr,
JSMSG_DEPRECATED_TOLOCALEFORMAT))
{
return false;
}
cx->compartment()->warnedAboutDateToLocaleFormat = true;
}
#endif
if (args.length() == 0) {
/*
* Use '%#c' for windows, because '%c' is backward-compatible and non-y2k

Просмотреть файл

@ -2554,6 +2554,8 @@ GCRuntime::updateRuntimePointersToRelocatedCells(AutoLockForExclusiveAccess& loc
WatchpointMap::sweepAll(rt);
Debugger::sweepAll(rt->defaultFreeOp());
jit::JitRuntime::SweepJitcodeGlobalTable(rt);
for (JS::WeakCache<void*>* cache : rt->weakCaches())
cache->sweep();
// Type inference may put more blocks here to free.
blocksToFreeAfterSweeping.ref().freeAll();
@ -5149,6 +5151,10 @@ GCRuntime::beginSweepingZoneGroup(AutoLockForExclusiveAccess& lock)
// Sweep entries containing about-to-be-finalized JitCode and
// update relocated TypeSet::Types inside the JitcodeGlobalTable.
jit::JitRuntime::SweepJitcodeGlobalTable(rt);
// Sweep runtime-wide weak caches.
for (JS::WeakCache<void*>* cache : rt->weakCaches())
cache->sweep();
}
{

Просмотреть файл

@ -0,0 +1,18 @@
// |reftest| skip-if(!xulRuntime.shell||this.hasOwnProperty("Intl"))
/* 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/. */
// Don't warn about Date.prototype.toLocaleFormat() when Intl isn't supported.
enableLastWarning();
new Date().toLocaleFormat("%Y");
var warning = getLastWarning();
assertEq(warning, null, "warning shouldn't be emitted for toLocaleFormat");
disableLastWarning();
if (typeof reportCompare === 'function')
reportCompare(0, 0);

Просмотреть файл

@ -0,0 +1,28 @@
// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty("Intl"))
/* 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/. */
// Warn once about Date.prototype.toLocaleFormat().
enableLastWarning();
new Date().toLocaleFormat("%Y");
var warning = getLastWarning();
assertEq(warning !== null, true, "warning should be emitted for toLocaleFormat");
assertEq(warning.name, "Warning");
assertEq(warning.message.indexOf("toLocaleFormat") !== -1, true,
"warning should mention toLocaleFormat");
clearLastWarning();
new Date().toLocaleFormat("%Y");
warning = getLastWarning();
assertEq(warning, null, "warning shouldn't be emitted for 2nd call to toLocaleFormat");
disableLastWarning();
if (typeof reportCompare === 'function')
reportCompare(0, 0);

Просмотреть файл

@ -915,3 +915,9 @@ JSRuntime::ionLazyLinkListAdd(jit::IonBuilder* builder)
ionLazyLinkList().insertFront(builder);
ionLazyLinkListSize_++;
}
JS_PUBLIC_API(void)
JS::shadow::RegisterWeakCache(JSRuntime* rt, WeakCache<void*>* cachep)
{
rt->registerWeakCache(cachep);
}

Просмотреть файл

@ -560,6 +560,15 @@ struct JSRuntime : public js::MallocProvider<JSRuntime>
windowProxyClass_ = clasp;
}
private:
// List of non-ephemeron weak containers to sweep during beginSweepingZoneGroup.
js::ActiveThreadData<mozilla::LinkedList<JS::WeakCache<void*>>> weakCaches_;
public:
mozilla::LinkedList<JS::WeakCache<void*>>& weakCaches() { return weakCaches_.ref(); }
void registerWeakCache(JS::WeakCache<void*>* cachep) {
weakCaches().insertBack(cachep);
}
private:
/*
* Head of circular list of all enabled Debuggers that have

Просмотреть файл

@ -64,6 +64,17 @@ class DebugFrame
explicit DebugFrame() {}
void StaticAsserts() {
// VS2017 doesn't consider offsetOfResults() etc. to be constexpr, so we have to use
// offsetof directly. These asserts can't be at class-level because the type is incomplete.
static_assert(offsetof(DebugFrame, resultI32_) == 0, "results shall be at offset 0");
static_assert(offsetof(DebugFrame, tlsData_) + sizeof(TlsData*) ==
offsetof(DebugFrame, frame_),
"TLS pointer must be a field just before the wasm frame");
static_assert(sizeof(DebugFrame) % 8 == 0 && offsetof(DebugFrame, frame_) % 8 == 0,
"DebugFrame and its portion is 8-bytes aligned for AbstractFramePtr");
}
public:
inline uint32_t funcIndex() const { return funcIndex_; }
inline TlsData* tlsData() const { return tlsData_; }
@ -110,12 +121,6 @@ class DebugFrame
static constexpr size_t offsetOfFrame() { return offsetof(DebugFrame, frame_); }
};
static_assert(DebugFrame::offsetOfResults() == 0, "results shall be at offset 0");
static_assert(DebugFrame::offsetOfTlsData() + sizeof(TlsData*) == DebugFrame::offsetOfFrame(),
"TLS pointer must be a field just before the wasm frame");
static_assert(sizeof(DebugFrame) % 8 == 0 && DebugFrame::offsetOfFrame() % 8 == 0,
"DebugFrame and its portion is 8-bytes aligned for AbstractFramePtr");
} // namespace wasm
} // namespace js

Просмотреть файл

@ -593,10 +593,6 @@ GeckoRestyleManager::UpdateOnlyAnimationStyles()
tracker.Init(this);
if (doCSS) {
// FIXME: We should have the transition manager and animation manager
// add only the elements for which animations are currently throttled
// (i.e., animating on the compositor with main-thread style updates
// suppressed).
PresContext()->EffectCompositor()->AddStyleUpdatesTo(tracker);
}

Просмотреть файл

@ -1575,7 +1575,8 @@ nsDisplayImage::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters)
{
if (!nsDisplayItem::ForceActiveLayers()) {
if (!nsDisplayItem::ForceActiveLayers() &&
aManager->GetBackendType() != layers::LayersBackend::LAYERS_WR) {
bool animated = false;
if (!nsLayoutUtils::AnimatedImageLayersEnabled() ||
mImage->GetType() != imgIContainer::TYPE_RASTER ||

Просмотреть файл

@ -306,7 +306,8 @@ fails == 280708-1b.html 280708-1b.html
== 283686-2.html 283686-2.html
== 283686-3.html 283686-3.html
fails == 289384-1.xhtml 289384-1.xhtml
skip-if(stylo) == 289480.html#top 289480.html#top # Bug 1341705
fails == 289480.html#top 289480-ref.html
fails == 289480-ref.html 289480-ref.html
fails == 290129-1.html 290129-1.html
fails == 291078-1.html 291078-1.html
== 291078-2.html 291078-2.html
@ -1475,7 +1476,7 @@ fails == 538909-1.html 538909-1.html
== 539323-3.html 539323-3.html
fails == 539880-1.html 539880-1.html
fails == 539880-1-dynamic.html 539880-1-dynamic.html
skip-if(stylo) == 539949-1.html#test2 539949-1.html#test2 # load fails???
fails == 539949-1.html#test2 539949-1-ref.html#test2
fails == 541382-1.html 541382-1.html
== 541406-1.html 541406-1.html
fails needs-focus == 542116-1.html 542116-1.html

Просмотреть файл

@ -1,5 +1,5 @@
# DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
skip-if(stylo) HTTP == deferred-anchor.xhtml#d deferred-anchor.xhtml#d # Fails to load?
HTTP == deferred-anchor.xhtml#d deferred-anchor-ref.xhtml#d
fuzzy-if(xulRuntime.widgetToolkit=="gtk3",1,23) == deferred-anchor2.xhtml deferred-anchor2.xhtml
fails HTTP == fixed-1.html fixed-1.html
fails == fixed-table-1.html fixed-table-1.html
@ -23,7 +23,7 @@ fails == scroll-behavior-9.html scroll-behavior-9.html
skip-if(Android) pref(layout.css.scroll-behavior.enabled,true) pref(layout.css.scroll-behavior.property-enabled,true) == scroll-behavior-10.html scroll-behavior-10.html
fails == scroll-behavior-textarea.html scroll-behavior-textarea.html
fails HTTP == simple-1.html simple-1.html
skip-if(stylo) HTTP == subpixel-1.html#d subpixel-1.html#d # Fails to load?
fails HTTP == subpixel-1.html#d subpixel-1-ref.html#d
== text-1.html text-1.html
== text-2.html?up text-2.html?up
== transformed-1.html transformed-1.html

Просмотреть файл

@ -1728,10 +1728,10 @@ nsStyleSet::ResolveStyleWithReplacement(Element* aElement,
// because at this point the parameter is more than just the element
// for animation; it's also used for the SetBodyTextColor call when
// it's the body element.
// However, we only want to set the flag to call CheckAnimationRule
// However, we only want to set the flag to call UpdateAnimations
// if we're dealing with a replacement (such as style attribute
// replacement) that could lead to the animation property changing,
// and we explicitly do NOT want to call CheckAnimationRule when
// and we explicitly do NOT want to call UpdateAnimations when
// we're trying to do an animation-only update.
if (aReplacements & ~(eRestyle_CSSTransitions | eRestyle_CSSAnimations)) {
flags |= eDoAnimation;

Просмотреть файл

@ -516,30 +516,49 @@ nsTableFrame::ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude)
{
// Iterate over the row groups and adjust the row indices of all rows
// omit the rowgroups that will be inserted later
mDeletedRowIndexRanges.clear();
RowGroupArray rowGroups;
OrderRowGroups(rowGroups);
int32_t rowIndex = 0;
nsTHashtable<nsPtrHashKey<nsTableRowGroupFrame> > excludeRowGroups;
nsFrameList::Enumerator excludeRowGroupsEnumerator(aRowGroupsToExclude);
while (!excludeRowGroupsEnumerator.AtEnd()) {
excludeRowGroups.PutEntry(static_cast<nsTableRowGroupFrame*>(excludeRowGroupsEnumerator.get()));
#ifdef DEBUG
{
// Check to make sure that the row indices of all rows in excluded row
// groups are '0' (i.e. the initial value since they haven't been added yet)
const nsFrameList& rowFrames =
excludeRowGroupsEnumerator.get()->PrincipalChildList();
for (nsFrameList::Enumerator rows(rowFrames); !rows.AtEnd(); rows.Next()) {
nsTableRowFrame* row = static_cast<nsTableRowFrame*>(rows.get());
MOZ_ASSERT(row->GetRowIndex() == 0,
"exclusions cannot be used for rows that were already added,"
"because we'd need to process mDeletedRowIndexRanges");
}
}
#endif
excludeRowGroupsEnumerator.Next();
}
int32_t rowIndex = 0;
for (uint32_t rgIdx = 0; rgIdx < rowGroups.Length(); rgIdx++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgIdx];
if (!excludeRowGroups.GetEntry(rgFrame)) {
const nsFrameList& rowFrames = rgFrame->PrincipalChildList();
for (nsFrameList::Enumerator rows(rowFrames); !rows.AtEnd(); rows.Next()) {
if (mozilla::StyleDisplay::TableRow == rows.get()->StyleDisplay()->mDisplay) {
((nsTableRowFrame *)rows.get())->SetRowIndex(rowIndex);
if (mozilla::StyleDisplay::TableRow ==
rows.get()->StyleDisplay()->mDisplay) {
nsTableRowFrame* row = static_cast<nsTableRowFrame*>(rows.get());
row->SetRowIndex(rowIndex);
rowIndex++;
}
}
}
}
}
void
nsTableFrame::InsertColGroups(int32_t aStartColIndex,
const nsFrameList::Slice& aColGroups)
@ -920,13 +939,18 @@ nsTableFrame::InsertRows(nsTableRowGroupFrame* aRowGroupFrame,
nsTableCellMap* cellMap = GetCellMap();
if (cellMap) {
TableArea damageArea(0, 0, 0, 0);
bool didRecalculate = RecalculateRowIndices();
bool shouldRecalculateIndex = !IsDeletedRowIndexRangesEmpty();
if (shouldRecalculateIndex) {
ResetRowIndices(nsFrameList::Slice(mFrames, nullptr, nullptr));
}
int32_t origNumRows = cellMap->GetRowCount();
int32_t numNewRows = aRowFrames.Length();
cellMap->InsertRows(aRowGroupFrame, aRowFrames, aRowIndex, aConsiderSpans, damageArea);
MatchCellMapToColCache(cellMap);
if (!didRecalculate) {
// Perform row index adjustment only if row indices were not
// reset above
if (!shouldRecalculateIndex) {
if (aRowIndex < origNumRows) {
AdjustRowIndices(aRowIndex, numNewRows);
}
@ -952,32 +976,6 @@ nsTableFrame::InsertRows(nsTableRowGroupFrame* aRowGroupFrame,
return numColsToAdd;
}
bool
nsTableFrame::RecalculateRowIndices()
{
if (mDeletedRowIndexRanges.size() == 0) {
return false;
}
mDeletedRowIndexRanges.clear();
RowGroupArray rowGroups;
OrderRowGroups(rowGroups);
int32_t rowIndex = 0;
for (uint32_t rgIdx = 0; rgIdx < rowGroups.Length(); rgIdx++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgIdx];
const nsFrameList& rowFrames = rgFrame->PrincipalChildList();
for (nsFrameList::Enumerator rEnum(rowFrames); !rEnum.AtEnd(); rEnum.Next()) {
if (mozilla::StyleDisplay::TableRow == rEnum.get()->StyleDisplay()->mDisplay) {
nsTableRowFrame *row = static_cast<nsTableRowFrame*>(rEnum.get());
row->SetRowIndex(rowIndex);
rowIndex++;
}
}
}
return true;
}
void
nsTableFrame::AddDeletedRowIndex(int32_t aDeletedRowStoredIndex)
{

Просмотреть файл

@ -872,12 +872,6 @@ public:
*/
int32_t GetAdjustmentForStoredIndex(int32_t aStoredIndex);
/** Recalculate the row indices of all rows (if needed) and overwrite
* the value of the stored index with this newly calculated index.
* Returns whether recalculation was performed.
*/
bool RecalculateRowIndices();
/** Returns whether mDeletedRowIndexRanges is empty
*/
bool IsDeletedRowIndexRangesEmpty() const {

Просмотреть файл

@ -12,6 +12,15 @@
// corecrt_memory.h.
#include <string>
// Because we wrap lz4.c in an anonymous namespace, all of its #includes
// go in the anonymous namespace too. This would create conflicting
// declarations for intrinsic functions that are internally defined
// at top-level. Including intrin.h here prevents it from being included
// later within the anonymous namespace.
#ifdef _MSC_VER
#include <intrin.h>
#endif
using namespace mozilla::Compression;
namespace {

Просмотреть файл

@ -287,6 +287,7 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x
'gfx/VsyncSource.java',
'InputConnectionListener.java',
'InputMethods.java',
'NativeQueue.java',
'NotificationListener.java',
'NSSBridge.java',
'permissions/PermissionBlock.java',

Просмотреть файл

@ -9,6 +9,7 @@ import org.mozilla.gecko.annotation.RobocopTarget;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.mozglue.JNIObject;
import org.mozilla.gecko.NativeQueue.StateHolder;
import org.mozilla.gecko.util.BundleEventListener;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoBundle;
@ -57,6 +58,7 @@ public final class EventDispatcher extends JNIObject {
new HashMap<String, List<BundleEventListener>>(DEFAULT_BACKGROUND_EVENTS_COUNT);
private boolean mAttachedToGecko;
private final StateHolder mStateHolder;
@ReflectionTarget
@WrapForJNI(calledFrom = "gecko")
@ -65,6 +67,15 @@ public final class EventDispatcher extends JNIObject {
}
/* package */ EventDispatcher() {
mStateHolder = GeckoThread.getStateHolder();
}
/* package */ EventDispatcher(final NativeQueue.StateHolder stateHolder) {
mStateHolder = stateHolder;
}
private boolean isReadyForDispatchingToGecko() {
return mStateHolder.isReady();
}
@WrapForJNI(dispatchTo = "gecko") @Override // JNIObject
@ -228,7 +239,7 @@ public final class EventDispatcher extends JNIObject {
public void dispatch(final String type, final GeckoBundle message,
final EventCallback callback) {
synchronized (this) {
if (mAttachedToGecko && hasGeckoListener(type)) {
if (isReadyForDispatchingToGecko() && hasGeckoListener(type)) {
dispatchToGecko(type, message, JavaCallbackDelegate.wrap(callback));
return;
}
@ -279,15 +290,18 @@ public final class EventDispatcher extends JNIObject {
return true;
}
if (!GeckoThread.isRunning()) {
// Usually, we discard an event if there is no listeners for it by the time of
// the dispatch. However, if Gecko is not ready and there is no listener for
// this event that's possibly headed to Gecko, we make a special exception to
// queue this event until Gecko is ready. This way, Gecko can first register
// its listeners, and accept the event when it is ready.
GeckoThread.queueNativeCall(this, "dispatchToGecko",
String.class, type, GeckoBundle.class, message,
EventCallback.class, JavaCallbackDelegate.wrap(callback));
if (!isReadyForDispatchingToGecko()) {
// Usually, we discard an event if there is no listeners for it by
// the time of the dispatch. However, if Gecko(View) is not ready and
// there is no listener for this event that's possibly headed to
// Gecko, we make a special exception to queue this event until
// Gecko(View) is ready. This way, Gecko can first register its
// listeners, and accept the event when it is ready.
NativeQueue.queueUntil(mStateHolder,
mStateHolder.getReadyState(), this, "dispatchToGecko",
String.class, type,
GeckoBundle.class, message,
EventCallback.class, JavaCallbackDelegate.wrap(callback));
return true;
}

Просмотреть файл

@ -8,12 +8,10 @@ package org.mozilla.gecko;
import org.mozilla.gecko.annotation.RobocopTarget;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.mozglue.GeckoLoader;
import org.mozilla.gecko.NativeQueue.StateHolder;
import org.mozilla.gecko.util.FileUtils;
import org.mozilla.gecko.util.ThreadUtils;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@ -28,19 +26,14 @@ import android.util.Log;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.StringTokenizer;
public class GeckoThread extends Thread {
private static final String LOGTAG = "GeckoThread";
public enum State {
public enum State implements NativeQueue.State {
// After being loaded by class loader.
@WrapForJNI INITIAL(0),
// After launching Gecko thread
@ -73,47 +66,30 @@ public class GeckoThread extends Thread {
this.rank = rank;
}
public boolean is(final State other) {
@Override
public boolean is(final NativeQueue.State other) {
return this == other;
}
public boolean isAtLeast(final State other) {
return this.rank >= other.rank;
@Override
public boolean isAtLeast(final NativeQueue.State other) {
if (other instanceof State) {
return this.rank >= ((State) other).rank;
}
return false;
}
}
public boolean isAtMost(final State other) {
return this.rank <= other.rank;
}
private static final StateHolder sStateHolder =
new StateHolder(State.INITIAL, State.RUNNING);
// Inclusive
public boolean isBetween(final State min, final State max) {
return this.rank >= min.rank && this.rank <= max.rank;
}
/* package */ static StateHolder getStateHolder() {
return sStateHolder;
}
public static final State MIN_STATE = State.INITIAL;
public static final State MAX_STATE = State.EXITED;
private static volatile State sState = State.INITIAL;
private static class QueuedCall {
public Method method;
public Object target;
public Object[] args;
public State state;
public QueuedCall(final Method method, final Object target,
final Object[] args, final State state) {
this.method = method;
this.target = target;
this.args = args;
this.state = state;
}
}
private static final int QUEUED_CALLS_COUNT = 16;
private static final ArrayList<QueuedCall> QUEUED_CALLS = new ArrayList<>(QUEUED_CALLS_COUNT);
private static final Runnable UI_THREAD_CALLBACK = new Runnable() {
@Override
public void run() {
@ -259,153 +235,6 @@ public class GeckoThread extends Thread {
return isState(State.RUNNING);
}
// Invoke the given Method and handle checked Exceptions.
private static void invokeMethod(final Method method, final Object obj, final Object[] args) {
try {
method.setAccessible(true);
method.invoke(obj, args);
} catch (final IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
} catch (final InvocationTargetException e) {
throw new UnsupportedOperationException("Cannot make call", e.getCause());
}
}
// Queue a call to the given method.
private static void queueNativeCallLocked(final Class<?> cls, final String methodName,
final Object obj, final Object[] args,
final State state) {
final ArrayList<Class<?>> argTypes = new ArrayList<>(args.length);
final ArrayList<Object> argValues = new ArrayList<>(args.length);
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof Class) {
argTypes.add((Class<?>) args[i]);
argValues.add(args[++i]);
continue;
}
Class<?> argType = args[i].getClass();
if (argType == Boolean.class) argType = Boolean.TYPE;
else if (argType == Byte.class) argType = Byte.TYPE;
else if (argType == Character.class) argType = Character.TYPE;
else if (argType == Double.class) argType = Double.TYPE;
else if (argType == Float.class) argType = Float.TYPE;
else if (argType == Integer.class) argType = Integer.TYPE;
else if (argType == Long.class) argType = Long.TYPE;
else if (argType == Short.class) argType = Short.TYPE;
argTypes.add(argType);
argValues.add(args[i]);
}
final Method method;
try {
method = cls.getDeclaredMethod(
methodName, argTypes.toArray(new Class<?>[argTypes.size()]));
} catch (final NoSuchMethodException e) {
throw new IllegalArgumentException("Cannot find method", e);
}
if (!Modifier.isNative(method.getModifiers())) {
// As a precaution, we disallow queuing non-native methods. Queuing non-native
// methods is dangerous because the method could end up being called on either
// the original thread or the Gecko thread depending on timing. Native methods
// usually handle this by posting an event to the Gecko thread automatically,
// but there is no automatic mechanism for non-native methods.
throw new UnsupportedOperationException("Not allowed to queue non-native methods");
}
if (isStateAtLeast(state)) {
invokeMethod(method, obj, argValues.toArray());
return;
}
QUEUED_CALLS.add(new QueuedCall(
method, obj, argValues.toArray(), state));
}
/**
* Queue a call to the given static method until Gecko is in the given state.
*
* @param state The Gecko state in which the native call could be executed.
* Default is State.RUNNING, which means this queued call will
* run when Gecko is at or after RUNNING state.
* @param cls Class that declares the static method.
* @param methodName Name of the static method.
* @param args Args to call the static method with; to specify a parameter type,
* pass in a Class instance first, followed by the value.
*/
public static void queueNativeCallUntil(final State state, final Class<?> cls,
final String methodName, final Object... args) {
synchronized (QUEUED_CALLS) {
queueNativeCallLocked(cls, methodName, null, args, state);
}
}
/**
* Queue a call to the given static method until Gecko is in the RUNNING state.
*/
public static void queueNativeCall(final Class<?> cls, final String methodName,
final Object... args) {
synchronized (QUEUED_CALLS) {
queueNativeCallLocked(cls, methodName, null, args, State.RUNNING);
}
}
/**
* Queue a call to the given instance method until Gecko is in the given state.
*
* @param state The Gecko state in which the native call could be executed.
* @param obj Object that declares the instance method.
* @param methodName Name of the instance method.
* @param args Args to call the instance method with; to specify a parameter type,
* pass in a Class instance first, followed by the value.
*/
public static void queueNativeCallUntil(final State state, final Object obj,
final String methodName, final Object... args) {
synchronized (QUEUED_CALLS) {
queueNativeCallLocked(obj.getClass(), methodName, obj, args, state);
}
}
/**
* Queue a call to the given instance method until Gecko is in the RUNNING state.
*/
public static void queueNativeCall(final Object obj, final String methodName,
final Object... args) {
synchronized (QUEUED_CALLS) {
queueNativeCallLocked(obj.getClass(), methodName, obj, args, State.RUNNING);
}
}
// Run all queued methods
private static void flushQueuedNativeCallsLocked(final State state) {
int lastSkipped = -1;
for (int i = 0; i < QUEUED_CALLS.size(); i++) {
final QueuedCall call = QUEUED_CALLS.get(i);
if (call == null) {
// We already handled the call.
continue;
}
if (!state.isAtLeast(call.state)) {
// The call is not ready yet; skip it.
lastSkipped = i;
continue;
}
// Mark as handled.
QUEUED_CALLS.set(i, null);
invokeMethod(call.method, call.target, call.args);
}
if (lastSkipped < 0) {
// We're done here; release the memory
QUEUED_CALLS.clear();
QUEUED_CALLS.trimToSize();
} else if (lastSkipped < QUEUED_CALLS.size() - 1) {
// We skipped some; free up null entries at the end,
// but keep all the previous entries for later.
QUEUED_CALLS.subList(lastSkipped + 1, QUEUED_CALLS.size()).clear();
}
}
private static void loadGeckoLibs(final Context context, final String resourcePath) {
GeckoLoader.loadSQLiteLibs(context, resourcePath);
GeckoLoader.loadNSSLibs(context, resourcePath);
@ -617,7 +446,7 @@ public class GeckoThread extends Thread {
* @return True if the current Gecko thread state matches
*/
public static boolean isState(final State state) {
return sState.is(state);
return sStateHolder.getState().is(state);
}
/**
@ -628,7 +457,7 @@ public class GeckoThread extends Thread {
* @return True if the current Gecko thread state matches
*/
public static boolean isStateAtLeast(final State state) {
return sState.isAtLeast(state);
return sStateHolder.getState().isAtLeast(state);
}
/**
@ -639,7 +468,7 @@ public class GeckoThread extends Thread {
* @return True if the current Gecko thread state matches
*/
public static boolean isStateAtMost(final State state) {
return sState.isAtMost(state);
return state.isAtLeast(sStateHolder.getState());
}
/**
@ -651,28 +480,18 @@ public class GeckoThread extends Thread {
* @return True if the current Gecko thread state matches
*/
public static boolean isStateBetween(final State minState, final State maxState) {
return sState.isBetween(minState, maxState);
return isStateAtLeast(minState) && isStateAtMost(maxState);
}
@WrapForJNI(calledFrom = "gecko")
private static void setState(final State newState) {
ThreadUtils.assertOnGeckoThread();
synchronized (QUEUED_CALLS) {
flushQueuedNativeCallsLocked(newState);
sState = newState;
}
sStateHolder.setState(newState);
}
@WrapForJNI(calledFrom = "gecko")
private static boolean checkAndSetState(final State currentState, final State newState) {
synchronized (QUEUED_CALLS) {
if (sState == currentState) {
flushQueuedNativeCallsLocked(newState);
sState = newState;
return true;
}
}
return false;
private static boolean checkAndSetState(final State expectedState,
final State newState) {
return sStateHolder.checkAndSetState(expectedState, newState);
}
@WrapForJNI(stubName = "SpeculativeConnect")
@ -736,4 +555,36 @@ public class GeckoThread extends Thread {
private static void requestUiThreadCallback(long delay) {
ThreadUtils.getUiHandler().postDelayed(UI_THREAD_CALLBACK, delay);
}
/**
* Queue a call to the given static method until Gecko is in the RUNNING state.
*/
public static void queueNativeCall(final Class<?> cls, final String methodName,
final Object... args) {
NativeQueue.queueUntil(getStateHolder(), State.RUNNING, cls, methodName, args);
}
/**
* Queue a call to the given instance method until Gecko is in the RUNNING state.
*/
public static void queueNativeCall(final Object obj, final String methodName,
final Object... args) {
NativeQueue.queueUntil(getStateHolder(), State.RUNNING, obj, methodName, args);
}
/**
* Queue a call to the given instance method until Gecko is in the RUNNING state.
*/
public static void queueNativeCallUntil(final State state, final Object obj, final String methodName,
final Object... args) {
NativeQueue.queueUntil(getStateHolder(), state, obj, methodName, args);
}
/**
* Queue a call to the given static method until Gecko is in the RUNNING state.
*/
public static void queueNativeCallUntil(final State state, final Class<?> cls, final String methodName,
final Object... args) {
NativeQueue.queueUntil(getStateHolder(), state, cls, methodName, args);
}
}

Просмотреть файл

@ -12,6 +12,7 @@ import org.mozilla.gecko.annotation.ReflectionTarget;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.mozglue.JNIObject;
import org.mozilla.gecko.NativeQueue.StateHolder;
import org.mozilla.gecko.util.BundleEventListener;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoBundle;
@ -41,7 +42,40 @@ public class GeckoView extends LayerView
private static final boolean DEBUG = false;
private final EventDispatcher mEventDispatcher = new EventDispatcher();
/* package */ enum State implements NativeQueue.State {
@WrapForJNI INITIAL(0),
@WrapForJNI READY(1);
private int rank;
private State(int rank) {
this.rank = rank;
}
@Override
public boolean is(final NativeQueue.State other) {
return this == other;
}
@Override
public boolean isAtLeast(final NativeQueue.State other) {
if (other instanceof State) {
return this.rank >= ((State) other).rank;
}
return false;
}
}
private final StateHolder mStateHolder =
new StateHolder(State.INITIAL, State.READY);
@WrapForJNI(calledFrom = "gecko")
private void setState(final State newState) {
mStateHolder.setState(newState);
}
private final EventDispatcher mEventDispatcher =
new EventDispatcher(mStateHolder);
private ChromeDelegate mChromeDelegate;
/* package */ ContentListener mContentListener;

Просмотреть файл

@ -0,0 +1,219 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* 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/. */
package org.mozilla.gecko;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
public class NativeQueue {
private static final String LOGTAG = "GeckoNativeQueue";
public interface State {
boolean is(final State other);
boolean isAtLeast(final State other);
}
public static class StateHolder {
private volatile State mState;
private final State mReadyState;
public StateHolder(final State initial, final State ready) {
this.mState = initial;
this.mReadyState = ready;
}
public boolean isReady() {
return getState().isAtLeast(mReadyState);
}
public State getReadyState() {
return mReadyState;
}
public State getState() {
return mState;
}
public boolean setState(final State newState) {
return checkAndSetState(null, newState);
}
public boolean checkAndSetState(final State expectedState,
final State newState) {
synchronized (NativeQueue.sQueue) {
if (expectedState != null && !mState.is(expectedState)) {
return false;
}
NativeQueue.flushQueuedLocked(newState);
mState = newState;
return true;
}
}
}
private static class QueuedCall {
public Method method;
public Object target;
public Object[] args;
public State state;
public QueuedCall(final Method method, final Object target,
final Object[] args, final State state) {
this.method = method;
this.target = target;
this.args = args;
this.state = state;
}
}
private static final int QUEUED_CALLS_COUNT = 16;
/* package */ static final ArrayList<QueuedCall> sQueue =
new ArrayList<>(QUEUED_CALLS_COUNT);
// Invoke the given Method and handle checked Exceptions.
private static void invokeMethod(final Method method, final Object obj,
final Object[] args) {
try {
method.setAccessible(true);
method.invoke(obj, args);
} catch (final IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
} catch (final InvocationTargetException e) {
throw new UnsupportedOperationException("Cannot make call", e.getCause());
}
}
// Queue a call to the given method.
private static void queueNativeCallLocked(final StateHolder stateHolder,
final Class<?> cls,
final String methodName,
final Object obj,
final Object[] args,
final State state) {
final ArrayList<Class<?>> argTypes = new ArrayList<>(args.length);
final ArrayList<Object> argValues = new ArrayList<>(args.length);
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof Class) {
argTypes.add((Class<?>) args[i]);
argValues.add(args[++i]);
continue;
}
Class<?> argType = args[i].getClass();
if (argType == Boolean.class) argType = Boolean.TYPE;
else if (argType == Byte.class) argType = Byte.TYPE;
else if (argType == Character.class) argType = Character.TYPE;
else if (argType == Double.class) argType = Double.TYPE;
else if (argType == Float.class) argType = Float.TYPE;
else if (argType == Integer.class) argType = Integer.TYPE;
else if (argType == Long.class) argType = Long.TYPE;
else if (argType == Short.class) argType = Short.TYPE;
argTypes.add(argType);
argValues.add(args[i]);
}
final Method method;
try {
method = cls.getDeclaredMethod(
methodName, argTypes.toArray(new Class<?>[argTypes.size()]));
} catch (final NoSuchMethodException e) {
throw new IllegalArgumentException("Cannot find method", e);
}
if (!Modifier.isNative(method.getModifiers())) {
// As a precaution, we disallow queuing non-native methods. Queuing non-native
// methods is dangerous because the method could end up being called on either
// the original thread or the Gecko thread depending on timing. Native methods
// usually handle this by posting an event to the Gecko thread automatically,
// but there is no automatic mechanism for non-native methods.
throw new UnsupportedOperationException("Not allowed to queue non-native methods");
}
if (stateHolder.getState().isAtLeast(state)) {
invokeMethod(method, obj, argValues.toArray());
return;
}
sQueue.add(new QueuedCall(
method, obj, argValues.toArray(), state));
}
/**
* Queue a call to the given instance method if the given current state does
* not satisfy the given state.
*
* @param stateHolder The state holder used to query the current state.
* @param state The state in which the native call could be executed.
* @param obj Object that declares the instance method.
* @param methodName Name of the instance method.
* @param args Args to call the instance method with; to specify a parameter
* type, pass in a Class instance first, followed by the value.
*/
public static void queueUntil(final StateHolder stateHolder,
final State state,
final Object obj,
final String methodName,
final Object... args) {
synchronized (sQueue) {
queueNativeCallLocked(stateHolder, obj.getClass(), methodName, obj,
args, state);
}
}
/**
* Queue a call to the given static method if the given current state does
* not satisfy the given state.
*
* @param stateHolder The state holder used to query the current state.
* @param state The state in which the native call could be executed.
* @param cls Class that declares the static method.
* @param methodName Name of the instance method.
* @param args Args to call the instance method with; to specify a parameter
* type, pass in a Class instance first, followed by the value.
*/
public static void queueUntil(final StateHolder stateHolder,
final State state,
final Class<?> cls,
final String methodName,
final Object... args) {
synchronized (sQueue) {
queueNativeCallLocked(stateHolder, cls, methodName, null, args, state);
}
}
// Run all queued methods
private static void flushQueuedLocked(final State state) {
int lastSkipped = -1;
for (int i = 0; i < sQueue.size(); i++) {
final QueuedCall call = sQueue.get(i);
if (call == null) {
// We already handled the call.
continue;
}
if (!state.isAtLeast(call.state)) {
// The call is not ready yet; skip it.
lastSkipped = i;
continue;
}
// Mark as handled.
sQueue.set(i, null);
invokeMethod(call.method, call.target, call.args);
}
if (lastSkipped < 0) {
// We're done here; release the memory
sQueue.clear();
sQueue.trimToSize();
} else if (lastSkipped < sQueue.size() - 1) {
// We skipped some; free up null entries at the end,
// but keep all the previous entries for later.
sQueue.subList(lastSkipped + 1, sQueue.size()).clear();
}
}
}

Просмотреть файл

@ -2163,6 +2163,7 @@ nsHttpTransaction::Do0RTT()
nsresult
nsHttpTransaction::Finish0RTT(bool aRestart, bool aAlpnChanged /* ignored */)
{
LOG(("nsHttpTransaction::Finish0RTT %p %d %d\n", this, aRestart, aAlpnChanged));
MOZ_ASSERT(m0RTTInProgress);
m0RTTInProgress = false;
if (aRestart) {
@ -2174,6 +2175,10 @@ nsHttpTransaction::Finish0RTT(bool aRestart, bool aAlpnChanged /* ignored */)
} else {
return NS_ERROR_FAILURE;
}
} else if (!mConnected) {
// this is code that was skipped in ::ReadSegments while in 0RTT
mConnected = true;
mConnection->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
}
return NS_OK;
}

Просмотреть файл

@ -899,6 +899,8 @@ class TestInfoCommand(MachCommandBase):
@CommandArgument('--end',
default=date.today().strftime("%Y-%m-%d"),
help='End date (YYYY-MM-DD)')
@CommandArgument('--verbose', action='store_true',
help='Enable debug logging.')
def test_info(self, **params):
@ -909,6 +911,7 @@ class TestInfoCommand(MachCommandBase):
self.branches = params['branches']
self.start = params['start']
self.end = params['end']
self.verbose = params['verbose']
if len(self.test_name) < 6:
print("'%s' is too short for a test name!" % self.test_name)
@ -1055,9 +1058,16 @@ class TestInfoCommand(MachCommandBase):
def submit(self, query):
import requests
import datetime
if self.verbose:
print(datetime.datetime.now())
print(json.dumps(query))
response = requests.post("http://activedata.allizom.org/query",
data=json.dumps(query),
stream=True)
if self.verbose:
print(datetime.datetime.now())
print(response)
response.raise_for_status()
data = response.json()["data"]
return data
@ -1092,12 +1102,29 @@ class TestInfoCommand(MachCommandBase):
data = self.submit(query)
if data and len(data) > 0:
data.sort(key=self.get_platform)
worst_rate = 0.0
worst_platform = None
total_runs = 0
total_failures = 0
for record in data:
platform = self.get_platform(record)
runs = record['count']
total_runs = total_runs + runs
failures = record['failures']
total_failures = total_failures + failures
rate = (float)(failures) / runs
if rate >= worst_rate:
worst_rate = rate
worst_platform = platform
worst_failures = failures
worst_runs = runs
print("%-30s %6d failures in %6d runs" % (
platform, failures, runs))
print("\nTotal: %d failures in %d runs or %.3f failures/run" %
(total_failures, total_runs, (float)(total_failures) / total_runs))
if worst_failures > 0:
print("Worst rate on %s %d failures in %d runs or %.3f failures/run" %
(worst_platform, worst_failures, worst_runs, worst_rate))
else:
print("No test result data found.")

Просмотреть файл

@ -149,7 +149,7 @@ addTest(function(exception_t) {
if (Reflect.setPrototypeOf) {
assert_false(Reflect.setPrototypeOf(C, new Object()),
"Reflect.setPrototypeOf on cross-origin Window");
assert_false(Reflect.setPrototypeOf(C, new Object()),
assert_false(Reflect.setPrototypeOf(C.location, new Object()),
"Reflect.setPrototypeOf on cross-origin Location");
}
}, "[[SetPrototypeOf]] should return false");

Просмотреть файл

@ -267,6 +267,7 @@ fail-if = os == "android"
fail-if = os == "android"
[test_types.js]
[test_undothemeuninstall.js]
skip-if = appname == "thunderbird"
[test_undouninstall.js]
[test_uninstall.js]
[test_update.js]

Просмотреть файл

@ -11,98 +11,76 @@ tags = appupdate
head = head_update.js
[marSuccessComplete.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
[marSuccessPartial.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
[marFailurePartial.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
[marStageSuccessComplete.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
[marStageSuccessPartial.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
[marVersionDowngrade.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985 and mar signing
[marWrongChannel.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985 and mar signing
[marStageFailurePartial.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
[marCallbackAppSuccessComplete_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marCallbackAppSuccessPartial_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marCallbackAppStageSuccessComplete_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marCallbackAppStageSuccessPartial_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marAppInUseSuccessComplete.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985 and bug 1164150
[marAppInUseStageSuccessComplete_unix.js]
skip-if = os == 'win'
reason = not a Windows test and bug 1164150
reason = not a Windows test
[marAppInUseStageFailureComplete_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marFileLockedFailureComplete_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marFileLockedFailurePartial_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marFileLockedStageFailureComplete_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marFileLockedStageFailurePartial_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marFileInUseSuccessComplete_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marFileInUseSuccessPartial_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marRMRFDirFileInUseSuccessComplete_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marRMRFDirFileInUseSuccessPartial_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marFileInUseStageFailureComplete_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marFileInUseStageFailurePartial_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marRMRFDirFileInUseStageFailureComplete_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marRMRFDirFileInUseStageFailurePartial_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marAppApplyDirLockedStageFailure_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marAppApplyUpdateAppBinInUseStageSuccess_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test
[marAppApplyUpdateSuccess.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985 and bug 1164150
[marAppApplyUpdateStageSuccess.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985 and bug 1164150
[marWrongApplyToDirFailure_win.js]
skip-if = os != 'win' || debug && (os_version == '5.1' || os_version == '5.2')
reason = Windows only test and bug 1291985
skip-if = os != 'win'
reason = Windows only test

Просмотреть файл

@ -9,119 +9,61 @@ tags = appupdate
head = head_update.js
[bootstrapSvc.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marSuccessCompleteSvc.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marSuccessPartialSvc.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marFailurePartialSvc.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marStageSuccessCompleteSvc.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marStageSuccessPartialSvc.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marStageFailurePartialSvc.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marCallbackAppSuccessCompleteSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marCallbackAppSuccessPartialSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marCallbackAppStageSuccessCompleteSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marCallbackAppStageSuccessPartialSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marAppInUseSuccessCompleteSvc.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marAppInUseStageFailureCompleteSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marFileLockedFailureCompleteSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marFileLockedFailurePartialSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marFileLockedStageFailureCompleteSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marFileLockedStageFailurePartialSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marFileInUseSuccessCompleteSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marFileInUseSuccessPartialSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marRMRFDirFileInUseSuccessCompleteSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marRMRFDirFileInUseSuccessPartialSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marFileInUseStageFailureCompleteSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marFileInUseStageFailurePartialSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marRMRFDirFileInUseStageFailureCompleteSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marRMRFDirFileInUseStageFailurePartialSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marAppApplyDirLockedStageFailureSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marAppApplyUpdateAppBinInUseStageSuccessSvc_win.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marAppApplyUpdateSuccessSvc.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[marAppApplyUpdateStageSuccessSvc.js]
skip-if = os == 'win' && debug && (os_version == '5.1' || os_version == '5.2')
reason = bug 1291985
run-sequentially = Uses the Mozilla Maintenance Service.
[checkUpdaterSigSvc.js]

Просмотреть файл

@ -434,6 +434,8 @@ xul|button[type="menu"] > xul|menupopup xul|menuseparator {
/* textboxes */
html|input[type="email"],
html|input[type="tel"],
html|input[type="text"],
html|textarea,
xul|textbox {
@ -462,6 +464,8 @@ xul|textbox.tree-input {
padding-left: unset;
}
html|input[type="email"],
html|input[type="tel"],
html|input[type="text"],
html|textarea {
font-family: inherit;
@ -469,12 +473,16 @@ html|textarea {
padding: 5px 10px;
}
html|input[type="email"]:focus,
html|input[type="tel"]:focus,
html|input[type="text"]:focus,
html|textarea:focus,
xul|textbox[focused] {
border-color: var(--in-content-border-focus);
}
html|input[type="email"]:disabled,
html|input[type="tel"]:disabled,
html|input[type="text"]:disabled,
html|textarea:disabled,
xul|textbox[disabled="true"] {

Просмотреть файл

@ -1000,6 +1000,33 @@ auto GeckoThread::State::RUNNING() -> State::LocalRef
const char GeckoView::name[] =
"org/mozilla/gecko/GeckoView";
constexpr char GeckoView::SetState_t::name[];
constexpr char GeckoView::SetState_t::signature[];
auto GeckoView::SetState(mozilla::jni::Object::Param a0) const -> void
{
return mozilla::jni::Method<SetState_t>::Call(GeckoView::mCtx, nullptr, a0);
}
const char GeckoView::State::name[] =
"org/mozilla/gecko/GeckoView$State";
constexpr char GeckoView::State::INITIAL_t::name[];
constexpr char GeckoView::State::INITIAL_t::signature[];
auto GeckoView::State::INITIAL() -> State::LocalRef
{
return mozilla::jni::Field<INITIAL_t>::Get(State::Context(), nullptr);
}
constexpr char GeckoView::State::READY_t::name[];
constexpr char GeckoView::State::READY_t::signature[];
auto GeckoView::State::READY() -> State::LocalRef
{
return mozilla::jni::Field<READY_t>::Get(State::Context(), nullptr);
}
const char GeckoView::Window::name[] =
"org/mozilla/gecko/GeckoView$Window";

Просмотреть файл

@ -2989,14 +2989,85 @@ public:
explicit GeckoView(const Context& ctx) : ObjectBase<GeckoView>(ctx) {}
class State;
class Window;
struct SetState_t {
typedef GeckoView Owner;
typedef void ReturnType;
typedef void SetterType;
typedef mozilla::jni::Args<
mozilla::jni::Object::Param> Args;
static constexpr char name[] = "setState";
static constexpr char signature[] =
"(Lorg/mozilla/gecko/GeckoView$State;)V";
static const bool isStatic = false;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::GECKO;
static const mozilla::jni::DispatchTarget dispatchTarget =
mozilla::jni::DispatchTarget::CURRENT;
};
auto SetState(mozilla::jni::Object::Param) const -> void;
static const int32_t LOAD_DEFAULT = 0;
static const int32_t LOAD_NEW_TAB = 1;
static const int32_t LOAD_SWITCH_TAB = 2;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::GECKO;
};
class GeckoView::State : public mozilla::jni::ObjectBase<State>
{
public:
static const char name[];
explicit State(const Context& ctx) : ObjectBase<State>(ctx) {}
struct INITIAL_t {
typedef State Owner;
typedef State::LocalRef ReturnType;
typedef State::Param SetterType;
typedef mozilla::jni::Args<> Args;
static constexpr char name[] = "INITIAL";
static constexpr char signature[] =
"Lorg/mozilla/gecko/GeckoView$State;";
static const bool isStatic = true;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::ANY;
static const mozilla::jni::DispatchTarget dispatchTarget =
mozilla::jni::DispatchTarget::CURRENT;
};
static auto INITIAL() -> State::LocalRef;
struct READY_t {
typedef State Owner;
typedef State::LocalRef ReturnType;
typedef State::Param SetterType;
typedef mozilla::jni::Args<> Args;
static constexpr char name[] = "READY";
static constexpr char signature[] =
"Lorg/mozilla/gecko/GeckoView$State;";
static const bool isStatic = true;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::ANY;
static const mozilla::jni::DispatchTarget dispatchTarget =
mozilla::jni::DispatchTarget::CURRENT;
};
static auto READY() -> State::LocalRef;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::ANY;

Просмотреть файл

@ -509,10 +509,13 @@ nsAppShell::Init()
if (obsServ) {
obsServ->AddObserver(this, "browser-delayed-startup-finished", false);
obsServ->AddObserver(this, "profile-after-change", false);
obsServ->AddObserver(this, "chrome-document-loaded", false);
obsServ->AddObserver(this, "tab-child-created", false);
obsServ->AddObserver(this, "quit-application-granted", false);
obsServ->AddObserver(this, "xpcom-shutdown", false);
if (XRE_IsParentProcess()) {
obsServ->AddObserver(this, "chrome-document-loaded", false);
}
}
if (sPowerManagerService)
@ -582,8 +585,18 @@ nsAppShell::Observe(nsISupports* aSubject,
java::GeckoThread::State::PROFILE_READY(),
java::GeckoThread::State::RUNNING());
}
removeObserver = true;
// Enable the window event dispatcher for the given GeckoView.
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aSubject);
MOZ_ASSERT(doc);
nsCOMPtr<nsIWidget> widget =
WidgetUtils::DOMWindowToWidget(doc->GetWindow());
MOZ_ASSERT(widget);
if (widget->WindowType() == nsWindowType::eWindowType_toplevel) {
// Make sure to call this only on top level nsWindow.
const auto window = static_cast<nsWindow*>(widget.get());
window->EnableEventDispatcher();
}
} else if (!strcmp(aTopic, "quit-application-granted")) {
if (jni::IsAvailable()) {
java::GeckoThread::SetState(

Просмотреть файл

@ -237,12 +237,12 @@ public:
Impl* operator->() const { return mImpl; }
};
class nsWindow::GeckoViewSupport final
: public GeckoView::Window::Natives<GeckoViewSupport>
, public SupportsWeakPtr<GeckoViewSupport>
{
nsWindow& window;
GeckoView::GlobalRef mView;
public:
typedef GeckoView::Window::Natives<GeckoViewSupport> Base;
@ -268,6 +268,7 @@ public:
const GeckoView::Window::LocalRef& aInstance,
GeckoView::Param aView)
: window(*aWindow)
, mView(aView)
{
Base::AttachNative(aInstance, static_cast<SupportsWeakPtr*>(this));
}
@ -301,6 +302,8 @@ public:
jni::Object::Param aDispatcher);
void LoadUri(jni::String::Param aUri, int32_t aFlags);
void EnableEventDispatcher();
};
/**
@ -1535,6 +1538,15 @@ nsWindow::GetRootLayerId() const
return mCompositorSession ? mCompositorSession->RootLayerTreeId() : 0;
}
void
nsWindow::EnableEventDispatcher()
{
if (!mGeckoViewSupport) {
return;
}
mGeckoViewSupport->EnableEventDispatcher();
}
void
nsWindow::SetParent(nsIWidget *aNewParent)
{
@ -2061,6 +2073,13 @@ nsWindow::GetEventTimeStamp(int64_t aEventTime)
return TimeStamp::FromSystemTime(tick);
}
void
nsWindow::GeckoViewSupport::EnableEventDispatcher()
{
MOZ_ASSERT(mView);
mView->SetState(GeckoView::State::READY());
}
void
nsWindow::UserActivity()
{

Просмотреть файл

@ -50,6 +50,7 @@ public:
static void InitNatives();
void SetScreenId(uint32_t aScreenId) { mScreenId = aScreenId; }
void EnableEventDispatcher();
private:
uint32_t mScreenId;

Просмотреть файл

@ -38,24 +38,6 @@
#include "nsTraceRefcnt.h"
#include "nsErrorService.h"
// Disable deprecation warnings generated by nsISupportsArray and associated
// classes.
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning (push)
#pragma warning (disable : 4996)
#endif
#include "nsSupportsArray.h"
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning (pop)
#endif
#include "nsArray.h"
#include "nsINIParserImpl.h"
#include "nsSupportsPrimitives.h"

Просмотреть файл

@ -16,7 +16,6 @@
COMPONENT(PERSISTENTPROPERTIES, nsPersistentProperties::Create)
COMPONENT(SUPPORTSARRAY, nsSupportsArray::Create)
COMPONENT(ARRAY, nsArrayBase::XPCOMConstructor)
COMPONENT(CONSOLESERVICE, nsConsoleServiceConstructor)
COMPONENT(ATOMSERVICE, nsAtomServiceConstructor)

Просмотреть файл

@ -9,8 +9,6 @@ XPIDL_SOURCES += [
'nsIArrayExtensions.idl',
'nsIAtom.idl',
'nsIAtomService.idl',
'nsICollection.idl',
'nsIEnumerator.idl',
'nsIHashable.idl',
'nsIINIParser.idl',
'nsIMutableArray.idl',
@ -24,7 +22,6 @@ XPIDL_SOURCES += [
'nsISerializable.idl',
'nsISimpleEnumerator.idl',
'nsIStringEnumerator.idl',
'nsISupportsArray.idl',
'nsISupportsIterators.idl',
'nsISupportsPrimitives.idl',
'nsIVariant.idl',
@ -69,7 +66,6 @@ EXPORTS += [
'nsStaticAtom.h',
'nsStaticNameTable.h',
'nsStringEnumerator.h',
'nsSupportsArray.h',
'nsSupportsPrimitives.h',
'nsTArray-inl.h',
'nsTArray.h',
@ -108,8 +104,6 @@ UNIFIED_SOURCES += [
'nsProperties.cpp',
'nsQuickSort.cpp',
'nsStringEnumerator.cpp',
'nsSupportsArray.cpp',
'nsSupportsArrayEnumerator.cpp',
'nsSupportsPrimitives.cpp',
'nsTArray.cpp',
'nsTObserverArray.cpp',

Просмотреть файл

@ -1,67 +0,0 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISerializable.idl"
interface nsIEnumerator;
[deprecated, scriptable, uuid(83b6019c-cbc4-11d2-8cca-0060b0fc14a3)]
interface nsICollection : nsISerializable
{
uint32_t Count();
nsISupports GetElementAt(in uint32_t index);
void QueryElementAt(in uint32_t index, in nsIIDRef uuid,
[iid_is(uuid),retval] out nsQIResult result);
void SetElementAt(in uint32_t index, in nsISupports item);
void AppendElement(in nsISupports item);
void RemoveElement(in nsISupports item);
/**
* This clashes with |nsISimpleEnumerator nsIArray.enumerate()| (only on the
* binary side), so it is renamed with a 'Deprecated' prefix in favor of the
* non-deprecated |nsIArray.enumerate|.
*/
[binaryname(DeprecatedEnumerate)]
nsIEnumerator Enumerate();
void Clear();
};
%{C++
#ifndef nsCOMPtr_h__
#include "nsCOMPtr.h"
#endif
class MOZ_STACK_CLASS nsQueryElementAt : public nsCOMPtr_helper
{
public:
nsQueryElementAt( nsICollection* aCollection, uint32_t aIndex, nsresult* aErrorPtr )
: mCollection(aCollection),
mIndex(aIndex),
mErrorPtr(aErrorPtr)
{
// nothing else to do here
}
virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** )
const override;
private:
nsICollection* MOZ_NON_OWNING_REF mCollection;
uint32_t mIndex;
nsresult* mErrorPtr;
};
inline
const nsQueryElementAt
do_QueryElementAt( nsICollection* aCollection, uint32_t aIndex, nsresult* aErrorPtr = 0 )
{
return nsQueryElementAt(aCollection, aIndex, aErrorPtr);
}
%}

Просмотреть файл

@ -1,50 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
%{C++
#define NS_ENUMERATOR_FALSE 1
%}
/*
* DO NOT USE THIS INTERFACE. IT IS HORRIBLY BROKEN, USES NS_COMFALSE
* AND IS BASICALLY IMPOSSIBLE TO USE CORRECTLY THROUGH PROXIES OR
* XPCONNECT. IF YOU SEE NEW USES OF THIS INTERFACE IN CODE YOU ARE
* REVIEWING, YOU SHOULD INSIST ON nsISimpleEnumerator.
*
* DON'T MAKE ME COME OVER THERE.
*/
[deprecated, scriptable, uuid(ad385286-cbc4-11d2-8cca-0060b0fc14a3)]
interface nsIEnumerator : nsISupports {
/** First will reset the list. will return NS_FAILED if no items
*/
void first();
/** Next will advance the list. will return failed if already at end
*/
void next();
/** CurrentItem will return the CurrentItem item it will fail if the
* list is empty
*/
nsISupports currentItem();
/** return if the collection is at the end. that is the beginning following
* a call to Prev and it is the end of the list following a call to next
*/
void isDone();
};
[deprecated, uuid(75f158a0-cadd-11d2-8cca-0060b0fc14a3)]
interface nsIBidirectionalEnumerator : nsIEnumerator {
/** Last will reset the list to the end. will return NS_FAILED if no items
*/
void last();
/** Prev will decrement the list. will return failed if already at beginning
*/
void prev();
};

Просмотреть файл

@ -1,60 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsICollection.idl"
/*
* This entire interface is deprecated and should not be used.
* See nsIArray and nsIMutableArray for the new implementations.
*
* http://groups.google.com/groups?q=nsisupportsarray+group:netscape.public.mozilla.xpcom&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=3D779491.3050506%40netscape.com&rnum=2
* http://groups.google.com/groups?q=nsisupportsarray+group:netscape.public.mozilla.xpcom&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=al8412%245ab2%40ripley.netscape.com&rnum=8
*/
%{C++
class nsIBidirectionalEnumerator;
class nsISupportsArray;
#define NS_SUPPORTSARRAY_CID \
{ /* bda17d50-0d6b-11d3-9331-00104ba0fd40 */ \
0xbda17d50, \
0x0d6b, \
0x11d3, \
{0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
}
#define NS_SUPPORTSARRAY_CONTRACTID "@mozilla.org/supports-array;1"
%}
[deprecated, scriptable, uuid(241addc8-3608-4e73-8083-2fd6fa09eba2)]
interface nsISupportsArray : nsICollection {
[notxpcom] long IndexOf([const] in nsISupports aPossibleElement);
// xpcom-compatible versions
long GetIndexOf(in nsISupports aPossibleElement);
[notxpcom] boolean InsertElementAt(in nsISupports aElement,
in unsigned long aIndex);
[notxpcom] boolean ReplaceElementAt(in nsISupports aElement,
in unsigned long aIndex);
[notxpcom] boolean RemoveElementAt(in unsigned long aIndex);
// xpcom-compatible versions
void DeleteElementAt(in unsigned long aIndex);
nsISupportsArray clone();
};
%{C++
// Construct and return a default implementation of nsISupportsArray:
extern MOZ_MUST_USE nsresult
NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult);
%}

Просмотреть файл

@ -1,264 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdint.h>
#include <string.h>
#include "nsArrayEnumerator.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsSupportsArray.h"
#include "nsSupportsArrayEnumerator.h"
// Disable deprecation warnings generated by nsISupportsArray and associated
// classes.
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning (push)
#pragma warning (disable : 4996)
#endif
nsresult
nsQueryElementAt::operator()(const nsIID& aIID, void** aResult) const
{
nsresult status =
mCollection ? mCollection->QueryElementAt(mIndex, aIID, aResult) :
NS_ERROR_NULL_POINTER;
if (mErrorPtr) {
*mErrorPtr = status;
}
return status;
}
nsSupportsArray::nsSupportsArray()
{
}
nsSupportsArray::~nsSupportsArray()
{
Clear();
}
nsresult
nsSupportsArray::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
{
if (aOuter) {
return NS_ERROR_NO_AGGREGATION;
}
nsCOMPtr<nsISupportsArray> it = new nsSupportsArray();
return it->QueryInterface(aIID, aResult);
}
NS_IMPL_ISUPPORTS(nsSupportsArray, nsIArray, nsISupportsArray, nsICollection,
nsISerializable)
NS_IMETHODIMP
nsSupportsArray::Read(nsIObjectInputStream* aStream)
{
nsresult rv;
uint32_t newArraySize;
rv = aStream->Read32(&newArraySize);
if (NS_FAILED(rv)) {
return rv;
}
uint32_t count;
rv = aStream->Read32(&count);
if (NS_FAILED(rv)) {
return rv;
}
NS_ASSERTION(count <= newArraySize, "overlarge mCount!");
if (count > newArraySize) {
count = newArraySize;
}
// Don't clear out our array until we know we have enough space for the new
// one and have successfully copied everything out of the stream.
nsCOMArray<nsISupports> tmp;
tmp.SetCapacity(newArraySize);
tmp.SetCount(count);
auto elems = tmp.Elements();
for (uint32_t i = 0; i < count; i++) {
rv = aStream->ReadObject(true, &elems[i]);
if (NS_FAILED(rv)) {
return rv;
}
}
// Now clear out existing refs and replace with the new array.
mArray.Clear();
mArray.SwapElements(tmp);
return NS_OK;
}
NS_IMETHODIMP
nsSupportsArray::Write(nsIObjectOutputStream* aStream)
{
nsresult rv;
rv = aStream->Write32(mArray.Capacity());
if (NS_FAILED(rv)) {
return rv;
}
rv = aStream->Write32(mArray.Length());
if (NS_FAILED(rv)) {
return rv;
}
for (size_t i = 0; i < mArray.Length(); i++) {
rv = aStream->WriteObject(mArray[i], true);
if (NS_FAILED(rv)) {
return rv;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsSupportsArray::GetElementAt(uint32_t aIndex, nsISupports** aOutPtr)
{
nsCOMPtr<nsISupports> elm = mArray.SafeElementAt(aIndex);
elm.forget(aOutPtr);
return NS_OK;
}
NS_IMETHODIMP_(int32_t)
nsSupportsArray::IndexOf(const nsISupports* aPossibleElement)
{
// nsCOMArray takes a non-const param, but it just passes through to
// nsTArray which takes a const param.
return mArray.IndexOf(const_cast<nsISupports*>(aPossibleElement));
}
NS_IMETHODIMP_(bool)
nsSupportsArray::InsertElementAt(nsISupports* aElement, uint32_t aIndex)
{
return mArray.InsertObjectAt(aElement, aIndex);
}
NS_IMETHODIMP_(bool)
nsSupportsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex)
{
// nsCOMArray::ReplaceObjectAt will grow the array if necessary. Instead
// we do the bounds check and only replace if it's in range.
if (aIndex < mArray.Length()) {
mArray.ReplaceElementAt(aIndex, aElement);
return true;
}
return false;
}
NS_IMETHODIMP_(bool)
nsSupportsArray::RemoveElementAt(uint32_t aIndex)
{
return mArray.RemoveObjectAt(aIndex);
}
NS_IMETHODIMP
nsSupportsArray::RemoveElement(nsISupports* aElement)
{
return mArray.RemoveObject(aElement) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsSupportsArray::Clear(void)
{
mArray.Clear();
return NS_OK;
}
NS_IMETHODIMP
nsSupportsArray::DeprecatedEnumerate(nsIEnumerator** aResult)
{
RefPtr<nsSupportsArrayEnumerator> e = new nsSupportsArrayEnumerator(this);
e.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSupportsArray::Clone(nsISupportsArray** aResult)
{
nsCOMPtr<nsISupportsArray> newArray;
nsresult rv = NS_NewISupportsArray(getter_AddRefs(newArray));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
for (size_t i = 0; i < mArray.Length(); i++) {
// AppendElement does an odd cast of bool to nsresult, we just cast back
// here.
if (!(bool)newArray->AppendElement(mArray[i])) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
newArray.forget(aResult);
return NS_OK;
}
nsresult
NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult)
{
nsresult rv;
rv = nsSupportsArray::Create(nullptr, NS_GET_IID(nsISupportsArray),
(void**)aInstancePtrResult);
return rv;
}
/**
* nsIArray adapters.
*/
NS_IMETHODIMP
nsSupportsArray::GetLength(uint32_t* aLength) {
return Count(aLength);
}
NS_IMETHODIMP
nsSupportsArray::QueryElementAt(uint32_t aIndex, const nsIID& aIID, void** aResult)
{
nsISupports* element = mArray.SafeElementAt(aIndex);
if (element) {
return element->QueryInterface(aIID, aResult);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsSupportsArray::IndexOf(uint32_t aStartIndex, nsISupports* aElement, uint32_t* aResult)
{
int32_t idx = mArray.IndexOf(aElement, aStartIndex);
if (idx < 0) {
return NS_ERROR_FAILURE;
}
*aResult = static_cast<uint32_t>(idx);
return NS_OK;
}
NS_IMETHODIMP
nsSupportsArray::Enumerate(nsISimpleEnumerator** aResult)
{
return NS_NewArrayEnumerator(aResult, this);
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning (pop)
#endif

Просмотреть файл

@ -1,107 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef nsSupportsArray_h__
#define nsSupportsArray_h__
#include "nsIArray.h"
#include "nsCOMArray.h"
#include "mozilla/Attributes.h"
// Disable deprecation warnings generated by nsISupportsArray and associated
// classes.
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning (push)
#pragma warning (disable : 4996)
#endif
#include "nsISupportsArray.h"
class nsSupportsArray final : public nsISupportsArray,
public nsIArray
{
~nsSupportsArray(void); // nonvirtual since we're not subclassed
public:
nsSupportsArray(void);
static MOZ_MUST_USE nsresult
Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISERIALIZABLE
// nsICollection methods:
NS_IMETHOD Count(uint32_t* aResult) override
{
*aResult = mArray.Length();
return NS_OK;
}
NS_IMETHOD GetElementAt(uint32_t aIndex, nsISupports** aResult) override;
MOZ_MUST_USE NS_IMETHOD
SetElementAt(uint32_t aIndex, nsISupports* aValue) override
{
return ReplaceElementAt(aValue, aIndex) ? NS_OK : NS_ERROR_FAILURE;
}
MOZ_MUST_USE NS_IMETHOD AppendElement(nsISupports* aElement) override
{
// XXX Invalid cast of bool to nsresult (bug 778110)
return (nsresult)InsertElementAt(aElement, mArray.Length())/* ? NS_OK : NS_ERROR_FAILURE*/;
}
// XXX this is badly named - should be RemoveFirstElement
MOZ_MUST_USE NS_IMETHOD RemoveElement(nsISupports* aElement) override;
NS_IMETHOD DeprecatedEnumerate(nsIEnumerator** aResult) override;
NS_IMETHOD Clear(void) override;
// nsISupportsArray methods:
NS_IMETHOD_(int32_t) IndexOf(const nsISupports* aPossibleElement) override;
NS_IMETHOD GetIndexOf(nsISupports* aPossibleElement, int32_t* aResult) override
{
*aResult = IndexOf(aPossibleElement);
return NS_OK;
}
MOZ_MUST_USE NS_IMETHOD_(bool)
InsertElementAt(nsISupports* aElement, uint32_t aIndex) override;
MOZ_MUST_USE NS_IMETHOD_(bool)
ReplaceElementAt(nsISupports* aElement, uint32_t aIndex) override;
MOZ_MUST_USE NS_IMETHOD_(bool)
RemoveElementAt(uint32_t aIndex) override;
MOZ_MUST_USE NS_IMETHOD DeleteElementAt(uint32_t aIndex) override
{
return (RemoveElementAt(aIndex) ? NS_OK : NS_ERROR_FAILURE);
}
MOZ_MUST_USE NS_IMETHOD Clone(nsISupportsArray** aResult) override;
/**
* nsIArray adapters.
*/
NS_DECL_NSIARRAY
private:
// Copy constructors are not allowed
explicit nsSupportsArray(const nsISupportsArray& aOther);
nsCOMArray<nsISupports> mArray;
};
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning (pop)
#endif
#endif // nsSupportsArray_h__

Просмотреть файл

@ -1,131 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsSupportsArrayEnumerator.h"
// Disable deprecation warnings generated by nsISupportsArray and associated
// classes.
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning (push)
#pragma warning (disable : 4996)
#endif
#include "nsISupportsArray.h"
nsSupportsArrayEnumerator::nsSupportsArrayEnumerator(nsISupportsArray* array)
: mArray(array)
, mCursor(0)
{
NS_ASSERTION(array, "null array");
}
nsSupportsArrayEnumerator::~nsSupportsArrayEnumerator()
{
}
NS_IMPL_ISUPPORTS(nsSupportsArrayEnumerator, nsIBidirectionalEnumerator,
nsIEnumerator)
NS_IMETHODIMP
nsSupportsArrayEnumerator::First()
{
mCursor = 0;
uint32_t cnt;
nsresult rv = mArray->Count(&cnt);
if (NS_FAILED(rv)) {
return rv;
}
int32_t end = (int32_t)cnt;
if (mCursor < end) {
return NS_OK;
} else {
return NS_ERROR_FAILURE;
}
}
NS_IMETHODIMP
nsSupportsArrayEnumerator::Next()
{
uint32_t cnt;
nsresult rv = mArray->Count(&cnt);
if (NS_FAILED(rv)) {
return rv;
}
int32_t end = (int32_t)cnt;
if (mCursor < end) { // don't count upward forever
mCursor++;
}
if (mCursor < end) {
return NS_OK;
} else {
return NS_ERROR_FAILURE;
}
}
NS_IMETHODIMP
nsSupportsArrayEnumerator::CurrentItem(nsISupports** aItem)
{
NS_ASSERTION(aItem, "null out parameter");
uint32_t cnt;
nsresult rv = mArray->Count(&cnt);
if (NS_FAILED(rv)) {
return rv;
}
if (mCursor >= 0 && mCursor < (int32_t)cnt) {
return mArray->GetElementAt(mCursor, aItem);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsSupportsArrayEnumerator::IsDone()
{
uint32_t cnt;
nsresult rv = mArray->Count(&cnt);
if (NS_FAILED(rv)) {
return rv;
}
// XXX This is completely incompatible with the meaning of nsresult.
// NS_ENUMERATOR_FALSE is defined to be 1. (bug 778111)
return (mCursor >= 0 && mCursor < (int32_t)cnt)
? (nsresult)NS_ENUMERATOR_FALSE : NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsSupportsArrayEnumerator::Last()
{
uint32_t cnt;
nsresult rv = mArray->Count(&cnt);
if (NS_FAILED(rv)) {
return rv;
}
mCursor = cnt - 1;
return NS_OK;
}
NS_IMETHODIMP
nsSupportsArrayEnumerator::Prev()
{
if (mCursor >= 0) {
--mCursor;
}
if (mCursor >= 0) {
return NS_OK;
} else {
return NS_ERROR_FAILURE;
}
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning (pop)
#endif

Просмотреть файл

@ -1,56 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef nsSupportsArrayEnumerator_h___
#define nsSupportsArrayEnumerator_h___
#include "nsCOMPtr.h"
#include "mozilla/Attributes.h"
// Disable deprecation warnings generated by nsISupportsArray and associated
// classes.
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning (push)
#pragma warning (disable : 4996)
#endif
#include "nsIEnumerator.h"
class nsISupportsArray;
class nsSupportsArrayEnumerator final : public nsIBidirectionalEnumerator
{
public:
NS_DECL_ISUPPORTS
explicit nsSupportsArrayEnumerator(nsISupportsArray* aArray);
// nsIEnumerator methods:
NS_DECL_NSIENUMERATOR
// nsIBidirectionalEnumerator methods:
NS_DECL_NSIBIDIRECTIONALENUMERATOR
private:
~nsSupportsArrayEnumerator();
protected:
nsCOMPtr<nsISupportsArray> mArray;
int32_t mCursor;
};
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning (pop)
#endif
#endif // __nsSupportsArrayEnumerator_h

Просмотреть файл

@ -1,169 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include "gtest/gtest.h"
// Disable deprecation warnings generated by nsISupportsArray and associated
// classes.
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning (push)
#pragma warning (disable : 4996)
#endif
#include "nsISupportsArray.h"
// {9e70a320-be02-11d1-8031-006008159b5a}
#define NS_IFOO_IID \
{0x9e70a320, 0xbe02, 0x11d1, \
{0x80, 0x31, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}}
namespace TestArray {
class IFoo : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
NS_IMETHOD_(nsrefcnt) RefCnt() = 0;
NS_IMETHOD_(int32_t) ID() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(IFoo, NS_IFOO_IID)
class Foo final : public IFoo {
public:
explicit Foo(int32_t aID);
// nsISupports implementation
NS_DECL_ISUPPORTS
// IFoo implementation
NS_IMETHOD_(nsrefcnt) RefCnt() override { return mRefCnt; }
NS_IMETHOD_(int32_t) ID() override { return mID; }
static int32_t gCount;
int32_t mID;
private:
~Foo();
};
int32_t Foo::gCount;
Foo::Foo(int32_t aID)
{
mID = aID;
++gCount;
}
Foo::~Foo()
{
--gCount;
}
NS_IMPL_ISUPPORTS(Foo, IFoo)
void CheckArray(nsISupportsArray* aArray, int32_t aExpectedCount, int32_t aElementIDs[], int32_t aExpectedTotal)
{
uint32_t cnt = 0;
#ifdef DEBUG
nsresult rv =
#endif
aArray->Count(&cnt);
NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
int32_t count = cnt;
int32_t index;
EXPECT_EQ(Foo::gCount, aExpectedTotal);
EXPECT_EQ(count, aExpectedCount);
for (index = 0; (index < count) && (index < aExpectedCount); index++) {
nsCOMPtr<IFoo> foo = do_QueryElementAt(aArray, index);
EXPECT_EQ(foo->ID(), aElementIDs[index]);
}
}
void FillArray(nsISupportsArray* aArray, int32_t aCount)
{
int32_t index;
for (index = 0; index < aCount; index++) {
nsCOMPtr<IFoo> foo = new Foo(index);
aArray->AppendElement(foo);
}
}
} // namespace TestArray
using namespace TestArray;
TEST(Array, main)
{
nsISupportsArray* array;
nsresult rv;
if (NS_OK == (rv = NS_NewISupportsArray(&array))) {
FillArray(array, 10);
int32_t fillResult[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
CheckArray(array, 10, fillResult, 10);
// test insert
nsCOMPtr<IFoo> foo = do_QueryElementAt(array, 3);
array->InsertElementAt(foo, 5);
int32_t insertResult[11] = {0, 1, 2, 3, 4, 3, 5, 6, 7, 8, 9};
CheckArray(array, 11, insertResult, 10);
array->InsertElementAt(foo, 0);
int32_t insertResult2[12] = {3, 0, 1, 2, 3, 4, 3, 5, 6, 7, 8, 9};
CheckArray(array, 12, insertResult2, 10);
array->AppendElement(foo);
int32_t appendResult[13] = {3, 0, 1, 2, 3, 4, 3, 5, 6, 7, 8, 9, 3};
CheckArray(array, 13, appendResult, 10);
// test IndexOf
int32_t expectedIndex = 0;
int32_t index = array->IndexOf(foo);
EXPECT_EQ(index, expectedIndex);
// test ReplaceElementAt
array->ReplaceElementAt(foo, 8);
int32_t replaceResult[13] = {3, 0, 1, 2, 3, 4, 3, 5, 3, 7, 8, 9, 3};
CheckArray(array, 13, replaceResult, 9);
// test RemoveElementAt, RemoveElement
array->RemoveElementAt(0);
int32_t removeResult[12] = {0, 1, 2, 3, 4, 3, 5, 3, 7, 8, 9, 3};
CheckArray(array, 12, removeResult, 9);
array->RemoveElementAt(7);
int32_t removeResult2[11] = {0, 1, 2, 3, 4, 3, 5, 7, 8, 9, 3};
CheckArray(array, 11, removeResult2, 9);
array->RemoveElement(foo);
int32_t removeResult3[10] = {0, 1, 2, 4, 3, 5, 7, 8, 9, 3};
CheckArray(array, 10, removeResult3, 9);
foo = nullptr;
// test clear
array->Clear();
FillArray(array, 4);
CheckArray(array, 4, fillResult, 4);
// test delete
NS_RELEASE(array);
}
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning (pop)
#endif

Просмотреть файл

@ -9,6 +9,10 @@
#include "nsCRT.h"
#include "mozilla/TypeTraits.h"
#include <stdio.h>
#include <functional>
using mozilla::IsSame;
using mozilla::DeclVal;
/**************************************************************
Now define the token deallocator class...

Просмотреть файл

@ -6,7 +6,6 @@
UNIFIED_SOURCES += [
'Helpers.cpp',
'TestArray.cpp',
'TestAtoms.cpp',
'TestAutoPtr.cpp',
'TestAutoRef.cpp',

Просмотреть файл

@ -107,45 +107,6 @@ function test_enumerate()
do_check_eq(arr.length, i);
}
function test_nssupportsarray_interop() {
// Tests to check that an nsSupportsArray instance can behave like an
// nsIArray.
let test = Components.classes["@mozilla.org/supports-array;1"]
.createInstance(Ci.nsISupportsArray);
let str = new SupportsString();
str.data = "element";
test.AppendElement(str);
// Now query to an nsIArray.
let iarray = test.QueryInterface(Ci.nsIArray);
do_check_neq(iarray, null);
// Make sure |nsIArray.length| works.
do_check_eq(iarray.length, 1);
// Make sure |nsIArray.queryElementAt| works.
let elm = iarray.queryElementAt(0, Ci.nsISupportsString);
do_check_eq(elm.data, "element");
// Make sure |nsIArray.indexOf| works.
let idx = iarray.indexOf(0, str);
do_check_eq(idx, 0);
// Make sure |nsIArray.enumerate| works.
let en = iarray.enumerate();
do_check_neq(en, null);
let i = 0;
while (en.hasMoreElements()) {
let str = en.getNext();
do_check_true(str instanceof Ci.nsISupportsString);
do_check_eq(str.data, "element");
i++;
}
do_check_eq(iarray.length, i);
}
function test_nsiarrayextensions() {
// Tests to check that the extensions that make an nsArray act like an
// nsISupportsArray for iteration purposes works.
@ -174,7 +135,6 @@ var tests = [
test_replace_element,
test_clear,
test_enumerate,
test_nssupportsarray_interop,
test_nsiarrayextensions,
];