Merge autoland to central, a=merge

MozReview-Commit-ID: I3hgM0ng45o
This commit is contained in:
Wes Kocher 2017-02-27 13:12:25 -08:00
Родитель 035e4968ce bbacba9f0d
Коммит f448516b0f
88 изменённых файлов: 1608 добавлений и 881 удалений

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

@ -6,6 +6,7 @@
/* import-globals-from ../../../toolkit/content/treeUtils.js */
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/AppConstants.jsm");
const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
const nsICookiePermission = Components.interfaces.nsICookiePermission;
@ -334,6 +335,7 @@ var gPermissionManager = {
} else if (AppConstants.platform == "macosx" &&
aEvent.keyCode == KeyEvent.DOM_VK_BACK_SPACE) {
this.onPermissionDeleted();
aEvent.preventDefault();
}
},

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

@ -469,17 +469,18 @@ html, body, #app, #memory-tool {
}
.heap-tree-item-name {
/**
* Flex: contains an .arrow and some text, which need to be laid out
* horizontally, vertically aligned in the middle of the container.
*/
display: flex;
align-items: center;
/**
* Flexing to fill out remaining vertical space.
* @see .header and .heap-tree-item */
flex: 1;
padding-inline-start: 5px;
overflow: hidden;
text-overflow: ellipsis;
}
.heap-tree-item-name .arrow {
display: inline-block;
vertical-align: middle;
}
/**
@ -520,19 +521,16 @@ html, body, #app, #memory-tool {
}
.heap-tree-item-individuals {
width: 38px;
min-width: 20px;
min-width: 38px;
overflow: hidden;
margin: 0;
}
.heap-tree-item-individuals > button {
height: 10px;
width: 32px;
/* Override default styles for toolbar buttons to fix entire row height. */
margin: 0 auto !important;
padding: 0;
color: inherit;
}
/**

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

@ -47,6 +47,7 @@
#include "mozilla/Mutex.h"
#include "nsICancelable.h"
#include "nsUnicharUtils.h"
#include "mozilla/net/HttpAuthUtils.h"
//-----------------------------------------------------------------------------
@ -164,13 +165,13 @@ nsHttpNegotiateAuth::ChallengeReceived(nsIHttpAuthenticableChannel *authChannel,
else {
bool allowed = TestNotInPBMode(authChannel, isProxyAuth) &&
(TestNonFqdn(uri) ||
TestPref(uri, kNegotiateAuthTrustedURIs));
mozilla::net::auth::URIMatchesPrefPattern(uri, kNegotiateAuthTrustedURIs));
if (!allowed) {
LOG(("nsHttpNegotiateAuth::ChallengeReceived URI blocked\n"));
return NS_ERROR_ABORT;
}
bool delegation = TestPref(uri, kNegotiateAuthDelegationURIs);
bool delegation = mozilla::net::auth::URIMatchesPrefPattern(uri, kNegotiateAuthDelegationURIs);
if (delegation) {
LOG((" using REQ_DELEGATE\n"));
req_flags |= nsIAuthModule::REQ_DELEGATE;
@ -622,151 +623,3 @@ nsHttpNegotiateAuth::TestNonFqdn(nsIURI *uri)
return !host.IsEmpty() && !host.Contains('.') &&
PR_StringToNetAddr(host.BeginReading(), &addr) != PR_SUCCESS;
}
bool
nsHttpNegotiateAuth::TestPref(nsIURI *uri, const char *pref)
{
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (!prefs)
return false;
nsAutoCString scheme, host;
int32_t port;
if (NS_FAILED(uri->GetScheme(scheme)))
return false;
if (NS_FAILED(uri->GetAsciiHost(host)))
return false;
port = NS_GetRealPort(uri);
if (port == -1) {
return false;
}
char *hostList;
if (NS_FAILED(prefs->GetCharPref(pref, &hostList)) || !hostList)
return false;
struct FreePolicy { void operator()(void* p) { free(p); } };
mozilla::UniquePtr<char[], FreePolicy> hostListScope;
hostListScope.reset(hostList);
// pseudo-BNF
// ----------
//
// url-list base-url ( base-url "," LWS )*
// base-url ( scheme-part | host-part | scheme-part host-part )
// scheme-part scheme "://"
// host-part host [":" port]
//
// for example:
// "https://, http://office.foo.com"
//
mozilla::Tokenizer t(hostList);
while (!t.CheckEOF()) {
t.SkipWhites();
nsDependentCSubstring url;
mozilla::Unused << t.ReadUntil(mozilla::Tokenizer::Token::Char(','), url);
if (url.IsEmpty()) {
continue;
}
if (MatchesBaseURI(scheme, host, port, url)) {
return true;
}
}
return false;
}
bool
nsHttpNegotiateAuth::MatchesBaseURI(const nsCSubstring &matchScheme,
const nsCSubstring &matchHost,
int32_t matchPort,
nsDependentCSubstring const& url)
{
// check if scheme://host:port matches baseURI
// parse the base URI
mozilla::Tokenizer t(url);
mozilla::Tokenizer::Token token;
t.SkipWhites();
// We don't know if the url to check against starts with scheme
// or a host name. Start recording here.
t.Record();
mozilla::Unused << t.Next(token);
// The ipv6 literals MUST be enclosed with [] in the preference.
bool ipv6 = false;
if (token.Equals(mozilla::Tokenizer::Token::Char('['))) {
nsDependentCSubstring ipv6BareLiteral;
if (!t.ReadUntil(mozilla::Tokenizer::Token::Char(']'), ipv6BareLiteral)) {
// Broken ipv6 literal
return false;
}
nsDependentCSubstring ipv6Literal;
t.Claim(ipv6Literal, mozilla::Tokenizer::INCLUDE_LAST);
if (!matchHost.Equals(ipv6Literal, nsCaseInsensitiveUTF8StringComparator()) &&
!matchHost.Equals(ipv6BareLiteral, nsCaseInsensitiveUTF8StringComparator())) {
return false;
}
ipv6 = true;
} else if (t.CheckChar(':') && t.CheckChar('/') && t.CheckChar('/')) {
if (!matchScheme.Equals(token.Fragment())) {
return false;
}
// Re-start recording the hostname from the point after scheme://.
t.Record();
}
while (t.Next(token)) {
bool eof = token.Equals(mozilla::Tokenizer::Token::EndOfFile());
bool port = token.Equals(mozilla::Tokenizer::Token::Char(':'));
if (eof || port) {
if (!ipv6) { // Match already performed above.
nsDependentCSubstring hostName;
t.Claim(hostName);
// An empty hostname means to accept everything for the schema
if (!hostName.IsEmpty()) {
if (hostName.First() == '.') {
if (!StringEndsWith(matchHost, hostName, nsCaseInsensitiveUTF8StringComparator())) {
return false;
}
} else { // host to match doesn't begin with '.', do a full compare
if (!matchHost.Equals(hostName, nsCaseInsensitiveUTF8StringComparator())) {
return false;
}
}
}
}
if (port) {
uint16_t portNumber;
if (!t.ReadInteger(&portNumber)) {
// Missing port number
return false;
}
if (matchPort != portNumber) {
return false;
}
if (!t.CheckEOF()) {
return false;
}
}
} else if (ipv6) {
// After an ipv6 literal there can only be EOF or :port. Everything else
// must be treated as non-match/broken input.
return false;
}
}
// All negative checks has passed positively.
return true;
}

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

@ -30,13 +30,6 @@ private:
// tests if the host part of an uri is fully qualified
bool TestNonFqdn(nsIURI *uri);
// returns true if URI is accepted by the list of hosts in the pref
bool TestPref(nsIURI *, const char *pref);
bool MatchesBaseURI(const nsCSubstring &scheme,
const nsCSubstring &host,
int32_t port,
nsDependentCSubstring const& url);
// Thread for GenerateCredentialsAsync
RefPtr<mozilla::LazyIdleThread> mNegotiateThread;
};

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

@ -11,7 +11,7 @@
#include "mozilla/TimeStamp.h"
#include "mozilla/Maybe.h"
#if !defined(OS_WIN) && !defined(OS_NETBSD) && !defined(OS_OPENBSD) && !defined(OS_MACOSX)
#if !defined(OS_WIN) && !defined(OS_MACOSX)
#include <pthread.h>
#include <semaphore.h>
#include "SharedMemoryBasic.h"
@ -30,7 +30,7 @@ struct ParamTraits;
namespace mozilla {
#if defined(OS_WIN)
typedef HANDLE CrossProcessSemaphoreHandle;
#elif !defined(OS_NETBSD) && !defined(OS_OPENBSD) && !defined(OS_MACOSX)
#elif !defined(OS_MACOSX)
typedef mozilla::ipc::SharedMemoryBasic::Handle CrossProcessSemaphoreHandle;
#else
// Stub for other platforms. We can't use uintptr_t here since different
@ -86,7 +86,7 @@ private:
#if defined(OS_WIN)
HANDLE mSemaphore;
#elif !defined(OS_NETBSD) && !defined(OS_OPENBSD) && !defined(OS_MACOSX)
#elif !defined(OS_MACOSX)
RefPtr<mozilla::ipc::SharedMemoryBasic> mSharedBuffer;
sem_t* mSemaphore;
mozilla::Atomic<int32_t>* mRefCount;

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

@ -86,7 +86,7 @@ if CONFIG['OS_ARCH'] == 'WINNT':
SOURCES += [
'CrossProcessSemaphore_windows.cpp',
]
elif not CONFIG['OS_ARCH'] in ('NetBSD', 'OpenBSD', 'Darwin'):
elif CONFIG['OS_ARCH'] != 'Darwin':
UNIFIED_SOURCES += [
'CrossProcessSemaphore_posix.cpp',
]

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

@ -360,6 +360,35 @@ GeneratePrototypeGuards(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
}
}
static void
GeneratePrototypeHoleGuards(CacheIRWriter& writer, JSObject* obj, ObjOperandId objId)
{
if (obj->hasUncacheableProto()) {
// If the shape does not imply the proto, emit an explicit proto guard.
writer.guardProto(objId, obj->staticPrototype());
}
JSObject* pobj = obj->staticPrototype();
while (pobj) {
ObjOperandId protoId = writer.loadObject(pobj);
// Non-singletons with uncacheable protos can change their proto
// without a shape change, so also guard on the group (which determines
// the proto) in this case.
if (pobj->hasUncacheableProto() && !pobj->isSingleton())
writer.guardGroup(protoId, pobj->group());
// Make sure the shape matches, to avoid non-dense elements or anything
// else that is being checked by CanAttachDenseElementHole.
writer.guardShape(protoId, pobj->as<NativeObject>().lastProperty());
// Also make sure there are no dense elements.
writer.guardNoDenseElements(protoId);
pobj = pobj->staticPrototype();
}
}
static void
TestMatchingReceiver(CacheIRWriter& writer, JSObject* obj, Shape* shape, ObjOperandId objId,
Maybe<ObjOperandId>* expandoId)
@ -1338,31 +1367,7 @@ GetPropIRGenerator::tryAttachDenseElementHole(HandleObject obj, ObjOperandId obj
// Guard on the shape, to prevent non-dense elements from appearing.
writer.guardShape(objId, obj->as<NativeObject>().lastProperty());
if (obj->hasUncacheableProto()) {
// If the shape does not imply the proto, emit an explicit proto guard.
writer.guardProto(objId, obj->staticPrototype());
}
JSObject* pobj = obj->staticPrototype();
while (pobj) {
ObjOperandId protoId = writer.loadObject(pobj);
// Non-singletons with uncacheable protos can change their proto
// without a shape change, so also guard on the group (which determines
// the proto) in this case.
if (pobj->hasUncacheableProto() && !pobj->isSingleton())
writer.guardGroup(protoId, pobj->group());
// Make sure the shape matches, to avoid non-dense elements or anything
// else that is being checked by CanAttachDenseElementHole.
writer.guardShape(protoId, pobj->as<NativeObject>().lastProperty());
// Also make sure there are no dense elements.
writer.guardNoDenseElements(protoId);
pobj = pobj->staticPrototype();
}
GeneratePrototypeHoleGuards(writer, obj, objId);
writer.loadDenseElementHoleResult(objId, indexId);
writer.typeMonitorResult();
@ -1768,6 +1773,30 @@ InIRGenerator::tryAttachDenseIn(uint32_t index, Int32OperandId indexId,
return true;
}
bool
InIRGenerator::tryAttachDenseInHole(uint32_t index, Int32OperandId indexId,
HandleObject obj, ObjOperandId objId)
{
if (!obj->isNative())
return false;
if (obj->as<NativeObject>().containsDenseElement(index))
return false;
if (!CanAttachDenseElementHole(obj))
return false;
// Guard on the shape, to prevent non-dense elements from appearing.
writer.guardShape(objId, obj->as<NativeObject>().lastProperty());
GeneratePrototypeHoleGuards(writer, obj, objId);
writer.loadDenseElementHoleExistsResult(objId, indexId);
writer.returnFromIC();
trackAttached("DenseInHole");
return true;
}
bool
InIRGenerator::tryAttachNativeIn(HandleId key, ValOperandId keyId,
HandleObject obj, ObjOperandId objId)
@ -1843,6 +1872,8 @@ InIRGenerator::tryAttachStub()
if (maybeGuardInt32Index(key_, keyId, &index, &indexId)) {
if (tryAttachDenseIn(index, indexId, obj_, objId))
return true;
if (tryAttachDenseInHole(index, indexId, obj_, objId))
return true;
trackNotAttached();
return false;

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

@ -212,6 +212,7 @@ extern const char* CacheKindNames[];
_(LoadDenseElementResult) \
_(LoadDenseElementHoleResult) \
_(LoadDenseElementExistsResult) \
_(LoadDenseElementHoleExistsResult) \
_(LoadUnboxedArrayElementResult) \
_(LoadTypedElementResult) \
_(LoadInt32ArrayLengthResult) \
@ -804,6 +805,10 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
writeOpWithOperandId(CacheOp::LoadDenseElementExistsResult, obj);
writeOperandId(index);
}
void loadDenseElementHoleExistsResult(ObjOperandId obj, Int32OperandId index) {
writeOpWithOperandId(CacheOp::LoadDenseElementHoleExistsResult, obj);
writeOperandId(index);
}
void loadUnboxedArrayElementResult(ObjOperandId obj, Int32OperandId index, JSValueType elementType) {
writeOpWithOperandId(CacheOp::LoadUnboxedArrayElementResult, obj);
writeOperandId(index);
@ -1186,6 +1191,8 @@ class MOZ_RAII InIRGenerator : public IRGenerator
bool tryAttachDenseIn(uint32_t index, Int32OperandId indexId,
HandleObject obj, ObjOperandId objId);
bool tryAttachDenseInHole(uint32_t index, Int32OperandId indexId,
HandleObject obj, ObjOperandId objId);
bool tryAttachNativeIn(HandleId key, ValOperandId keyId,
HandleObject obj, ObjOperandId objId);
bool tryAttachNativeInDoesNotExist(HandleId key, ValOperandId keyId,

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

@ -1911,6 +1911,44 @@ CacheIRCompiler::emitLoadDenseElementExistsResult()
return true;
}
bool
CacheIRCompiler::emitLoadDenseElementHoleExistsResult()
{
AutoOutputRegister output(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register index = allocator.useRegister(masm, reader.int32OperandId());
AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
// Make sure the index is nonnegative.
masm.branch32(Assembler::LessThan, index, Imm32(0), failure->label());
// Load obj->elements.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
// Guard on the initialized length.
Label hole;
Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::BelowOrEqual, initLength, index, &hole);
// Load value and replace with true.
Label done;
masm.loadValue(BaseObjectElementIndex(scratch, index), output.valueReg());
masm.branchTestMagic(Assembler::Equal, output.valueReg(), &hole);
masm.moveValue(BooleanValue(true), output.valueReg());
masm.jump(&done);
// Load false for the hole.
masm.bind(&hole);
masm.moveValue(BooleanValue(false), output.valueReg());
masm.bind(&done);
return true;
}
bool
CacheIRCompiler::emitLoadUnboxedArrayElementResult()
{

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

@ -48,6 +48,7 @@ namespace jit {
_(LoadDenseElementResult) \
_(LoadDenseElementHoleResult) \
_(LoadDenseElementExistsResult) \
_(LoadDenseElementHoleExistsResult) \
_(LoadUnboxedArrayElementResult) \
_(LoadTypedElementResult) \
_(WrapResult)

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

@ -1289,7 +1289,7 @@ nsFlexContainerFrame::CSSAlignmentForAbsPosChild(
} else {
// Single-line, or multi-line but the (one) line stretches to fill
// container. Respect align-self.
alignment = aChildRI.mStylePosition->UsedAlignSelf(nullptr);
alignment = aChildRI.mStylePosition->UsedAlignSelf(StyleContext());
// XXX strip off <overflow-position> bits until we implement it
// (bug 1311892)
alignment &= ~NS_STYLE_ALIGN_FLAG_BITS;
@ -1310,8 +1310,6 @@ nsFlexContainerFrame::CSSAlignmentForAbsPosChild(
alignment = isAxisReversed ? NS_STYLE_ALIGN_END : NS_STYLE_ALIGN_START;
} else if (alignment == NS_STYLE_ALIGN_FLEX_END) {
alignment = isAxisReversed ? NS_STYLE_ALIGN_START : NS_STYLE_ALIGN_END;
} else if (alignment == NS_STYLE_ALIGN_AUTO) {
alignment = NS_STYLE_ALIGN_START;
} else if (alignment == NS_STYLE_ALIGN_LEFT ||
alignment == NS_STYLE_ALIGN_RIGHT) {
if (aLogicalAxis == eLogicalAxisInline) {

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

@ -6657,20 +6657,14 @@ nsGridContainerFrame::CSSAlignmentForAbsPosChild(const ReflowInput& aChildRI,
"This method should only be called for abspos children");
uint16_t alignment = (aLogicalAxis == eLogicalAxisInline) ?
aChildRI.mStylePosition->UsedJustifySelf(nullptr) :
aChildRI.mStylePosition->UsedAlignSelf(nullptr);
aChildRI.mStylePosition->UsedJustifySelf(StyleContext()) :
aChildRI.mStylePosition->UsedAlignSelf(StyleContext());
// XXX strip off <overflow-position> bits until we implement it
// (bug 1311892)
alignment &= ~NS_STYLE_ALIGN_FLAG_BITS;
// We group 'auto' with 'normal', because the spec says:
// "The 'auto' keyword is interpreted as 'normal'
// if the box is absolutely positioned [...]"
// https://drafts.csswg.org/css-align-3/#valdef-align-self-auto
// https://drafts.csswg.org/css-align-3/#valdef-justify-self-auto
if (alignment == NS_STYLE_ALIGN_AUTO ||
alignment == NS_STYLE_ALIGN_NORMAL) {
if (alignment == NS_STYLE_ALIGN_NORMAL) {
// "the 'normal' keyword behaves as 'start' on replaced
// absolutely-positioned boxes, and behaves as 'stretch' on all other
// absolutely-positioned boxes."

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

@ -925,8 +925,8 @@ fails == 407243-1.html 407243-1.html
== 407937-1.html 407937-1.html
== 408493-1.html 408493-1.html
== 408493-2.html 408493-2.html
fails == 408656-1a.html 408656-1a.html
fails == 408656-1b.html 408656-1b.html
== 408656-1a.html 408656-1a.html
== 408656-1b.html 408656-1b.html
== 408656-1c.html 408656-1c.html
fails == 408782-1a.html 408782-1a.html
fails == 408782-1b.html 408782-1b.html

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

@ -34,5 +34,5 @@ fails == column-balancing-nested-000.html column-balancing-nested-000.html
fails == column-balancing-nested-001.html column-balancing-nested-001.html
== columnrule-overflow.html columnrule-overflow.html
== columns-table-caption-000.html columns-table-caption-000.html
fails == positioning-transforms-bug1112501.html positioning-transforms-bug1112501.html
== positioning-transforms-bug1112501.html positioning-transforms-bug1112501.html
== fieldset-columns-001.html fieldset-columns-001.html

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

@ -14,7 +14,7 @@ random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == sync-image-switch-1d.htm
# Tests for "object-fit" & "object-position"
pref(layout.css.object-fit-and-position.enabled,true) == image-object-fit-dyn-1.html image-object-fit-dyn-1.html
skip-if(stylo) fails pref(layout.css.object-fit-and-position.enabled,true) == image-object-fit-with-background-1.html image-object-fit-with-background-1.html # Bug 1342188
fails skip-if(stylo) pref(layout.css.object-fit-and-position.enabled,true) == image-object-fit-with-background-1.html image-object-fit-with-background-1.html # Bug 1342188
fails pref(layout.css.object-fit-and-position.enabled,true) == image-object-fit-with-background-2.html image-object-fit-with-background-2.html
pref(layout.css.object-fit-and-position.enabled,true) == image-object-position-dyn-1.html image-object-position-dyn-1.html
fails pref(layout.css.object-fit-and-position.enabled,true) == image-object-position-with-background-1.html image-object-position-with-background-1.html

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

@ -47,7 +47,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -73,7 +73,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -20,6 +20,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
align-items: center; /* To exercise 'align-self: auto' on children */
}
br { clear: both }

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

@ -47,7 +47,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -73,7 +73,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -20,6 +20,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
align-items: center; /* To exercise 'align-self: auto' on children */
}
br { clear: both }

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

@ -50,7 +50,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -76,7 +76,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -20,6 +20,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
align-items: center; /* To exercise 'align-self: auto' on children */
}
br { clear: both }

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

@ -50,7 +50,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -76,7 +76,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -20,6 +20,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
align-items: center; /* To exercise 'align-self: auto' on children */
}
br { clear: both }

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

@ -47,7 +47,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -73,7 +73,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -20,6 +20,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
align-items: center; /* To exercise 'align-self: auto' on children */
}
br { clear: both }

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

@ -47,7 +47,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -73,7 +73,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -20,6 +20,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
align-items: center; /* To exercise 'align-self: auto' on children */
}
br { clear: both }

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

@ -50,7 +50,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -76,7 +76,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -20,6 +20,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
align-items: center; /* To exercise 'align-self: auto' on children */
}
br { clear: both }

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

@ -50,7 +50,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -76,7 +76,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -20,6 +20,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
align-items: center; /* To exercise 'align-self: auto' on children */
}
br { clear: both }

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

@ -48,7 +48,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -74,7 +74,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -19,6 +19,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
align-items: center; /* To exercise 'align-self: auto' on children */
position: relative;
}
br { clear: both }

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

@ -46,7 +46,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -72,7 +72,7 @@
<!-- The various align-self values, from
https://www.w3.org/TR/css-align-3/#propdef-align-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -19,6 +19,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
align-items: center; /* To exercise 'align-self: auto' on children */
}
br { clear: both }

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

@ -49,7 +49,7 @@
<!-- The various justify-self values, from
https://www.w3.org/TR/css-align-3/#propdef-justify-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -75,7 +75,7 @@
<!-- The various justify-self values, from
https://www.w3.org/TR/css-align-3/#propdef-justify-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -19,6 +19,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
justify-items: center; /* To exercise 'justify-self: auto' on children */
position: relative;
}
br { clear: both }

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

@ -47,7 +47,7 @@
<!-- The various justify-self values, from
https://www.w3.org/TR/css-align-3/#propdef-justify-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>
@ -73,7 +73,7 @@
<!-- The various justify-self values, from
https://www.w3.org/TR/css-align-3/#propdef-justify-self -->
<!-- auto | normal | stretch -->
<div class="container"><div class="alignStart"><!--auto--></div></div>
<div class="container"><div class="alignCenter"><!--auto--></div></div>
<div class="container"><div class="alignStart"><!--normal--></div></div>
<div class="container"><div class="alignStart"><!--stretch--></div></div>
<br>

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

@ -19,6 +19,7 @@
margin-bottom: 5px;
margin-right: 5px;
float: left; /* For testing in "rows" of containers */
justify-items: center; /* To exercise 'justify-self: auto' on children */
}
br { clear: both }

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

@ -0,0 +1,171 @@
#include "mozilla/net/HttpAuthUtils.h"
#include "mozilla/Tokenizer.h"
#include "nsIPrefService.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsUnicharUtils.h"
namespace mozilla {
namespace net {
namespace auth {
namespace detail {
bool
MatchesBaseURI(const nsCSubstring &matchScheme,
const nsCSubstring &matchHost,
int32_t matchPort,
nsDependentCSubstring const& url)
{
// check if scheme://host:port matches baseURI
// parse the base URI
mozilla::Tokenizer t(url);
mozilla::Tokenizer::Token token;
t.SkipWhites();
// We don't know if the url to check against starts with scheme
// or a host name. Start recording here.
t.Record();
mozilla::Unused << t.Next(token);
// The ipv6 literals MUST be enclosed with [] in the preference.
bool ipv6 = false;
if (token.Equals(mozilla::Tokenizer::Token::Char('['))) {
nsDependentCSubstring ipv6BareLiteral;
if (!t.ReadUntil(mozilla::Tokenizer::Token::Char(']'), ipv6BareLiteral)) {
// Broken ipv6 literal
return false;
}
nsDependentCSubstring ipv6Literal;
t.Claim(ipv6Literal, mozilla::Tokenizer::INCLUDE_LAST);
if (!matchHost.Equals(ipv6Literal, nsCaseInsensitiveUTF8StringComparator()) &&
!matchHost.Equals(ipv6BareLiteral, nsCaseInsensitiveUTF8StringComparator())) {
return false;
}
ipv6 = true;
} else if (t.CheckChar(':') && t.CheckChar('/') && t.CheckChar('/')) {
if (!matchScheme.Equals(token.Fragment())) {
return false;
}
// Re-start recording the hostname from the point after scheme://.
t.Record();
}
while (t.Next(token)) {
bool eof = token.Equals(mozilla::Tokenizer::Token::EndOfFile());
bool port = token.Equals(mozilla::Tokenizer::Token::Char(':'));
if (eof || port) {
if (!ipv6) { // Match already performed above.
nsDependentCSubstring hostName;
t.Claim(hostName);
// An empty hostname means to accept everything for the schema
if (!hostName.IsEmpty()) {
if (hostName.First() == '.') {
if (!StringEndsWith(matchHost, hostName, nsCaseInsensitiveUTF8StringComparator())) {
return false;
}
} else { // host to match doesn't begin with '.', do a full compare
if (!matchHost.Equals(hostName, nsCaseInsensitiveUTF8StringComparator())) {
return false;
}
}
}
}
if (port) {
uint16_t portNumber;
if (!t.ReadInteger(&portNumber)) {
// Missing port number
return false;
}
if (matchPort != portNumber) {
return false;
}
if (!t.CheckEOF()) {
return false;
}
}
} else if (ipv6) {
// After an ipv6 literal there can only be EOF or :port. Everything else
// must be treated as non-match/broken input.
return false;
}
}
// All negative checks has passed positively.
return true;
}
} // namespace detail
bool
URIMatchesPrefPattern(nsIURI *uri, const char *pref)
{
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (!prefs) {
return false;
}
nsAutoCString scheme, host;
int32_t port;
if (NS_FAILED(uri->GetScheme(scheme))) {
return false;
}
if (NS_FAILED(uri->GetAsciiHost(host))) {
return false;
}
port = NS_GetRealPort(uri);
if (port == -1) {
return false;
}
char *hostList;
if (NS_FAILED(prefs->GetCharPref(pref, &hostList)) || !hostList) {
return false;
}
struct FreePolicy { void operator()(void* p) { free(p); } };
mozilla::UniquePtr<char[], FreePolicy> hostListScope;
hostListScope.reset(hostList);
// pseudo-BNF
// ----------
//
// url-list base-url ( base-url "," LWS )*
// base-url ( scheme-part | host-part | scheme-part host-part )
// scheme-part scheme "://"
// host-part host [":" port]
//
// for example:
// "https://, http://office.foo.com"
//
mozilla::Tokenizer t(hostList);
while (!t.CheckEOF()) {
t.SkipWhites();
nsDependentCSubstring url;
mozilla::Unused << t.ReadUntil(mozilla::Tokenizer::Token::Char(','), url);
if (url.IsEmpty()) {
continue;
}
if (detail::MatchesBaseURI(scheme, host, port, url)) {
return true;
}
}
return false;
}
} // namespace auth
} // namespace net
} // namespace mozilla

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

@ -0,0 +1,32 @@
/* 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 HttpAuthUtils_h__
#define HttpAuthUtils_h__
class nsIURI;
namespace mozilla { namespace net { namespace auth {
/* Tries to match the given URI against the value of a given pref
*
* The pref should be in pseudo-BNF format.
* url-list base-url ( base-url "," LWS )*
* base-url ( scheme-part | host-part | scheme-part host-part )
* scheme-part scheme "://"
* host-part host [":" port]
*
* for example:
* "https://, http://office.foo.com"
*
* Will return true if the URI matches any of the patterns, or false otherwise.
*/
bool URIMatchesPrefPattern(nsIURI *uri, const char *pref);
} // namespace auth
} // namespace net
} // namespace mozilla
#endif // HttpAuthUtils_h__

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

@ -38,6 +38,7 @@ EXPORTS += [
EXPORTS.mozilla.net += [
'AltDataOutputStreamChild.h',
'AltDataOutputStreamParent.h',
'HttpAuthUtils.h',
'HttpBaseChannel.h',
'HttpChannelChild.h',
'HttpChannelParent.h',
@ -67,6 +68,7 @@ UNIFIED_SOURCES += [
'Http2Push.cpp',
'Http2Session.cpp',
'Http2Stream.cpp',
'HttpAuthUtils.cpp',
'HttpBaseChannel.cpp',
'HttpChannelChild.cpp',
'HttpChannelParent.cpp',

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

@ -33,6 +33,7 @@
#include "nsNetUtil.h"
#include "nsIChannel.h"
#include "nsUnicharUtils.h"
#include "mozilla/net/HttpAuthUtils.h"
namespace mozilla {
namespace net {
@ -43,102 +44,6 @@ static const char kTrustedURIs[] = "network.automatic-ntlm-auth.trusted-uris";
static const char kForceGeneric[] = "network.auth.force-generic-ntlm";
static const char kSSOinPBmode[] = "network.auth.private-browsing-sso";
// XXX MatchesBaseURI and TestPref are duplicated in nsHttpNegotiateAuth.cpp,
// but since that file lives in a separate library we cannot directly share it.
// bug 236865 addresses this problem.
static bool
MatchesBaseURI(const nsCSubstring &matchScheme,
const nsCSubstring &matchHost,
int32_t matchPort,
nsDependentCSubstring const& url)
{
// check if scheme://host:port matches baseURI
// parse the base URI
mozilla::Tokenizer t(url);
mozilla::Tokenizer::Token token;
t.SkipWhites();
// We don't know if the url to check against starts with scheme
// or a host name. Start recording here.
t.Record();
mozilla::Unused << t.Next(token);
// The ipv6 literals MUST be enclosed with [] in the preference.
bool ipv6 = false;
if (token.Equals(mozilla::Tokenizer::Token::Char('['))) {
nsDependentCSubstring ipv6BareLiteral;
if (!t.ReadUntil(mozilla::Tokenizer::Token::Char(']'), ipv6BareLiteral)) {
// Broken ipv6 literal
return false;
}
nsDependentCSubstring ipv6Literal;
t.Claim(ipv6Literal, mozilla::Tokenizer::INCLUDE_LAST);
if (!matchHost.Equals(ipv6Literal, nsCaseInsensitiveUTF8StringComparator()) &&
!matchHost.Equals(ipv6BareLiteral, nsCaseInsensitiveUTF8StringComparator())) {
return false;
}
ipv6 = true;
} else if (t.CheckChar(':') && t.CheckChar('/') && t.CheckChar('/')) {
if (!matchScheme.Equals(token.Fragment())) {
return false;
}
// Re-start recording the hostname from the point after scheme://.
t.Record();
}
while (t.Next(token)) {
bool eof = token.Equals(mozilla::Tokenizer::Token::EndOfFile());
bool port = token.Equals(mozilla::Tokenizer::Token::Char(':'));
if (eof || port) {
if (!ipv6) { // Match already performed above.
nsDependentCSubstring hostName;
t.Claim(hostName);
// An empty hostname means to accept everything for the schema
if (!hostName.IsEmpty()) {
if (hostName.First() == '.') {
if (!StringEndsWith(matchHost, hostName, nsCaseInsensitiveUTF8StringComparator())) {
return false;
}
} else { // host to match doesn't begin with '.', do a full compare
if (!matchHost.Equals(hostName, nsCaseInsensitiveUTF8StringComparator())) {
return false;
}
}
}
}
if (port) {
uint16_t portNumber;
if (!t.ReadInteger(&portNumber)) {
// Missing port number
return false;
}
if (matchPort != portNumber) {
return false;
}
if (!t.CheckEOF()) {
return false;
}
}
} else if (ipv6) {
// After an ipv6 literal there can only be EOF or :port. Everything else
// must be treated as non-match/broken input.
return false;
}
}
// All negative checks has passed positively.
return true;
}
static bool
IsNonFqdn(nsIURI *uri)
{
@ -153,59 +58,6 @@ IsNonFqdn(nsIURI *uri)
PR_StringToNetAddr(host.BeginReading(), &addr) != PR_SUCCESS;
}
static bool
TestPref(nsIURI *uri, const char *pref)
{
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (!prefs)
return false;
nsAutoCString scheme, host;
int32_t port;
if (NS_FAILED(uri->GetScheme(scheme)))
return false;
if (NS_FAILED(uri->GetAsciiHost(host)))
return false;
if (NS_FAILED(uri->GetPort(&port)))
return false;
char *hostList;
if (NS_FAILED(prefs->GetCharPref(pref, &hostList)) || !hostList)
return false;
struct FreePolicy { void operator()(void* p) { free(p); } };
mozilla::UniquePtr<char[], FreePolicy> hostListScope;
hostListScope.reset(hostList);
// pseudo-BNF
// ----------
//
// url-list base-url ( base-url "," LWS )*
// base-url ( scheme-part | host-part | scheme-part host-part )
// scheme-part scheme "://"
// host-part host [":" port]
//
// for example:
// "https://, http://office.foo.com"
//
mozilla::Tokenizer t(hostList);
while (!t.CheckEOF()) {
t.SkipWhites();
nsDependentCSubstring url;
mozilla::Unused << t.ReadUntil(mozilla::Tokenizer::Token::Char(','), url);
if (url.IsEmpty()) {
continue;
}
if (MatchesBaseURI(scheme, host, port, url)) {
return true;
}
}
return false;
}
// Check to see if we should use our generic (internal) NTLM auth module.
static bool
ForceGenericNTLM()
@ -274,7 +126,7 @@ CanUseDefaultCredentials(nsIHttpAuthenticableChannel *channel,
return true;
}
bool isTrustedHost = (uri && TestPref(uri, kTrustedURIs));
bool isTrustedHost = (uri && auth::URIMatchesPrefPattern(uri, kTrustedURIs));
LOG(("Default credentials allowed for host: %d\n", isTrustedHost));
return isTrustedHost;
}

62
servo/Cargo.lock сгенерированный
Просмотреть файл

@ -293,7 +293,7 @@ dependencies = [
"cssparser 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -585,8 +585,8 @@ dependencies = [
name = "deny_public_fields"
version = "0.0.1"
dependencies = [
"syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -630,7 +630,7 @@ version = "0.0.1"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -653,7 +653,7 @@ name = "domobject_derive"
version = "0.0.1"
dependencies = [
"quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -955,7 +955,7 @@ dependencies = [
"gfx_traits 0.0.1",
"harfbuzz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
@ -996,7 +996,7 @@ name = "gfx_traits"
version = "0.0.1"
dependencies = [
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"range 0.0.1",
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1092,12 +1092,12 @@ dependencies = [
[[package]]
name = "heapsize_derive"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1129,11 +1129,11 @@ dependencies = [
[[package]]
name = "html5ever"
version = "0.13.0"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1141,7 +1141,7 @@ dependencies = [
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1151,7 +1151,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1297,8 +1297,8 @@ name = "jstraceable_derive"
version = "0.0.1"
dependencies = [
"quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1643,7 +1643,7 @@ dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.20.0 (git+https://github.com/servo/webrender)",
@ -1728,7 +1728,7 @@ version = "0.0.1"
dependencies = [
"cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2112,7 +2112,7 @@ name = "range"
version = "0.0.1"
dependencies = [
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2231,8 +2231,8 @@ dependencies = [
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_traits 0.0.1",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2295,7 +2295,7 @@ dependencies = [
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_traits 0.0.1",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2336,7 +2336,7 @@ dependencies = [
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_traits 0.0.1",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2617,7 +2617,7 @@ name = "servo_url"
version = "0.0.1"
dependencies = [
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_rand 0.0.1",
@ -2736,7 +2736,7 @@ dependencies = [
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2795,7 +2795,7 @@ dependencies = [
"cssparser-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2851,11 +2851,11 @@ dependencies = [
[[package]]
name = "synstructure"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -3436,11 +3436,11 @@ dependencies = [
"checksum glx 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b280007fa9c7442cfd1e0b1addb8d1a59240267110e8705f8f7e2c7bfb7e2f72"
"checksum harfbuzz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6b76113246f5c089dcf272cf89c3f61168a4d77b50ec5b2c1fab8c628c9ea762"
"checksum heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5a376f7402b85be6e0ba504243ecbc0709c48019ecc6286d0540c2e359050c88"
"checksum heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b6876925b6c3de6f9073f016f425de0076ab68cf30522107fa586ae6524abfe"
"checksum heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "46f96d52fb1564059fc97b85ef6165728cc30198ab60073bf114c66c4c89bb5d"
"checksum heartbeats-simple 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad003ce233955e9d95f2c69cde84e68302ba9ba4a673d351c9bff93c738aadc"
"checksum heartbeats-simple-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e1a408c0011427cc0e0049f7861c70377819aedfc006e8c901b1c70fd98fb1a4"
"checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58"
"checksum html5ever 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43c1b50a0c2b4f697c025699ae33b2b4072fff5b6cbd7c184e25eea2beccb3ef"
"checksum html5ever 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d60508177ec4e5774a112efcf4d4d5f123cb00a43476fa5940b7da568371a165"
"checksum html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9bd86e3b6a5a7933a272cc0a854f24e371f31576e585c0b41e8f857270c5134"
"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d"
"checksum hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)" = "1b9bf64f730d6ee4b0528a5f0a316363da9d8104318731509d4ccc86248f82b3"
@ -3559,7 +3559,7 @@ dependencies = [
"checksum syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "58fd09df59565db3399efbba34ba8a2fec1307511ebd245d0061ff9d42691673"
"checksum syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0e28da8d02d75d1e58b89258e0741128f0b0d8a8309fb5c627be0fbd37a76c67"
"checksum synom 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8fece1853fb872b0acdc3ff88f37c474018e125ef81cd4cb8c0ca515746b62ed"
"checksum synstructure 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e13808dc5a739d5ff1cff4a2361afdf4ec52d42221c7ddc1d8c438f5a53746a7"
"checksum synstructure 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ccc9780bf1aa601943988c2876ab22413c01ad1739689aa6af18d0aa0b3f38b"
"checksum syntex 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb3f52553a966675982404dc34028291b347e0c9a9c0b0b34f2da6be8a0443f8"
"checksum syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dee2f6e49c075f71332bb775219d5982bee6732d26227fa1ae1b53cdb12f5cc5"
"checksum syntex_pos 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df3921c7945dfb9ffc53aa35adb2cf4313b5ab5f079c3619b3d4eb82a0efc2b"

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

@ -10,5 +10,5 @@ path = "lib.rs"
proc-macro = true
[dependencies]
syn = "0.10"
synstructure = "0.4"
syn = "0.11"
synstructure = "0.5"

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

@ -10,5 +10,5 @@ path = "lib.rs"
proc-macro = true
[dependencies]
syn = "0.10"
syn = "0.11"
quote = "0.3"

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

@ -10,6 +10,6 @@ path = "lib.rs"
proc-macro = true
[dependencies]
syn = "0.10"
quote = "0.3"
synstructure = "0.4"
syn = "0.11"
synstructure = "0.5"

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

@ -4,38 +4,7 @@
use rustc::hir::def_id::DefId;
use rustc::lint::{LateContext, LintContext};
use syntax::ast;
use syntax::codemap::{ExpnFormat, Span};
use syntax::ptr::P;
/// Matches a type with a provided string, and returns its type parameters if successful
pub fn match_ty_unwrap<'a>(ty: &'a ast::Ty, segments: &[&str]) -> Option<&'a [P<ast::Ty>]> {
match ty.node {
ast::TyKind::Path(_, ast::Path { segments: ref seg, .. }) => {
// So hir::Path isn't the full path, just the tokens that were provided.
// I could muck around with the maps and find the full path
// however the more efficient way is to simply reverse the iterators and zip them
// which will compare them in reverse until one of them runs out of segments
if seg.iter().rev().zip(segments.iter().rev()).all(|(a, b)| &*a.identifier.name.as_str() == *b) {
match seg.last() {
Some(&ast::PathSegment { parameters: Some(ref params), .. }) => {
match **params {
ast::PathParameters::AngleBracketed(ref a) => Some(&a.types),
// `Foo(A,B) -> C`
ast::PathParameters::Parenthesized(_) => None,
}
}
Some(&ast::PathSegment { parameters: None, .. }) => Some(&[]),
None => None,
}
} else {
None
}
},
_ => None
}
}
/// check if a DefId's path matches the given absolute type path
/// usage e.g. with

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

@ -1413,10 +1413,26 @@ fn static_assert() {
self.gecko.mDisplay = result;
self.gecko.mOriginalDisplay = result;
}
/// Set the display value from the style adjustment code. This is pretty
/// much like set_display, but without touching the mOriginalDisplay field,
/// which we want to keep.
pub fn set_adjusted_display(&mut self, v: longhands::display::computed_value::T) {
use properties::longhands::display::computed_value::T as Keyword;
let result = match v {
% for value in display_keyword.values_for('gecko'):
Keyword::${to_rust_ident(value)} =>
structs::${display_keyword.gecko_constant(value)},
% endfor
};
self.gecko.mDisplay = result;
}
pub fn copy_display_from(&mut self, other: &Self) {
self.gecko.mDisplay = other.gecko.mDisplay;
self.gecko.mOriginalDisplay = other.gecko.mOriginalDisplay;
self.gecko.mOriginalDisplay = other.gecko.mDisplay;
}
<%call expr="impl_keyword_clone('display', 'mDisplay', display_keyword)"></%call>
// overflow-y is implemented as a newtype of overflow-x, so we need special handling.

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

@ -1949,13 +1949,15 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D<Au>,
};
if let Some(computed_display) = computed_display {
let box_ = style.mutate_box();
box_.set_display(computed_display);
% if product == "servo":
box_.set_display(computed_display);
box_.set__servo_display_for_hypothetical_box(if blockify_root || blockify_item {
computed_display
} else {
specified_display
});
% else:
box_.set_adjusted_display(computed_display);
% endif
}
}

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

@ -1504,9 +1504,11 @@ pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSet
// Append missing property values in the initial or the finial keyframes.
if step.start_percentage.0 == 0. ||
step.start_percentage.0 == 1. {
for (index, property) in animation.properties_changed.iter().enumerate() {
let mut index = unsafe { (*keyframe).mPropertyValues.len() };
for property in animation.properties_changed.iter() {
if !seen.has_transition_property_bit(&property) {
add_computed_property_value(keyframe, index, style, property);
index += 1;
}
}
}

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

@ -1,5 +1,8 @@
[package]
name = "test"
version = "*"
version = "0.0.1"
authors = ["The Servo Project Developers"]
publish = false
[dependencies]
test-package = { version = "*" }

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

@ -144,11 +144,12 @@ macosx64/debug:
build-platform: macosx64/debug
test-sets:
- macosx64-tests-debug
# Disable bbb talos tests for mac until we disable bb scheduling
# macosx64/opt:
# build-platform: macosx64/opt
# test-sets:
# - macosx64-tests-talos
# - macosx64-tests-debug
##
# Android platforms (matching /android.*/)

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

@ -134,23 +134,26 @@ windows-vm-tests:
macosx64-tests-debug:
- cppunit
- crashtest
# - gtest
- external-media-tests-base
- external-media-tests-youtube
- gtest
- jittest
- jsreftest
# - marionette
# - mochitest
# - mochitest-a11y
# - mochitest-browser-chrome
# - mochitest-chrome
# - mochitest-clipboard
# - mochitest-devtools-chrome
# - mochitest-gpu
# - mochitest-jetpack
# - mochitest-media
- marionette
- mochitest
- mochitest-a11y
- mochitest-browser-chrome
- mochitest-chrome
- mochitest-clipboard
- mochitest-devtools-chrome
- mochitest-gpu
- mochitest-jetpack
- mochitest-media
- mochitest-webgl
# - reftest
# - web-platform-tests
# - web-platform-tests-reftests
# - xpcshell
- reftest
- web-platform-tests
- web-platform-tests-reftests
- xpcshell
macosx64-tests-talos:
- talos-chrome

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

@ -63,6 +63,7 @@ crashtest:
by-test-platform:
windows.*: false # Bug 1304435
linux64-ccov/opt: false
macosx64/debug: true
default: both
mozharness:
by-test-platform:
@ -75,7 +76,7 @@ crashtest:
- --test-suite=crashtest
default:
script: desktop_unittest.py
chunked: true
chunked: false
no-read-buildbot-config: true
config:
by-test-platform:
@ -93,6 +94,7 @@ crashtest:
external-media-tests-base:
description: "External Media Test run"
suite: external-media-tests
unittest-try-name: 'media-tests'
treeherder-symbol: tc-VP(b-m)
e10s: false
tier: 2
@ -116,6 +118,7 @@ external-media-tests-twitch:
description: "External Media Test Twitch run"
suite: external-media-tests/twitch
treeherder-symbol: tc-VP(b-t)
unittest-try-name: media-twitch-tests
e10s: false
tier: 2
max-run-time: 5400
@ -139,6 +142,7 @@ external-media-tests-twitch:
external-media-tests-youtube:
description: "External Media Test Youtube run"
suite: external-media-tests/youtube
unittest-try-name: media-youtube-tests
treeherder-symbol: tc-VP(b-y)
e10s: false
tier: 2
@ -232,8 +236,14 @@ jittest:
chunks:
by-test-platform:
windows.*: 1
macosx.*: 1
default: 6
mozharness:
chunked:
by-test-platform:
windows.*: false
macosx.*: false
default: true
script: desktop_unittest.py
no-read-buildbot-config: true
config:
@ -264,6 +274,7 @@ jsreftest:
android.*: 10
windows.*: 2
linux64-qr/.*: 4
macosx.*: 2
default: 3
e10s:
by-test-platform:
@ -293,6 +304,7 @@ jsreftest:
default:
script: desktop_unittest.py
no-read-buildbot-config: true
chunked: true
config:
by-test-platform:
windows.*:
@ -331,6 +343,7 @@ marionette:
e10s:
by-test-platform:
linux64-ccov/opt: false
macosx.*: true
default: both
mozharness:
by-test-platform:
@ -379,6 +392,7 @@ mochitest:
linux64-ccov/opt: false
linux64-jsdcov/opt: false
android.*: false
macosx64/debug: true
default: both
max-run-time:
by-test-platform:
@ -430,7 +444,7 @@ mochitest-a11y:
mozharness:
script: desktop_unittest.py
no-read-buildbot-config: true
chunked: true
chunked: false
config:
by-test-platform:
windows.*:
@ -463,6 +477,7 @@ mochitest-browser-chrome:
by-test-platform:
linux64-jsdcov/opt: false
linux64-ccov/opt: false
macosx64/debug: true
default: both
max-run-time:
by-test-platform:
@ -474,6 +489,7 @@ mochitest-browser-chrome:
mozharness:
script: desktop_unittest.py
no-read-buildbot-config: true
chunked: true
config:
by-test-platform:
windows.*:
@ -540,7 +556,6 @@ mochitest-chrome:
by-test-platform:
android-4.3-arm7-api-15/debug: 4
android.*: 2
macosx.*: 1
default: 3
max-run-time: 3600
e10s: false
@ -560,6 +575,7 @@ mochitest-chrome:
default:
script: desktop_unittest.py
no-read-buildbot-config: true
chunked: true
config:
by-test-platform:
windows.*:
@ -579,6 +595,10 @@ mochitest-clipboard:
treeherder-symbol: tc-M(cl)
loopback-video: true
instance-size: xlarge
e10s:
by-test-platform:
macosx64/debug: true
default: both
mozharness:
by-test-platform:
android.*:
@ -592,7 +612,7 @@ mochitest-clipboard:
default:
script: desktop_unittest.py
no-read-buildbot-config: true
chunked: true
chunked: false
config:
by-test-platform:
windows.*:
@ -618,6 +638,7 @@ mochitest-devtools-chrome:
chunks:
by-test-platform:
windows.*: 8
macosx.*: 8
default: 10
run-on-projects:
by-test-platform:
@ -629,10 +650,12 @@ mochitest-devtools-chrome:
linux64-jsdcov/opt: false
# Bug 1304433: mochitest-devtools-chrome (e10s) not greened on windows
windows.*: false
macosx64/debug: true
default: both
mozharness:
script: desktop_unittest.py
no-read-buildbot-config: true
chunked: true
config:
by-test-platform:
windows.*:
@ -671,6 +694,7 @@ mochitest-gpu:
by-test-platform:
windows.*: both
android.*: false
macosx64/opt: both
default: true
mozharness:
by-test-platform:
@ -685,7 +709,7 @@ mochitest-gpu:
default:
script: desktop_unittest.py
no-read-buildbot-config: true
chunked: true
chunked: false
config:
by-test-platform:
windows.*:
@ -714,7 +738,7 @@ mochitest-jetpack:
mozharness:
script: desktop_unittest.py
no-read-buildbot-config: true
chunked: true
chunked: false
config:
by-test-platform:
windows.*:
@ -735,6 +759,10 @@ mochitest-media:
treeherder-symbol: tc-M(mda)
max-run-time: 5400
loopback-video: true
e10s:
by-test-platform:
macosx64/debug: true
default: both
instance-size:
by-test-platform:
android.*: xlarge
@ -742,6 +770,7 @@ mochitest-media:
chunks:
by-test-platform:
android.*: 3
macosx64.*: 1
default: 3
docker-image: {"in-tree": "desktop1604-test"}
mozharness:
@ -756,7 +785,10 @@ mochitest-media:
default:
script: desktop_unittest.py
no-read-buildbot-config: true
chunked: true
chunked:
by-test-platform:
macosx64.*: false
default: true
config:
by-test-platform:
windows.*:
@ -805,6 +837,10 @@ mochitest-webgl:
by-test-platform:
android.*: 10
default: 3
e10s:
by-test-platform:
macosx64/opt: false
default: both
loopback-video: true
max-run-time:
by-test-platform:
@ -876,7 +912,8 @@ reftest:
by-test-platform:
android-4.3-arm7-api-15/debug: 48
android.*: 16
macosx.*: 1
macosx64/opt: 1
macosx64/debug: 2
default: 8
max-run-time:
by-test-platform:
@ -898,6 +935,10 @@ reftest:
default:
script: desktop_unittest.py
no-read-buildbot-config: true
chunked:
by-test-platform:
macosx64/opt: false
default: true
config:
by-test-platform:
windows.*:
@ -1154,14 +1195,16 @@ talos-tp5o:
web-platform-tests:
description: "Web platform test run"
suite: web-platform-tests
treeherder-symbol: tc-W()
treeherder-symbol: tc-W(wpt)
chunks:
by-test-platform:
macosx.*: 5
macosx64/opt: 5
macosx64/debug: 10
default: 12
e10s:
by-test-platform:
linux64-ccov/opt: false
macosx.*: true
default: both
max-run-time: 7200
instance-size: xlarge
@ -1174,6 +1217,7 @@ web-platform-tests:
mozharness:
script: web_platform_tests.py
no-read-buildbot-config: true
chunked: true
config:
by-test-platform:
windows.*:
@ -1241,7 +1285,7 @@ xpcshell:
by-test-platform:
linux64-jsdcov/opt: xpcshell-coverage
default: xpcshell
treeherder-symbol: tc-X()
treeherder-symbol: tc-X(X)
run-on-projects:
by-test-platform:
linux64-qr/.*: ['graphics']

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

@ -32,7 +32,7 @@ def talos_task(n, tp):
tasks = {k: v for k, v in [
unittest_task('mochitest-browser-chrome', 'linux'),
unittest_task('mochitest-e10s-browser-chrome', 'linux64'),
unittest_task('mochitest-browser-chrome-e10s', 'linux64'),
unittest_task('mochitest-chrome', 'linux'),
unittest_task('mochitest-webgl', 'linux'),
unittest_task('crashtest-e10s', 'linux'),

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

@ -20,15 +20,14 @@ JOB_NAME_WHITELIST = set([
'android-api-15-gradle-dependencies-opt',
'android-api-15-gradle-opt',
'android-api-15-opt',
'android-api-15-nightly-opt',
'android-api-15-partner-sample1-opt',
'android-l10n-opt',
'android-nightly-l10n-opt',
'android-x86-opt',
'android-x86-nightly-opt',
'aries-debug',
'aries-eng-opt',
'browser-haz-debug',
'linux-debug',
'linux-opt',
'linux-pgo',
'linux-qr-debug',
'linux-qr-opt',
'linux64-add-on-devel',
'linux64-artifact-opt',
'linux64-asan-debug',
'linux64-asan-opt',
@ -36,9 +35,6 @@ JOB_NAME_WHITELIST = set([
'linux64-clang-tidy',
'linux64-debug',
'linux64-jsdcov-opt',
'linux64-l10n-opt',
'linux64-nightly-opt',
'linux64-nightly-l10n-opt',
'linux64-opt',
'linux64-pgo',
'linux64-qr-debug',
@ -47,54 +43,42 @@ JOB_NAME_WHITELIST = set([
'linux64-stylo-debug',
'linux64-stylo-opt',
'linux64-valgrind-opt',
'linux-debug',
'linux-opt',
'linux-pgo',
'linux-qr-debug',
'linux-qr-opt',
'linux32-nightly-opt',
'linux32-l10n-opt',
'linux32-nightly-l10n-opt',
'linux64-add-on-devel',
'macosx64-add-on-devel',
'macosx64-clang-tidy',
'macosx64-debug',
'macosx64-opt',
'macosx64-qr-debug',
'macosx64-qr-opt',
'macosx64-st-an-opt',
'macosx64-add-on-devel',
'nexus-5-l-eng-debug',
'nexus-5-l-eng-opt',
'osx-10-10',
'shell-haz-debug',
'sm-arm64-sim-debug',
'sm-arm-sim-debug',
'sm-arm64-sim-debug',
'sm-asan-opt',
'sm-compacting-debug',
'sm-mozjs-sys-debug',
'sm-msan-opt',
'sm-nonunified-debug',
'sm-package-opt',
'sm-plaindebug-debug',
'sm-plain-opt',
'sm-plaindebug-debug',
'sm-rootanalysis-debug',
'sm-tsan-opt',
'win64-add-on-devel',
'win32-add-on-devel',
'win32-st-an-debug',
'win32-st-an-opt',
'win32-clang-tidy',
'win32-debug',
'win32-opt',
'win32-pgo',
'win32-qr-debug',
'win32-qr-opt',
'win64-st-an-debug',
'win64-st-an-opt',
'win32-st-an-debug',
'win32-st-an-opt',
'win64-add-on-devel',
'win64-clang-tidy',
'win64-debug',
'win64-opt',
'win64-pgo',
'win64-st-an-debug',
'win64-st-an-opt',
'win64-qr-debug',
'win64-qr-opt',
])

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

@ -342,9 +342,41 @@ def mozharness_test_buildbot_bridge(config, job, taskdesc):
test_name = test.get('talos-try-name', test['test-name'])
mozharness = test['mozharness']
if test['e10s'] and not test_name.endswith('-e10s'):
# mochitest e10s follows the pattern mochitest-e10s-<suffix>
# in buildbot, except for these special cases
buildbot_specials = [
'mochitest-webgl',
'mochitest-clipboard',
'mochitest-media',
'mochitest-gpu',
'mochitest-e10s',
]
test_name = test.get(
'talos-try-name',
test.get(
'unittest-try-name',
test['test-name']
)
)
if test['e10s'] and 'e10s' not in test_name:
test_name += '-e10s'
if test_name.startswith('mochitest') \
and test_name.endswith('e10s') \
and not any(map(
lambda name: test_name.startswith(name),
buildbot_specials
)):
split_mochitest = test_name.split('-')
test_name = '-'.join([
split_mochitest[0],
split_mochitest[-1],
'-'.join(split_mochitest[1:-1])
])
# in buildbot, mochitest-webgl is called mochitest-gl
test_name = test_name.replace('webgl', 'gl')
if mozharness.get('chunked', False):
this_chunk = test.get('this-chunk')
test_name = '{}-{}'.format(test_name, this_chunk)

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

@ -179,7 +179,7 @@ test_description_schema = Schema({
Required('checkout', default=False): bool,
# Wheter to perform a machine reboot after test is done
Optional('reboot', default=False): bool,
Optional('reboot', default=True): bool,
# What to run
Required('mozharness'): optionally_keyed_by(
@ -227,7 +227,9 @@ test_description_schema = Schema({
# If true, include chunking information in the command even if the number
# of chunks is 1
Required('chunked', default=False): bool,
Required('chunked', default=False): optionally_keyed_by(
'test-platform',
bool),
# The chunking argument format to use
Required('chunking-args', default='this-chunk'): Any(
@ -317,7 +319,7 @@ def set_defaults(config, tests):
test.setdefault('run-on-projects', ['all'])
test.setdefault('instance-size', 'default')
test.setdefault('max-run-time', 3600)
test.setdefault('reboot', False)
test.setdefault('reboot', True)
test['mozharness'].setdefault('extra-options', [])
yield test
@ -374,13 +376,15 @@ def set_asan_docker_image(config, tests):
@transforms.add
def set_worker_implementation(config, tests):
"""Set the worker implementation based on the test platform."""
use_tc_worker = config.config['args'].taskcluster_worker
for test in tests:
if test.get('suite', '') == 'talos':
if test['test-platform'].startswith('macosx'):
test['worker-implementation'] = \
'native-engine' if use_tc_worker else 'buildbot-bridge'
elif test.get('suite', '') == 'talos':
test['worker-implementation'] = 'buildbot-bridge'
elif test['test-platform'].startswith('win'):
test['worker-implementation'] = 'generic-worker'
elif test['test-platform'].startswith('macosx'):
test['worker-implementation'] = 'native-engine'
else:
test['worker-implementation'] = 'docker-worker'
yield test
@ -406,7 +410,8 @@ def set_tier(config, tests):
'android-4.3-arm7-api-15/debug',
'android-4.2-x86/opt']:
test['tier'] = 1
elif test['test-platform'].startswith('windows'):
elif test['test-platform'].startswith('windows') \
or test['worker-implementation'] == 'native-engine':
test['tier'] = 3
else:
test['tier'] = 2
@ -454,6 +459,7 @@ def handle_keyed_by(config, tests):
'suite',
'run-on-projects',
'os-groups',
'mozharness.chunked',
'mozharness.config',
'mozharness.extra-options',
]
@ -583,15 +589,6 @@ def remove_linux_pgo_try_talos(config, tests):
yield test
@transforms.add
def remove_native(config, tests):
"""Remove native-engine jobs if -w is not given."""
for test in tests:
if test['worker-implementation'] != 'native-engine' \
or config.config['args'].taskcluster_worker:
yield test
@transforms.add
def make_job_description(config, tests):
"""Convert *test* descriptions to *job* descriptions (input to

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

@ -88,12 +88,12 @@ UNITTEST_ALIASES = {
'mochitest-debug': alias_prefix('mochitest-debug-'),
'mochitest-a11y': alias_contains('mochitest-a11y'),
'mochitest-bc': alias_prefix('mochitest-browser-chrome'),
'mochitest-e10s-bc': alias_prefix('mochitest-e10s-browser-chrome'),
'mochitest-e10s-bc': alias_prefix('mochitest-browser-chrome-e10s'),
'mochitest-browser-chrome': alias_prefix('mochitest-browser-chrome'),
'mochitest-e10s-browser-chrome': alias_prefix('mochitest-e10s-browser-chrome'),
'mochitest-e10s-browser-chrome': alias_prefix('mochitest-browser-chrome-e10s'),
'mochitest-chrome': alias_contains('mochitest-chrome'),
'mochitest-dt': alias_prefix('mochitest-devtools-chrome'),
'mochitest-e10s-dt': alias_prefix('mochitest-e10s-devtools-chrome'),
'mochitest-e10s-dt': alias_prefix('mochitest-devtools-chrome-e10s'),
'mochitest-gl': alias_prefix('mochitest-webgl'),
'mochitest-gl-e10s': alias_prefix('mochitest-webgl-e10s'),
'mochitest-gpu': alias_prefix('mochitest-gpu'),

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

@ -327,11 +327,46 @@ const KEY_CODE_LOOKUP = {
"\uE004": "Tab",
};
/** Represents possible values for a pointer-move origin. */
action.PointerOrigin = {
Viewport: "viewport",
Pointer: "pointer",
};
/**
* Look up a PointerOrigin.
*
* @param {?} obj
* Origin for a pointerMove action.
*
* @return {?}
* A pointer origin that is either "viewport" (default), "pointer", or a
* web-element reference.
*
* @throws {InvalidArgumentError}
* If |obj| is not a valid origin.
*/
action.PointerOrigin.get = function(obj) {
let origin = obj;
if (typeof obj == "undefined") {
origin = this.Viewport;
} else if (typeof obj == "string") {
let name = capitalize(obj);
assert.in(name, this, error.pprint`Unknown pointer-move origin: ${obj}`);
origin = this[name];
} else if (!element.isWebElementReference(obj)) {
throw new InvalidArgumentError("Expected 'origin' to be a string or a " +
`web element reference, got: ${obj}`);
}
return origin;
};
/** Represents possible subtypes for a pointer input source. */
action.PointerType = {
Mouse: "mouse",
Pen: "pen",
Touch: "touch",
// TODO For now, only mouse is supported
//Pen: "pen",
//Touch: "touch",
};
/**
@ -348,9 +383,7 @@ action.PointerType = {
*/
action.PointerType.get = function (str) {
let name = capitalize(str);
if (!(name in this)) {
throw new InvalidArgumentError(`Unknown pointerType: ${str}`);
}
assert.in(name, this, error.pprint`Unknown pointerType: ${str}`);
return this[name];
};
@ -400,8 +433,8 @@ class InputState {
/**
* @param {?} obj
* Object with property |type|, representing an action sequence or an
* action item.
* Object with property |type| and optionally |parameters| or |pointerType|,
* representing an action sequence or an action item.
*
* @return {action.InputState}
* An |action.InputState| object for the type of the |actionSequence|.
@ -411,11 +444,18 @@ class InputState {
*/
static fromJson(obj) {
let type = obj.type;
if (!(type in ACTIONS)) {
throw new InvalidArgumentError(`Unknown action type: ${type}`);
}
assert.in(type, ACTIONS, error.pprint`Unknown action type: ${type}`);
let name = type == "none" ? "Null" : capitalize(type);
return new action.InputState[name]();
if (name == "Pointer") {
if (!obj.pointerType && (!obj.parameters || !obj.parameters.pointerType)) {
throw new InvalidArgumentError(
error.pprint`Expected obj to have pointerType, got: ${obj}`);
}
let pointerType = obj.pointerType || obj.parameters.pointerType;
return new action.InputState[name](pointerType);
} else {
return new action.InputState[name]();
}
}
}
@ -488,7 +528,7 @@ action.InputState.Key = class Key extends InputState {
* Normalized key value.
*
* @return {boolean}
* True if |key| is removed successfully, false otherwise.
* True if |key| was present before removal, false otherwise.
*/
release(key) {
return this.pressed.delete(key);
@ -510,18 +550,61 @@ action.InputState.Null = class Null extends InputState {
*
* @param {string} subtype
* Kind of pointing device: mouse, pen, touch.
* @param {boolean} primary
* Whether the pointing device is primary.
*
* @throws {InvalidArgumentError}
* If subtype is undefined or an invalid pointer type.
*/
action.InputState.Pointer = class Pointer extends InputState {
constructor(subtype, primary) {
constructor(subtype) {
super();
this.pressed = new Set();
this.subtype = subtype;
this.primary = primary;
assert.defined(subtype, error.pprint`Expected subtype to be defined, got: ${subtype}`);
this.subtype = action.PointerType.get(subtype);
this.x = 0;
this.y = 0;
}
/**
* Check whether |button| is pressed.
*
* @param {number} button
* Positive integer that refers to a mouse button.
*
* @return {boolean}
* True if |button| is in set of pressed buttons.
*/
isPressed(button) {
assert.positiveInteger(button);
return this.pressed.has(button);
}
/**
* Add |button| to the set of pressed keys.
*
* @param {number} button
* Positive integer that refers to a mouse button.
*
* @return {Set}
* Set of pressed buttons.
*/
press(button) {
assert.positiveInteger(button);
return this.pressed.add(button);
}
/**
* Remove |button| from the set of pressed buttons.
*
* @param {number} button
* A positive integer that refers to a mouse button.
*
* @return {boolean}
* True if |button| was present before removals, false otherwise.
*/
release(button) {
assert.positiveInteger(button);
return this.pressed.delete(button);
}
};
/**
@ -543,9 +626,7 @@ action.Action = class {
throw new InvalidArgumentError("Missing id, type or subtype");
}
for (let attr of [id, type, subtype]) {
if (typeof attr != "string") {
throw new InvalidArgumentError(`Expected string, got: ${attr}`);
}
assert.string(attr, error.pprint`Expected string, got: ${attr}`);
}
this.id = id;
this.type = type;
@ -595,11 +676,9 @@ action.Action = class {
// TODO countGraphemes
// TODO key.value could be a single code point like "\uE012" (see rawKey)
// or "grapheme cluster"
if (typeof key != "string") {
throw new InvalidArgumentError(
"Expected 'value' to be a string that represents single code point " +
"or grapheme cluster, got: " + key);
}
assert.string(key,
error.pprint("Expected 'value' to be a string that represents single code point " +
`or grapheme cluster, got: ${key}`));
item.value = key;
break;
@ -616,14 +695,7 @@ action.Action = class {
assert.positiveInteger(item.duration,
error.pprint`Expected 'duration' (${item.duration}) to be >= 0`);
}
if (typeof actionItem.element != "undefined" &&
!element.isWebElementReference(actionItem.element)) {
throw new InvalidArgumentError(
"Expected 'actionItem.element' to be a web element reference, " +
`got: ${actionItem.element}`);
}
item.element = actionItem.element;
item.origin = action.PointerOrigin.get(actionItem.origin);
item.x = actionItem.x;
if (typeof item.x != "undefined") {
assert.positiveInteger(item.x, error.pprint`Expected 'x' (${item.x}) to be >= 0`);
@ -710,18 +782,18 @@ action.Sequence = class extends Array {
* If |actionSequence.actions| is not an Array.
*/
static fromJson(actionSequence) {
// used here only to validate 'type' and InputState type
// used here to validate 'type' in addition to InputState type below
let inputSourceState = InputState.fromJson(actionSequence);
let id = actionSequence.id;
assert.defined(id, "Expected 'id' to be defined");
assert.string(id, error.pprint`Expected 'id' to be a string, got: ${id}`);
let actionItems = actionSequence.actions;
if (!Array.isArray(actionItems)) {
throw new InvalidArgumentError(
`Expected 'actionSequence.actions' to be an Array, got: ${actionSequence.actions}`);
}
if (action.inputStateMap.has(id) && !action.inputStateMap.get(id).is(inputSourceState)) {
assert.array(actionItems,
error.pprint("Expected 'actionSequence.actions' to be an Array, " +
`got: ${actionSequence.actions}`));
if (!action.inputStateMap.has(id)) {
action.inputStateMap.set(id, inputSourceState);
} else if (!action.inputStateMap.get(id).is(inputSourceState)) {
throw new InvalidArgumentError(
`Expected ${id} to be mapped to ${inputSourceState}, ` +
`got: ${action.inputStateMap.get(id)}`);
@ -739,19 +811,14 @@ action.Sequence = class extends Array {
*
* @param {string=} pointerType
* Type of pointing device. If the parameter is undefined, "mouse" is used.
* @param {boolean=} primary
* Whether the input source is the primary pointing device.
* If the parameter is undefined, true is used.
*/
action.PointerParameters = class {
constructor(pointerType = "mouse", primary = true) {
constructor(pointerType = "mouse") {
this.pointerType = action.PointerType.get(pointerType);
assert.boolean(primary);
this.primary = primary;
}
toString() {
return `[pointerParameters ${this.pointerType}, primary=${this.primary}]`;
return `[pointerParameters ${this.pointerType}]`;
}
/**
@ -765,13 +832,13 @@ action.PointerParameters = class {
if (typeof parametersData == "undefined") {
return new action.PointerParameters();
} else {
return new action.PointerParameters(parametersData.pointerType, parametersData.primary);
return new action.PointerParameters(parametersData.pointerType);
}
}
};
/**
* Adds |pointerType| and |primary| attributes to Action |act|. Helper function
* Adds |pointerType| attribute to Action |act|. Helper function
* for |action.Action.fromJson|.
*
* @param {string} id
@ -783,17 +850,21 @@ action.PointerParameters = class {
*
* @throws {InvalidArgumentError}
* If |id| is already mapped to an |action.InputState| that is
* not compatible with |act.subtype|.
* not compatible with |act.type| or |pointerParams.pointerType|.
*/
action.processPointerAction = function processPointerAction(id, pointerParams, act) {
let subtype = act.subtype;
if (action.inputStateMap.has(id) && action.inputStateMap.get(id).subtype !== subtype) {
if (action.inputStateMap.has(id) && action.inputStateMap.get(id).type !== act.type) {
throw new InvalidArgumentError(
`Expected 'id' ${id} to be mapped to InputState whose type is ` +
`${action.inputStateMap.get(id).type}, got: ${act.type}`);
}
let pointerType = pointerParams.pointerType;
if (action.inputStateMap.has(id) && action.inputStateMap.get(id).subtype !== pointerType) {
throw new InvalidArgumentError(
`Expected 'id' ${id} to be mapped to InputState whose subtype is ` +
`${action.inputStateMap.get(id).subtype}, got: ${subtype}`);
`${action.inputStateMap.get(id).subtype}, got: ${pointerType}`);
}
act.pointerType = pointerParams.pointerType;
act.primary = pointerParams.primary;
};
/** Collect properties associated with KeyboardEvent */
@ -820,6 +891,21 @@ action.Key = class {
}
};
/** Collect properties associated with MouseEvent */
action.Mouse = class {
constructor(type, button = 0) {
this.type = type;
assert.positiveInteger(button);
this.button = button;
this.buttons = 0;
}
update(inputState) {
let allButtons = Array.from(inputState.pressed);
this.buttons = allButtons.reduce((a, i) => a + Math.pow(2, i), 0);
}
};
/**
* Dispatch a chain of actions over |chain.length| ticks.
*
@ -896,6 +982,40 @@ action.computeTickDuration = function(tickActions) {
return max;
};
/**
* Compute viewport coordinates of pointer target based on given origin.
*
* @param {action.Action} a
* Action that specifies pointer origin and x and y coordinates of target.
* @param {action.InputState} inputState
* Input state that specifies current x and y coordinates of pointer.
* @param {Map.<string, number>=} center
* Object representing x and y coordinates of an element center-point.
* This is only used if |a.origin| is a web element reference.
*
* @return {Map.<string, number>}
* x and y coordinates of pointer destination.
*/
action.computePointerDestination = function(a, inputState, center = undefined) {
let {x, y} = a;
switch (a.origin) {
case action.PointerOrigin.Viewport:
break;
case action.PointerOrigin.Pointer:
x += inputState.x;
y += inputState.y;
break;
default:
// origin represents web element
assert.defined(center);
assert.in("x", center);
assert.in("y", center);
x += center.x;
y += center.y;
}
return {"x": x, "y": y};
};
/**
* Create a closure to use as a map from action definitions to Promise events.
*
@ -912,9 +1032,6 @@ action.computeTickDuration = function(tickActions) {
*/
function toEvents(tickDuration, seenEls, container) {
return function (a) {
if (!action.inputStateMap.has(a.id)) {
action.inputStateMap.set(a.id, InputState.fromJson(a));
}
let inputState = action.inputStateMap.get(a.id);
switch (a.subtype) {
case action.KeyUp:
@ -924,8 +1041,14 @@ function toEvents(tickDuration, seenEls, container) {
return dispatchKeyDown(a, inputState, container.frame);
case action.PointerDown:
return dispatchPointerDown(a, inputState, container.frame);
case action.PointerUp:
return dispatchPointerUp(a, inputState, container.frame);
case action.PointerMove:
return dispatchPointerMove(a, inputState, tickDuration, seenEls, container);
case action.PointerCancel:
throw new UnsupportedOperationError();
@ -996,6 +1119,180 @@ function dispatchKeyUp(a, inputState, win) {
});
}
/**
* Dispatch a pointerDown action equivalent to pressing a pointer-device
* button.
*
* @param {action.Action} a
* Action to dispatch.
* @param {action.InputState} inputState
* Input state for this action's input source.
* @param {nsIDOMWindow} win
* Current window.
*
* @return {Promise}
* Promise to dispatch at least a pointerdown event.
*/
function dispatchPointerDown(a, inputState, win) {
return new Promise(resolve => {
if (inputState.isPressed(a.button)) {
resolve();
return;
}
inputState.press(a.button);
// Append a copy of |a| with pointerUp subtype
action.inputsToCancel.push(Object.assign({}, a, {subtype: action.PointerUp}));
switch (inputState.subtype) {
case action.PointerType.Mouse:
let mouseEvent = new action.Mouse("mousedown", a.button);
mouseEvent.update(inputState);
event.synthesizeMouseAtPoint(inputState.x, inputState.y, mouseEvent, win);
break;
case action.PointerType.Pen:
case action.PointerType.Touch:
throw new UnsupportedOperationError("Only 'mouse' pointer type is supported");
break;
default:
throw new TypeError(`Unknown pointer type: ${inputState.subtype}`);
}
resolve();
});
}
/**
* Dispatch a pointerUp action equivalent to releasing a pointer-device
* button.
*
* @param {action.Action} a
* Action to dispatch.
* @param {action.InputState} inputState
* Input state for this action's input source.
* @param {nsIDOMWindow} win
* Current window.
*
* @return {Promise}
* Promise to dispatch at least a pointerup event.
*/
function dispatchPointerUp(a, inputState, win) {
return new Promise(resolve => {
if (!inputState.isPressed(a.button)) {
resolve();
return;
}
inputState.release(a.button);
switch (inputState.subtype) {
case action.PointerType.Mouse:
let mouseEvent = new action.Mouse("mouseup", a.button);
mouseEvent.update(inputState);
event.synthesizeMouseAtPoint(inputState.x, inputState.y,
mouseEvent, win);
break;
case action.PointerType.Pen:
case action.PointerType.Touch:
throw new UnsupportedOperationError("Only 'mouse' pointer type is supported");
default:
throw new TypeError(`Unknown pointer type: ${inputState.subtype}`);
}
resolve();
});
}
/**
* Dispatch a pointerMove action equivalent to moving pointer device in a line.
*
* If the action duration is 0, the pointer jumps immediately to the target coordinates.
* Otherwise, events are synthesized to mimic a pointer travelling in a discontinuous,
* approximately straight line, with the pointer coordinates being updated around 60
* times per second.
*
* @param {action.Action} a
* Action to dispatch.
* @param {action.InputState} inputState
* Input state for this action's input source.
* @param {element.Store} seenEls
* Element store.
* @param {?} container
* Object with |frame| attribute of type |nsIDOMWindow|.
*
* @return {Promise}
* Promise to dispatch at least one pointermove event, as well as mousemove events
* as appropriate.
*/
function dispatchPointerMove(a, inputState, tickDuration, seenEls, container) {
const timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
// interval between pointermove increments in ms, based on common vsync
const fps60 = 17;
return new Promise(resolve => {
const start = Date.now();
const [startX, startY] = [inputState.x, inputState.y];
let target = action.computePointerDestination(a, inputState,
getElementCenter(a.origin, seenEls, container));
const [targetX, targetY] = [target.x, target.y];
if (!inViewPort(targetX, targetY, container.frame)) {
throw new MoveTargetOutOfBoundsError(
`(${targetX}, ${targetY}) is out of bounds of viewport ` +
`width (${container.frame.innerWidth}) and height (${container.frame.innerHeight})`);
}
const duration = typeof a.duration == "undefined" ? tickDuration : a.duration;
if (duration === 0) {
// move pointer to destination in one step
performOnePointerMove(inputState, targetX, targetY, container.frame);
resolve();
return;
}
const distanceX = targetX - startX;
const distanceY = targetY - startY;
const ONE_SHOT = Ci.nsITimer.TYPE_ONE_SHOT;
let intermediatePointerEvents = Task.spawn(function* () {
// wait |fps60| ms before performing first incremental pointer move
yield new Promise(resolveTimer =>
timer.initWithCallback(resolveTimer, fps60, ONE_SHOT)
);
let durationRatio = Math.floor(Date.now() - start) / duration;
const epsilon = fps60 / duration / 10;
while ((1 - durationRatio) > epsilon) {
let x = Math.floor(durationRatio * distanceX + startX);
let y = Math.floor(durationRatio * distanceY + startY);
performOnePointerMove(inputState, x, y, container.frame);
// wait |fps60| ms before performing next pointer move
yield new Promise(resolveTimer =>
timer.initWithCallback(resolveTimer, fps60, ONE_SHOT));
durationRatio = Math.floor(Date.now() - start) / duration;
}
});
// perform last pointer move after all incremental moves are resolved and
// durationRatio is close enough to 1
intermediatePointerEvents.then(() => {
performOnePointerMove(inputState, targetX, targetY, container.frame);
resolve();
});
});
}
function performOnePointerMove(inputState, targetX, targetY, win) {
if (targetX == inputState.x && targetY == inputState.y) {
return;
}
switch (inputState.subtype) {
case action.PointerType.Mouse:
let mouseEvent = new action.Mouse("mousemove");
mouseEvent.update(inputState);
//TODO both pointermove (if available) and mousemove
event.synthesizeMouseAtPoint(targetX, targetY, mouseEvent, win);
break;
case action.PointerType.Pen:
case action.PointerType.Touch:
throw new UnsupportedOperationError("Only 'mouse' pointer type is supported");
default:
throw new TypeError(`Unknown pointer type: ${inputState.subtype}`);
}
inputState.x = targetX;
inputState.y = targetY;
}
/**
* Dispatch a pause action equivalent waiting for |a.duration| milliseconds, or a
* default time interval of |tickDuration|.
@ -1031,8 +1328,21 @@ function flushEvents(container) {
}
function capitalize(str) {
if (typeof str != "string") {
throw new InvalidArgumentError(`Expected string, got: ${str}`);
}
assert.string(str);
return str.charAt(0).toUpperCase() + str.slice(1);
}
function inViewPort(x, y, win) {
assert.number(x);
assert.number(y);
// Viewport includes scrollbars if rendered.
return !(x < 0 || y < 0 || x > win.innerWidth || y > win.innerHeight);
}
function getElementCenter(elementReference, seenEls, container) {
if (element.isWebElementReference(elementReference)) {
let uuid = elementReference[element.Key] || elementReference[element.LegacyKey];
let el = seenEls.get(uuid, container);
return element.coordinates(el);
}
}

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

@ -100,7 +100,7 @@ assert.b2g = function (msg = "") {
assert.content = function (context, msg = "") {
msg = msg || "Only supported in content context";
assert.that(c => c.toString() == "content", msg, UnsupportedOperationError)(context);
}
};
/**
* Asserts that the current browser is a mobile browser, that is either
@ -136,6 +136,25 @@ assert.defined = function (obj, msg = "") {
return assert.that(o => typeof o != "undefined", msg)(obj);
};
/**
* Asserts that |obj| is a finite number.
*
* @param {?} obj
* Value to test.
* @param {string=} msg
* Custom error message.
*
* @return {number}
* |obj| is returned unaltered.
*
* @throws {InvalidArgumentError}
* If |obj| is not a number.
*/
assert.number = function (obj, msg = "") {
msg = msg || error.pprint`Expected ${obj} to be finite number`;
return assert.that(Number.isFinite, msg)(obj);
};
/**
* Asserts that |obj| is an integer.
*

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

@ -15,6 +15,7 @@ const ERRORS = new Set([
"InvalidSelectorError",
"InvalidSessionIDError",
"JavaScriptError",
"MoveTargetOutOfBoundsError",
"NoAlertOpenError",
"NoSuchElementError",
"NoSuchFrameError",
@ -301,6 +302,13 @@ class JavaScriptError extends WebDriverError {
}
}
class MoveTargetOutOfBoundsError extends WebDriverError {
constructor (message) {
super(message);
this.status = "move target out of bounds";
}
}
class NoAlertOpenError extends WebDriverError {
constructor (message) {
super(message);
@ -394,6 +402,7 @@ const STATUSES = new Map([
["invalid selector", InvalidSelectorError],
["invalid session id", InvalidSessionIDError],
["javascript error", JavaScriptError],
["move target out of bounds", MoveTargetOutOfBoundsError],
["no alert open", NoAlertOpenError],
["no such element", NoSuchElementError],
["no such frame", NoSuchFrameError],

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

@ -232,7 +232,7 @@ event.synthesizeMouse = function (
* CSS pixels from the left document margin.
* @param {number} top
* CSS pixels from the top document margin.
* @param {Object.<string, ?>} event
* @param {Object.<string, ?>} opts
* Object which may contain the properties "shiftKey", "ctrlKey",
* "altKey", "metaKey", "accessKey", "clickCount", "button", and
* "type".
@ -247,15 +247,26 @@ event.synthesizeMouseAtPoint = function (
let button = opts.button || 0;
let clickCount = opts.clickCount || 1;
let modifiers = event.parseModifiers_(opts);
let pressure = ("pressure" in opts) ? opts.pressure : 0;
let inputSource = ("inputSource" in opts) ? opts.inputSource :
Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE;
let isDOMEventSynthesized =
("isSynthesized" in opts) ? opts.isSynthesized : true;
let isWidgetEventSynthesized =
("isWidgetEventSynthesized" in opts) ? opts.isWidgetEventSynthesized : false;
let buttons = ("buttons" in opts) ? opts.buttons : domutils.MOUSE_BUTTONS_NOT_SPECIFIED;
if (("type" in event) && opts.type) {
if (("type" in opts) && opts.type) {
domutils.sendMouseEvent(
opts.type, left, top, button, clickCount, modifiers);
opts.type, left, top, button, clickCount, modifiers, false, pressure, inputSource,
isDOMEventSynthesized, isWidgetEventSynthesized, buttons);
} else {
domutils.sendMouseEvent(
"mousedown", left, top, button, clickCount, modifiers);
"mousedown", left, top, button, clickCount, modifiers, false, pressure, inputSource,
isDOMEventSynthesized, isWidgetEventSynthesized, buttons);
domutils.sendMouseEvent(
"mouseup", left, top, button, clickCount, modifiers);
"mouseup", left, top, button, clickCount, modifiers, false, pressure, inputSource,
isDOMEventSynthesized, isWidgetEventSynthesized, buttons);
}
};

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

@ -25,7 +25,7 @@ add_test(function test_createAction() {
});
add_test(function test_defaultPointerParameters() {
let defaultParameters = {pointerType: action.PointerType.Mouse, primary: true};
let defaultParameters = {pointerType: action.PointerType.Mouse};
deepEqual(action.PointerParameters.fromJson(), defaultParameters);
run_next_test();
@ -34,16 +34,15 @@ add_test(function test_defaultPointerParameters() {
add_test(function test_processPointerParameters() {
let check = (regex, message, arg) => checkErrors(
regex, action.PointerParameters.fromJson, [arg], message);
let parametersData = {pointerType: "foo", primary: undefined};
let message = `parametersData: [pointerType: ${parametersData.pointerType}, ` +
`primary: ${parametersData.primary}]`;
check(/Unknown pointerType/, message, parametersData);
parametersData.pointerType = "pen";
parametersData.primary = "a";
check(/Expected \[object String\] "a" to be boolean/, message, parametersData);
parametersData.primary = false;
let parametersData;
for (let d of ["foo", "", "get", "Get"]) {
parametersData = {pointerType: d};
let message = `parametersData: [pointerType: ${parametersData.pointerType}]`;
check(/Unknown pointerType/, message, parametersData);
}
parametersData.pointerType = "mouse"; //TODO "pen";
deepEqual(action.PointerParameters.fromJson(parametersData),
{pointerType: action.PointerType.Pen, primary: false});
{pointerType: "mouse"}); //TODO action.PointerType.Pen});
run_next_test();
});
@ -89,37 +88,66 @@ add_test(function test_validateActionDurationAndCoordinates() {
run_next_test();
});
add_test(function test_processPointerMoveActionElementValidation() {
add_test(function test_processPointerMoveActionOriginValidation() {
let actionSequence = {type: "pointer", id: "some_id"};
let actionItem = {duration: 5000, type: "pointerMove"};
for (let d of [-1, "a", {a: "blah"}]) {
actionItem.element = d;
checkErrors(/Expected 'actionItem.element' to be a web element reference/,
for (let d of [-1, {a: "blah"}, []]) {
actionItem.origin = d;
checkErrors(/Expected \'origin\' to be a string or a web element reference/,
action.Action.fromJson,
[actionSequence, actionItem],
`actionItem.element: (${getTypeString(d)})`);
`actionItem.origin: (${getTypeString(d)})`);
}
actionItem.element = {[element.Key]: "something"};
let a = action.Action.fromJson(actionSequence, actionItem);
deepEqual(a.element, actionItem.element);
run_next_test();
});
add_test(function test_processPointerMoveActionOriginStringValidation() {
let actionSequence = {type: "pointer", id: "some_id"};
let actionItem = {duration: 5000, type: "pointerMove"};
for (let d of ["a", "", "get", "Get"]) {
actionItem.origin = d;
checkErrors(/Unknown pointer-move origin/,
action.Action.fromJson,
[actionSequence, actionItem],
`actionItem.origin: ${d}`);
}
run_next_test();
});
add_test(function test_processPointerMoveActionElementOrigin() {
let actionSequence = {type: "pointer", id: "some_id"};
let actionItem = {duration: 5000, type: "pointerMove"};
actionItem.origin = {[element.Key]: "something"};
let a = action.Action.fromJson(actionSequence, actionItem);
deepEqual(a.origin, actionItem.origin);
run_next_test();
});
add_test(function test_processPointerMoveActionDefaultOrigin() {
let actionSequence = {type: "pointer", id: "some_id"};
// origin left undefined
let actionItem = {duration: 5000, type: "pointerMove"};
let a = action.Action.fromJson(actionSequence, actionItem);
deepEqual(a.origin, action.PointerOrigin.Viewport);
run_next_test();
});
add_test(function test_processPointerMoveAction() {
let actionSequence = {id: "some_id", type: "pointer"};
let actionItems = [
{
duration: 5000,
type: "pointerMove",
element: undefined,
origin: undefined,
x: undefined,
y: undefined,
},
{
duration: undefined,
type: "pointerMove",
element: {[element.Key]: "id", [element.LegacyKey]: "id"},
origin: {[element.Key]: "id", [element.LegacyKey]: "id"},
x: undefined,
y: undefined,
},
@ -128,34 +156,88 @@ add_test(function test_processPointerMoveAction() {
type: "pointerMove",
x: 0,
y: undefined,
element: undefined,
origin: undefined,
},
{
duration: 5000,
type: "pointerMove",
x: 1,
y: 2,
element: undefined,
origin: undefined,
},
];
for (let expected of actionItems) {
let actual = action.Action.fromJson(actionSequence, expected);
ok(actual instanceof action.Action);
equal(actual.duration, expected.duration);
equal(actual.element, expected.element);
equal(actual.x, expected.x);
equal(actual.y, expected.y);
let origin = expected.origin;
if (typeof origin == "undefined") {
origin = action.PointerOrigin.Viewport;
}
deepEqual(actual.origin, origin);
}
run_next_test();
});
add_test(function test_computePointerDestinationViewport() {
let act = { type: "pointerMove", x: 100, y: 200, origin: "viewport"};
let inputState = new action.InputState.Pointer(action.PointerType.Mouse);
// these values should not affect the outcome
inputState.x = "99";
inputState.y = "10";
let target = action.computePointerDestination(act, inputState);
equal(act.x, target.x);
equal(act.y, target.y);
run_next_test();
});
add_test(function test_computePointerDestinationPointer() {
let act = { type: "pointerMove", x: 100, y: 200, origin: "pointer"};
let inputState = new action.InputState.Pointer(action.PointerType.Mouse);
inputState.x = 10;
inputState.y = 99;
let target = action.computePointerDestination(act, inputState);
equal(act.x + inputState.x, target.x);
equal(act.y + inputState.y, target.y);
run_next_test();
});
add_test(function test_computePointerDestinationElement() {
// origin represents a web element
// using an object literal instead to test default case in computePointerDestination
let act = {type: "pointerMove", x: 100, y: 200, origin: {}};
let inputState = new action.InputState.Pointer(action.PointerType.Mouse);
let elementCenter = {x: 10, y: 99};
let target = action.computePointerDestination(act, inputState, elementCenter);
equal(act.x + elementCenter.x, target.x);
equal(act.y + elementCenter.y, target.y);
Assert.throws(
() => action.computePointerDestination(act, inputState, {a: 1}),
InvalidArgumentError,
"Invalid element center coordinates.");
Assert.throws(
() => action.computePointerDestination(act, inputState, undefined),
InvalidArgumentError,
"Undefined element center coordinates.");
run_next_test();
});
add_test(function test_processPointerAction() {
let actionSequence = {
type: "pointer",
id: "some_id",
parameters: {
pointerType: "touch",
primary: false,
pointerType: "mouse" //TODO "touch"
},
};
let actionItems = [
@ -183,7 +265,6 @@ add_test(function test_processPointerAction() {
equal(actual.duration, expected.duration);
}
if (expected.type !== "pause") {
equal(actual.primary, actionSequence.parameters.primary);
equal(actual.pointerType, actionSequence.parameters.pointerType);
}
}
@ -253,20 +334,24 @@ add_test(function test_processInputSourceActionSequenceValidation() {
let check = (message, regex) => checkErrors(
regex, action.Sequence.fromJson, [actionSequence], message);
check(`actionSequence.type: ${actionSequence.type}`, /Unknown action type/);
action.inputStateMap.clear();
actionSequence.type = "none";
actionSequence.id = -1;
check(`actionSequence.id: ${getTypeString(actionSequence.id)}`,
/Expected 'id' to be a string/);
action.inputStateMap.clear();
actionSequence.id = undefined;
check(`actionSequence.id: ${getTypeString(actionSequence.id)}`,
/Expected 'id' to be defined/);
action.inputStateMap.clear();
actionSequence.id = "some_id";
actionSequence.actions = -1;
check(`actionSequence.actions: ${getTypeString(actionSequence.actions)}`,
/Expected 'actionSequence.actions' to be an Array/);
action.inputStateMap.clear();
run_next_test();
});
@ -283,6 +368,7 @@ add_test(function test_processInputSourceActionSequence() {
let actions = action.Sequence.fromJson(actionSequence);
equal(actions.length, 1);
deepEqual(actions[0], expectedAction);
action.inputStateMap.clear();
run_next_test();
});
@ -293,18 +379,17 @@ add_test(function test_processInputSourceActionSequencePointer() {
id: "9",
actions: [actionItem],
parameters: {
pointerType: "pen",
primary: false,
pointerType: "mouse" // TODO "pen"
},
};
let expectedAction = new action.Action(
actionSequence.id, actionSequence.type, actionItem.type);
expectedAction.pointerType = actionSequence.parameters.pointerType;
expectedAction.primary = actionSequence.parameters.primary;
expectedAction.button = actionItem.button;
let actions = action.Sequence.fromJson(actionSequence);
equal(actions.length, 1);
deepEqual(actions[0], expectedAction);
action.inputStateMap.clear();
run_next_test();
});
@ -321,6 +406,7 @@ add_test(function test_processInputSourceActionSequenceKey() {
let actions = action.Sequence.fromJson(actionSequence);
equal(actions.length, 1);
deepEqual(actions[0], expectedAction);
action.inputStateMap.clear();
run_next_test();
});
@ -349,26 +435,40 @@ add_test(function test_processInputSourceActionSequenceInputStateMap() {
add_test(function test_processPointerActionInputStateMap() {
let actionItem = {type: "pointerDown"};
let id = "1";
let parameters = {pointerType: "mouse", primary: false};
let parameters = {pointerType: "mouse"};
let a = new action.Action(id, "pointer", actionItem.type);
let wrongInputState = new action.InputState.Pointer("pause", true);
let wrongInputState = new action.InputState.Key();
action.inputStateMap.set(id, wrongInputState);
checkErrors(
/to be mapped to InputState whose subtype is/, action.processPointerAction,
/to be mapped to InputState whose type is/, action.processPointerAction,
[id, parameters, a],
`$subtype ${actionItem.type} with ${wrongInputState.subtype} in inputState`);
`type "pointer" with ${wrongInputState.type} in inputState`);
action.inputStateMap.clear();
let rightInputState = new action.InputState.Pointer("pointerDown", false);
// TODO - uncomment once pen is supported
//wrongInputState = new action.InputState.Pointer("pen");
//action.inputStateMap.set(id, wrongInputState);
//checkErrors(
// /to be mapped to InputState whose subtype is/, action.processPointerAction,
// [id, parameters, a],
// `subtype ${parameters.pointerType} with ${wrongInputState.subtype} in inputState`);
//action.inputStateMap.clear();
let rightInputState = new action.InputState.Pointer("mouse");
action.inputStateMap.set(id, rightInputState);
action.processPointerAction(id, parameters, a);
equal(a.primary, parameters.primary);
action.inputStateMap.clear();
run_next_test();
});
add_test(function test_createInputState() {
for (let kind in action.InputState) {
let state = new action.InputState[kind]();
let state;
if (kind == "Pointer") {
state = new action.InputState[kind]("mouse");
} else {
state = new action.InputState[kind]();
}
ok(state);
if (kind === "Null") {
equal(state.type, "none");
@ -376,6 +476,10 @@ add_test(function test_createInputState() {
equal(state.type, kind.toLowerCase());
}
}
Assert.throws(() => new action.InputState.Pointer(), InvalidArgumentError,
"Missing InputState.Pointer constructor arg");
Assert.throws(() => new action.InputState.Pointer("foo"), InvalidArgumentError,
"Invalid InputState.Pointer constructor arg");
run_next_test();
});
@ -408,6 +512,7 @@ add_test(function test_extractActionChain_oneTickOneInput() {
equal(1, actionsByTick.length);
equal(1, actionsByTick[0].length);
deepEqual(actionsByTick, [[expectedAction]]);
action.inputStateMap.clear();
run_next_test();
});
@ -427,8 +532,7 @@ add_test(function test_extractActionChain_twoAndThreeTicks() {
id: "7",
actions: mouseActionItems,
parameters: {
pointerType: "touch",
primary: false,
pointerType: "mouse" //TODO "touch"
},
};
let keyActionItems = [
@ -459,12 +563,14 @@ add_test(function test_extractActionChain_twoAndThreeTicks() {
let expectedAction = new action.Action(keyActionSequence.id, "key", keyActionItems[2].type);
expectedAction.value = keyActionItems[2].value;
deepEqual(actionsByTick[2][0], expectedAction);
action.inputStateMap.clear();
// one empty action sequence
actionsByTick = action.Chain.fromJson(
[keyActionSequence, {type: "none", id: "some", actions: []}]);
equal(keyActionItems.length, actionsByTick.length);
equal(1, actionsByTick[0].length);
action.inputStateMap.clear();
run_next_test();
});

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

@ -40,11 +40,23 @@ add_test(function test_defined() {
run_next_test();
});
add_test(function test_number() {
assert.number(1);
assert.number(0);
assert.number(-1);
assert.number(1.2);
for (let i of ["foo", "1", {}, [], NaN, Infinity, undefined]) {
Assert.throws(() => assert.number(i), InvalidArgumentError);
}
run_next_test();
});
add_test(function test_integer() {
assert.integer(1);
assert.integer(0);
assert.integer(-1);
Assert.throws(() => assert.integer("foo"), InvalidArgumentError);
Assert.throws(() => assert.integer(1.2), InvalidArgumentError);
run_next_test();
});

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

@ -31,8 +31,8 @@ config = {
'tooltool_script': ["/builds/tooltool.py"],
'tooltool_bootstrap': "setup.sh",
'enable_count_ctors': False,
'enable_talos_sendchange': True,
'enable_unittest_sendchange': True,
'enable_talos_sendchange': False,
'enable_unittest_sendchange': False,
#########################################################################

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

@ -37,8 +37,8 @@ config = {
'tooltool_script': ["/builds/tooltool.py"],
'tooltool_bootstrap': "setup.sh",
'enable_count_ctors': False,
'enable_talos_sendchange': True,
'enable_unittest_sendchange': True,
'enable_talos_sendchange': False,
'enable_unittest_sendchange': False,
#########################################################################

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

@ -12854,11 +12854,6 @@
{}
]
],
"./test_keys_wdspec.html": [
[
{}
]
],
"./update-built-tests.sh": [
[
{}
@ -62234,12 +62229,27 @@
{}
]
],
"webdriver/support/__init__.py": [
"webdriver/actions/__init__.py": [
[
{}
]
],
"webdriver/support/keys.py": [
"webdriver/actions/support/__init__.py": [
[
{}
]
],
"webdriver/actions/support/keys.py": [
[
{}
]
],
"webdriver/actions/support/refine.py": [
[
{}
]
],
"webdriver/actions/support/test_actions_wdspec.html": [
[
{}
]
@ -129329,9 +129339,27 @@
]
},
"wdspec": {
"webdriver/actions.py": [
"webdriver/actions/conftest.py": [
[
"/webdriver/actions.py",
"/webdriver/actions/conftest.py",
{}
]
],
"webdriver/actions/key.py": [
[
"/webdriver/actions/key.py",
{}
]
],
"webdriver/actions/mouse.py": [
[
"/webdriver/actions/mouse.py",
{}
]
],
"webdriver/actions/sequence.py": [
[
"/webdriver/actions/sequence.py",
{}
]
],
@ -129444,10 +129472,6 @@
"c51b17fbac2a2e3121dc74f7badbd2873ce92f61",
"support"
],
"./test_keys_wdspec.html": [
"13e6f15dcfe080bff5f3b3cbaf9b9f679915aca3",
"support"
],
"./update-built-tests.sh": [
"75ea35a5ce9d8e3e32e8d0c336dc12e04691d16a",
"support"
@ -176941,7 +176965,7 @@
"testharness"
],
"html/semantics/forms/the-select-element/common-HTMLOptionsCollection.html": [
"de186d5f39bf85cc073ad6262fa933f89a4500d5",
"b5a01e973e4d4c97c6fa06bd9fd1e535e8c622e8",
"testharness"
],
"html/semantics/forms/the-select-element/select-ask-for-reset.html": [
@ -178129,11 +178153,11 @@
"testharness"
],
"html/semantics/tabular-data/the-table-element/tFoot.html": [
"8017cabc08b5c10566ce97dee0cecd73d7ee3bce",
"ec9513f8c78bed931ac9ea51910d314b46639317",
"testharness"
],
"html/semantics/tabular-data/the-table-element/tHead.html": [
"45cd1c63c80dce76c5a51644fa17f8535846cb54",
"96c3470e247189297a84310173392007bad4977d",
"testharness"
],
"html/semantics/tabular-data/the-table-element/table-insertRow.html": [
@ -178197,7 +178221,7 @@
"testharness"
],
"html/semantics/tabular-data/the-tr-element/insertCell.html": [
"d3e48e89cfc8a9f3478af5c922fea6a59e88135e",
"8161e1f20e42a9fe5270cc779dca71ada097cd75",
"testharness"
],
"html/semantics/tabular-data/the-tr-element/rowIndex.html": [
@ -205836,10 +205860,42 @@
"a4611303723fa7225d7667a1e4fe2495451b824f",
"support"
],
"webdriver/actions.py": [
"3a857859e17b7965cec7fb1ba2368177f316a395",
"webdriver/actions/__init__.py": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
],
"webdriver/actions/conftest.py": [
"ba57459c1eb7d792e14e756078eb725f4c07aa6e",
"wdspec"
],
"webdriver/actions/key.py": [
"808f1311409fb70a40bbb995ff7da768d58e43cb",
"wdspec"
],
"webdriver/actions/mouse.py": [
"640ae3074200938ad63f77627d6645efa8c5716e",
"wdspec"
],
"webdriver/actions/sequence.py": [
"d80f382863e52ff223db735a2a551197e570774f",
"wdspec"
],
"webdriver/actions/support/__init__.py": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
],
"webdriver/actions/support/keys.py": [
"85bfdbd3203166c2b84616cc1936f6dd98f8de3b",
"support"
],
"webdriver/actions/support/refine.py": [
"0d244bffe67ef57be68aad99f1cbc7440ff80e27",
"support"
],
"webdriver/actions/support/test_actions_wdspec.html": [
"63b5de5ab6c7a00717663a18c3b4d79857ee2136",
"support"
],
"webdriver/conftest.py": [
"9a5d2c122d912af2d53478a3f83ac9da676ba531",
"wdspec"
@ -205856,14 +205912,6 @@
"2216ea3b518ec6b1beef54ce2580b5e62c2841a0",
"wdspec"
],
"webdriver/support/__init__.py": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
],
"webdriver/support/keys.py": [
"85bfdbd3203166c2b84616cc1936f6dd98f8de3b",
"support"
],
"webdriver/util/__init__.py": [
"8910ee7d68dfff68460731ea37eb0d406d07862d",
"support"

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

@ -1,4 +1,4 @@
[actions.py]
[key.py]
type: wdspec
disabled:
if (os == "linux") and (bits == 64) and debug: https://bugzilla.mozilla.org/show_bug.cgi?id=1318724

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

@ -0,0 +1,5 @@
[mouse.py]
type: wdspec
disabled:
if (os == "linux") and (bits == 64) and debug: https://bugzilla.mozilla.org/show_bug.cgi?id=1318724
expected: CRASH

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

@ -0,0 +1,5 @@
[sequence.py]
type: wdspec
disabled:
if (os == "linux") and (bits == 64) and debug: https://bugzilla.mozilla.org/show_bug.cgi?id=1318724
expected: CRASH

1
testing/web-platform/tests/.gitignore поставляемый
Просмотреть файл

@ -13,3 +13,4 @@ testharness_runner.html
webdriver/.idea
.vscode/
.DS_Store
*.rej

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

@ -1,69 +0,0 @@
<!doctype html>
<meta charset=utf-8>
<head>
<title>Test Keys</title>
<script>
var allEvents = {events: []};
function displayMessage(message) {
document.getElementById("events").innerHTML = "<p>" + message + "</p>";
}
function appendMessage(message) {
document.getElementById("events").innerHTML += "<p>" + message + "</p>";
}
/**
* Escape |key| if it's in a surrogate-half character range.
*
* Example: given "\ud83d" return "U+d83d".
*
* Otherwise JSON.stringify will convert it to U+FFFD (REPLACEMENT CHARACTER)
* when returning a value from executeScript, for example.
*/
function escapeSurrogateHalf(key) {
if (typeof key !== "undefined" && key.length === 1) {
var charCode = key.charCodeAt(0);
var highSurrogate = charCode >= 0xD800 && charCode <= 0xDBFF;
var surrogate = highSurrogate || (charCode >= 0xDC00 && charCode <= 0xDFFF);
if (surrogate) {
key = "U+" + charCode.toString(16);
}
}
return key;
}
function recordEvent(event) {
var key = escapeSurrogateHalf(event.key);
allEvents.events.push({
"code": event.code,
"key": key,
"which": event.which,
"location": event.location,
"ctrl": event.ctrlKey,
"meta": event.metaKey,
"shift": event.shiftKey,
"repeat": event.repeat,
"type": event.type
});
appendMessage(`${event.type}(code:${event.code}, key:${key}, which:${event.which})`);
}
function resetEvents() {
allEvents.events.length = 0;
displayMessage("");
}
</script>
</head>
<body>
<div>
<h2>KeyReporter</h2>
<input type="text" id="keys" size="80"
onkeyup="recordEvent(event)"
onkeypress="recordEvent(event)"
onkeydown="recordEvent(event)">
</div>
<div id="resultContainer" style="width:300;height:60">
<h2>Events</h2>
<div id="events"></div>
</div>
</body>

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

@ -83,26 +83,30 @@ class ActionSequence(object):
.key_up("a") \
.perform()
"""
def __init__(self, session, action_type, input_id):
def __init__(self, session, action_type, input_id, pointer_params=None):
"""Represents a sequence of actions of one type for one input source.
:param session: WebDriver session.
:param action_type: Action type; may be "none", "key", or "pointer".
:param input_id: ID of input source.
:param pointer_params: Optional dictionary of pointer parameters.
"""
self.session = session
# TODO take advantage of remote end generating uuid
self._id = input_id
self._type = action_type
self._actions = []
self._pointer_params = pointer_params
@property
def dict(self):
return {
"type": self._type,
"id": self._id,
"actions": self._actions,
d = {
"type": self._type,
"id": self._id,
"actions": self._actions,
}
if self._pointer_params is not None:
d["parameters"] = self._pointer_params
return d
@command
def perform(self):
@ -112,6 +116,48 @@ class ActionSequence(object):
def _key_action(self, subtype, value):
self._actions.append({"type": subtype, "value": value})
def _pointer_action(self, subtype, button):
self._actions.append({"type": subtype, "button": button})
def pointer_move(self, x, y, duration=None, origin=None):
"""Queue a pointerMove action.
:param x: Destination x-axis coordinate of pointer in CSS pixels.
:param y: Destination y-axis coordinate of pointer in CSS pixels.
:param duration: Number of milliseconds over which to distribute the
move. If None, remote end defaults to 0.
:param origin: Origin of coordinates, either "viewport", "pointer" or
an Element. If None, remote end defaults to "viewport".
"""
# TODO change to pointerMove once geckodriver > 0.14 is available on mozilla-central
action = {
"type": "move",
"x": x,
"y": y
}
if duration is not None:
action["duration"] = duration
if origin is not None:
action["origin"] = origin if isinstance(origin, basestring) else origin.json()
self._actions.append(action)
return self
def pointer_up(self, button):
"""Queue a pointerUp action for `button`.
:param button: Pointer button to perform action with.
"""
self._pointer_action("pointerUp", button)
return self
def pointer_down(self, button):
"""Queue a pointerDown action for `button`.
:param button: Pointer button to perform action with.
"""
self._pointer_action("pointerDown", button)
return self
def key_up(self, value):
"""Queue a keyUp action for `value`.

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

@ -0,0 +1,34 @@
import pytest
@pytest.fixture
def key_chain(session):
return session.actions.sequence("key", "keyboard_id")
@pytest.fixture
def mouse_chain(session):
return session.actions.sequence(
"pointer",
"pointer_id",
{"pointerType": "mouse"})
@pytest.fixture(autouse=True)
def release_actions(session, request):
# release all actions after each test
# equivalent to a teardown_function, but with access to session fixture
request.addfinalizer(session.actions.release)
@pytest.fixture
def key_reporter(session, test_actions_page, request):
"""Represents focused input element from `test_keys_page` fixture."""
input_el = session.find.css("#keys", all=False)
input_el.click()
return input_el
@pytest.fixture
def test_actions_page(session, server):
session.url = server.where_is("webdriver/actions/support/test_actions_wdspec.html")

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

@ -1,72 +1,7 @@
import pytest
from support.keys import Keys
def get_events(session):
"""Return list of key events recorded in the test_keys_page fixture."""
events = session.execute_script("return allEvents.events;") or []
# `key` values in `allEvents` may be escaped (see `escapeSurrogateHalf` in
# test_keys_wdspec.html), so this converts them back into unicode literals.
for e in events:
# example: turn "U+d83d" (6 chars) into u"\ud83d" (1 char)
if e["key"].startswith(u"U+"):
key = e["key"]
hex_suffix = key[key.index("+") + 1:]
e["key"] = unichr(int(hex_suffix, 16))
return events
def get_keys(input_el):
"""Get printable characters entered into `input_el`.
:param input_el: HTML input element.
"""
rv = input_el.property("value")
if rv is None:
return ""
else:
return rv
def filter_dict(source, d):
"""Filter `source` dict to only contain same keys as `d` dict.
:param source: dictionary to filter.
:param d: dictionary whose keys determine the filtering.
"""
return {k: source[k] for k in d.keys()}
@pytest.fixture
def key_reporter(session, test_keys_page, request):
"""Represents focused input element from `test_keys_page` fixture."""
input_el = session.find.css("#keys", all=False)
input_el.click()
return input_el
@pytest.fixture
def test_keys_page(session, server):
session.url = server.where_is("test_keys_wdspec.html")
@pytest.fixture
def key_chain(session):
return session.actions.sequence("key", "keyboard_id")
@pytest.fixture(autouse=True)
def release_actions(session, request):
# release all actions after each test
# equivalent to a teardown_function, but with access to session fixture
request.addfinalizer(session.actions.release)
def test_no_actions_send_no_events(session, key_reporter, key_chain):
key_chain.perform()
assert len(get_keys(key_reporter)) == 0
assert len(get_events(session)) == 0
from support.refine import get_keys, filter_dict, get_events
def test_lone_keyup_sends_no_events(session, key_reporter, key_chain):
@ -220,24 +155,6 @@ def test_sequence_of_keydown_printable_keys_sends_events(session,
assert get_keys(key_reporter) == "ab"
def test_release_char_sequence_sends_keyup_events_in_reverse(session,
key_reporter,
key_chain):
key_chain \
.key_down("a") \
.key_down("b") \
.perform()
# reset so we only see the release events
session.execute_script("resetEvents();")
session.actions.release()
expected = [
{"code": "KeyB", "key": "b", "type": "keyup"},
{"code": "KeyA", "key": "a", "type": "keyup"},
]
events = [filter_dict(e, expected[0]) for e in get_events(session)]
assert events == expected
def test_sequence_of_keydown_character_keys(session, key_reporter, key_chain):
key_chain.send_keys("ef").perform()
expected = [
@ -251,9 +168,3 @@ def test_sequence_of_keydown_character_keys(session, key_reporter, key_chain):
events = [filter_dict(e, expected[0]) for e in get_events(session)]
assert events == expected
assert get_keys(key_reporter) == "ef"
def test_release_no_actions_sends_no_events(session, key_reporter, key_chain):
session.actions.release()
assert len(get_keys(key_reporter)) == 0
assert len(get_events(session)) == 0

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

@ -0,0 +1,31 @@
from support.refine import get_events, filter_dict
def test_click_at_coordinates(session, test_actions_page, mouse_chain):
div_point = {
"x": 82,
"y": 187,
}
button = 0
mouse_chain \
.pointer_move(div_point["x"], div_point["y"], duration=1000) \
.pointer_down(button) \
.pointer_up(button) \
.perform()
events = get_events(session)
assert len(events) == 4
for e in events:
if e["type"] != "mousemove":
assert e["pageX"] == div_point["x"]
assert e["pageY"] == div_point["y"]
assert e["target"] == "outer"
if e["type"] != "mousedown":
assert e["buttons"] == 0
assert e["button"] == button
expected = [
{"type": "mousedown", "buttons": 1},
{"type": "mouseup", "buttons": 0},
{"type": "click", "buttons": 0},
]
filtered_events = [filter_dict(e, expected[0]) for e in events]
assert expected == filtered_events[1:]

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

@ -0,0 +1,31 @@
from support.refine import get_keys, filter_dict, get_events
def test_no_actions_send_no_events(session, key_reporter, key_chain):
key_chain.perform()
assert len(get_keys(key_reporter)) == 0
assert len(get_events(session)) == 0
def test_release_char_sequence_sends_keyup_events_in_reverse(session,
key_reporter,
key_chain):
key_chain \
.key_down("a") \
.key_down("b") \
.perform()
# reset so we only see the release events
session.execute_script("resetEvents();")
session.actions.release()
expected = [
{"code": "KeyB", "key": "b", "type": "keyup"},
{"code": "KeyA", "key": "a", "type": "keyup"},
]
events = [filter_dict(e, expected[0]) for e in get_events(session)]
assert events == expected
def test_release_no_actions_sends_no_events(session, key_reporter):
session.actions.release()
assert len(get_keys(key_reporter)) == 0
assert len(get_events(session)) == 0

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

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

@ -0,0 +1,33 @@
def get_events(session):
"""Return list of key events recorded in the test_keys_page fixture."""
events = session.execute_script("return allEvents.events;") or []
# `key` values in `allEvents` may be escaped (see `escapeSurrogateHalf` in
# test_keys_wdspec.html), so this converts them back into unicode literals.
for e in events:
# example: turn "U+d83d" (6 chars) into u"\ud83d" (1 char)
if "key" in e and e["key"].startswith(u"U+"):
key = e["key"]
hex_suffix = key[key.index("+") + 1:]
e["key"] = unichr(int(hex_suffix, 16))
return events
def get_keys(input_el):
"""Get printable characters entered into `input_el`.
:param input_el: HTML input element.
"""
rv = input_el.property("value")
if rv is None:
return ""
else:
return rv
def filter_dict(source, d):
"""Filter `source` dict to only contain same keys as `d` dict.
:param source: dictionary to filter.
:param d: dictionary whose keys determine the filtering.
"""
return {k: source[k] for k in d.keys()}

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

@ -0,0 +1,131 @@
<!doctype html>
<meta charset=utf-8>
<head>
<title>Test Actions</title>
<style>
div { padding:0px; margin: 0px; }
#resultContainer { width: 600px; height: 60px; }
#outer { width: 100px; height: 50px; background-color: #ccc; }
#trackPointer {
width: 5px;
height: 5px;
border: solid 1px red;
position: fixed; }
</style>
<script>
var allEvents = {events: []};
function displayMessage(message) {
document.getElementById("events").innerHTML = "<p>" + message + "</p>";
}
function appendMessage(message) {
document.getElementById("events").innerHTML += "<p>" + message + "</p>";
}
/**
* Escape |key| if it's in a surrogate-half character range.
*
* Example: given "\ud83d" return "U+d83d".
*
* Otherwise JSON.stringify will convert it to U+FFFD (REPLACEMENT CHARACTER)
* when returning a value from executeScript, for example.
*/
function escapeSurrogateHalf(key) {
if (typeof key !== "undefined" && key.length === 1) {
var charCode = key.charCodeAt(0);
var highSurrogate = charCode >= 0xD800 && charCode <= 0xDBFF;
var surrogate = highSurrogate || (charCode >= 0xDC00 && charCode <= 0xDFFF);
if (surrogate) {
key = "U+" + charCode.toString(16);
}
}
return key;
}
function recordKeyboardEvent(event) {
var key = escapeSurrogateHalf(event.key);
allEvents.events.push({
"code": event.code,
"key": key,
"which": event.which,
"location": event.location,
"ctrl": event.ctrlKey,
"meta": event.metaKey,
"shift": event.shiftKey,
"repeat": event.repeat,
"type": event.type
});
appendMessage(`${event.type}(` +
`code: ${event.code}, ` +
`key: ${key}, ` +
`which: ${event.which})`);
}
function recordPointerEvent(event) {
allEvents.events.push({
"type": event.type,
"button": event.button,
"buttons": event.buttons,
"pageX": event.pageX,
"pageY": event.pageY,
"target": event.target.id
});
appendMessage(`${event.type}(` +
`button: ${event.button}, ` +
`pageX: ${event.pageX}, ` +
`pageY: ${event.pageY}, ` +
`button: ${event.button}, ` +
`buttons: ${event.buttons}, ` +
`target id: ${event.target.id})`);
}
function recordFirstPointerMove(event) {
recordPointerEvent(event);
window.removeEventListener("mousemove", recordFirstPointerMove);
}
function resetEvents() {
allEvents.events.length = 0;
displayMessage("");
}
document.addEventListener("DOMContentLoaded", () => {
var keyReporter = document.getElementById("keys");
["keyup", "keypress", "keydown"].forEach((e) => {
keyReporter.addEventListener(e, recordKeyboardEvent);
});
var outer = document.getElementById("outer");
["click", "dblclick", "mousedown",
"mouseup", "contextmenu"].forEach((e) => {
outer.addEventListener(e, recordPointerEvent);
});
window.addEventListener("mousemove", recordFirstPointerMove);
//visual cue for mousemove
var pointer = document.getElementById("trackPointer");
window.addEventListener("mousemove", (e) => {
setTimeout(() => {
let offset = 15;
pointer.style.top = e.pageY + offset + "px";
pointer.style.left = e.pageX + offset + "px";
}, 30);
});
});
</script>
</head>
<body>
<div id="trackPointer"></div>
<div>
<h2>KeyReporter</h2>
<input type="text" id="keys" size="80">
</div>
<div>
<h2>ClickReporter</h2>
<div id="outer">
</div>
</div>
<div id="resultContainer">
<h2>Events</h2>
<div id="events"></div>
</div>
</body>
</html>

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

@ -732,7 +732,11 @@ Classifier::ApplyUpdates(nsTArray<TableUpdate*>* aUpdates)
LOG(("Failed to copy in-use directory for update."));
return rv;
}
CopyInUseLookupCacheForUpdate(); // i.e. mNewLookupCaches will be setup.
rv = CopyInUseLookupCacheForUpdate(); // i.e. mNewLookupCaches will be setup.
if (NS_FAILED(rv)) {
LOG(("Failed to create lookup caches from copied files."));
return rv;
}
}
LOG(("Applying %" PRIuSIZE " table updates.", aUpdates->Length()));
@ -1017,7 +1021,7 @@ Classifier::CopyInUseDirForUpdate()
return NS_OK;
}
void
nsresult
Classifier::CopyInUseLookupCacheForUpdate()
{
MOZ_ASSERT(mNewLookupCaches.IsEmpty(), "Update intermediaries is forgotten to "
@ -1028,8 +1032,12 @@ Classifier::CopyInUseLookupCacheForUpdate()
// Another option is to NOT pre-open these LookupCaches and
// do a "merge" instead of "swap" after update.
for (auto c: mLookupCaches) {
Unused << GetLookupCacheForUpdate(c->TableName());
if (!GetLookupCacheForUpdate(c->TableName())) {
return NS_ERROR_FAILURE;
}
}
return NS_OK;
}
nsresult
@ -1333,20 +1341,14 @@ Classifier::UpdateCache(TableUpdate* aUpdate)
LookupCache *
Classifier::GetLookupCache(const nsACString& aTable, bool aForUpdate)
{
if (aForUpdate) {
return GetLookupCacheFrom(aTable, mNewLookupCaches, mUpdatingDirectory);
}
return GetLookupCacheFrom(aTable, mLookupCaches, mRootStoreDirectory);
}
nsTArray<LookupCache*>& lookupCaches = aForUpdate ? mNewLookupCaches
: mLookupCaches;
auto& rootStoreDirectory = aForUpdate ? mUpdatingDirectory
: mRootStoreDirectory;
LookupCache *
Classifier::GetLookupCacheFrom(const nsACString& aTable,
nsTArray<LookupCache*>& aLookupCaches,
nsIFile* aRootStoreDirectory)
{
for (uint32_t i = 0; i < aLookupCaches.Length(); i++) {
if (aLookupCaches[i]->TableName().Equals(aTable)) {
return aLookupCaches[i];
for (auto c: lookupCaches) {
if (c->TableName().Equals(aTable)) {
return c;
}
}
@ -1356,9 +1358,9 @@ Classifier::GetLookupCacheFrom(const nsACString& aTable,
UniquePtr<LookupCache> cache;
nsCString provider = GetProvider(aTable);
if (StringEndsWith(aTable, NS_LITERAL_CSTRING("-proto"))) {
cache = MakeUnique<LookupCacheV4>(aTable, provider, aRootStoreDirectory);
cache = MakeUnique<LookupCacheV4>(aTable, provider, rootStoreDirectory);
} else {
cache = MakeUnique<LookupCacheV2>(aTable, provider, aRootStoreDirectory);
cache = MakeUnique<LookupCacheV2>(aTable, provider, rootStoreDirectory);
}
nsresult rv = cache->Init();
@ -1366,14 +1368,28 @@ Classifier::GetLookupCacheFrom(const nsACString& aTable,
return nullptr;
}
rv = cache->Open();
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_FILE_CORRUPTED) {
Reset();
}
if (NS_SUCCEEDED(rv)) {
lookupCaches.AppendElement(cache.get());
return cache.release();
}
// At this point we failed to open LookupCache.
//
// GetLookupCache for update and for other usage will run on update thread
// and worker thread respectively (Bug 1339760). Removing stuff only in
// their own realms potentially increases the concurrency.
if (aForUpdate) {
// Remove intermediaries no matter if it's due to file corruption or not.
RemoveUpdateIntermediaries();
return nullptr;
}
aLookupCaches.AppendElement(cache.get());
return cache.release();
// Non-update case.
if (rv == NS_ERROR_FILE_CORRUPTED) {
Reset(); // Not including the update intermediaries.
}
return nullptr;
}
nsresult

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

@ -32,7 +32,7 @@ public:
nsresult Open(nsIFile& aCacheDirectory);
void Close();
void Reset();
void Reset(); // Not including any intermediary for update.
/**
* Clear data for specific tables.
@ -126,7 +126,7 @@ private:
nsresult RecoverBackups();
nsresult CleanToDelete();
nsresult CopyInUseDirForUpdate();
void CopyInUseLookupCacheForUpdate();
nsresult CopyInUseLookupCacheForUpdate();
nsresult RegenActiveTables();

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

@ -57,12 +57,13 @@ Finder.prototype = {
destroy() {
if (this._iterator)
this._iterator.reset();
if (this._highlighter) {
let window = this._getWindow();
if (this._highlighter && window) {
// if we clear all the references before we hide the highlights (in both
// highlighting modes), we simply can't use them to find the ranges we
// need to clear from the selection.
this._highlighter.hide();
this._highlighter.clear();
this._highlighter.hide(window);
this._highlighter.clear(window);
}
this.listeners = [];
this._docShell.QueryInterface(Ci.nsIInterfaceRequestor)
@ -296,7 +297,7 @@ Finder.prototype = {
removeSelection() {
this._fastFind.collapseSelection();
this.enableSelection();
this.highlighter.clear();
this.highlighter.clear(this._getWindow());
},
focusContent() {
@ -475,6 +476,8 @@ Finder.prototype = {
},
_getWindow() {
if (!this._docShell)
return null;
return this._docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
},

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

@ -131,7 +131,7 @@ function mockAnonymousContentNode(domNode) {
};
}
let gWindows = new Map();
let gWindows = new WeakMap();
/**
* FinderHighlighter class that is used by Finder.jsm to take care of the
@ -337,9 +337,9 @@ FinderHighlighter.prototype = {
* @param {nsIDOMEvent} event When called from an event handler, this will
* be the triggering event.
*/
hide(window = null, skipRange = null, event = null) {
hide(window, skipRange = null, event = null) {
try {
window = (window || this.finder._getWindow()).top;
window = window.top;
} catch (ex) {
Cu.reportError(ex);
return;
@ -412,7 +412,7 @@ FinderHighlighter.prototype = {
let foundRange = this.finder._fastFind.getFoundRange();
if (data.result == Ci.nsITypeAheadFind.FIND_NOTFOUND || !data.searchString || !foundRange) {
this.hide();
this.hide(window);
return;
}
@ -454,14 +454,8 @@ FinderHighlighter.prototype = {
* keep to build the mask for.
*/
clear(window = null) {
if (!window) {
// Since we're clearing _all the things_, make sure we hide 'em all as well.
for (let win of gWindows.keys())
this.hide(win);
// Reset the Map, because no range references a node anymore.
gWindows.clear();
if (!window || !window.top)
return;
}
let dict = this.getForWindow(window.top);
this._finishOutlineAnimations(dict);
@ -479,6 +473,8 @@ FinderHighlighter.prototype = {
*/
onLocationChange() {
let window = this.finder._getWindow();
if (!window || !window.top)
return;
this.hide(window);
this.clear(window);
this._removeRangeOutline(window);
@ -494,9 +490,10 @@ FinderHighlighter.prototype = {
* @param {Boolean} useModalHighlight
*/
onModalHighlightChange(useModalHighlight) {
if (this._modal && !useModalHighlight) {
this.hide();
this.clear();
let window = this.finder._getWindow();
if (window && this._modal && !useModalHighlight) {
this.hide(window);
this.clear(window);
}
this._modal = useModalHighlight;
},