зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to mozilla-central. a=merge
This commit is contained in:
Коммит
2f4a6dc373
|
@ -361,35 +361,16 @@ class JSStreamConsumer final : public nsIInputStreamCallback {
|
|||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
static bool Start(nsIInputStream* aStream, JS::StreamConsumer* aConsumer,
|
||||
nsIGlobalObject* aGlobal, WorkerPrivate* aMaybeWorker) {
|
||||
nsresult rv;
|
||||
|
||||
bool nonBlocking = false;
|
||||
rv = aStream->IsNonBlocking(&nonBlocking);
|
||||
static bool Start(nsCOMPtr<nsIInputStream>&& aStream,
|
||||
JS::StreamConsumer* aConsumer, nsIGlobalObject* aGlobal,
|
||||
WorkerPrivate* aMaybeWorker) {
|
||||
nsCOMPtr<nsIAsyncInputStream> asyncStream;
|
||||
nsresult rv = NS_MakeAsyncNonBlockingInputStream(
|
||||
aStream.forget(), getter_AddRefs(asyncStream));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use a pipe to create an nsIAsyncInputStream if we don't already have one.
|
||||
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aStream);
|
||||
if (!asyncStream || !nonBlocking) {
|
||||
nsCOMPtr<nsIAsyncOutputStream> pipe;
|
||||
rv = NS_NewPipe2(getter_AddRefs(asyncStream), getter_AddRefs(pipe), true,
|
||||
true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEventTarget> thread =
|
||||
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
||||
|
||||
rv = NS_AsyncCopy(aStream, pipe, thread, NS_ASYNCCOPY_VIA_WRITESEGMENTS);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<JSStreamConsumer> consumer;
|
||||
if (aMaybeWorker) {
|
||||
RefPtr<WorkerStreamOwner> owner =
|
||||
|
@ -553,7 +534,8 @@ bool FetchUtil::StreamResponseToJS(JSContext* aCx, JS::HandleObject aObj,
|
|||
|
||||
nsIGlobalObject* global = xpc::NativeGlobal(js::UncheckedUnwrap(aObj));
|
||||
|
||||
if (!JSStreamConsumer::Start(body, aConsumer, global, aMaybeWorker)) {
|
||||
if (!JSStreamConsumer::Start(std::move(body), aConsumer, global,
|
||||
aMaybeWorker)) {
|
||||
return ThrowException(aCx, JSMSG_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
|
|
|
@ -2966,30 +2966,7 @@ void HTMLInputElement::Focus(ErrorResult& aError) {
|
|||
}
|
||||
}
|
||||
|
||||
if (mType != NS_FORM_INPUT_FILE) {
|
||||
nsGenericHTMLElement::Focus(aError);
|
||||
return;
|
||||
}
|
||||
|
||||
// For file inputs, focus the first button instead. In the case of there
|
||||
// being two buttons (when the picker is a directory picker) the user can
|
||||
// tab to the next one.
|
||||
nsIFrame* frame = GetPrimaryFrame();
|
||||
if (frame) {
|
||||
for (nsIFrame* childFrame : frame->PrincipalChildList()) {
|
||||
// See if the child is a button control.
|
||||
nsCOMPtr<nsIFormControl> formCtrl =
|
||||
do_QueryInterface(childFrame->GetContent());
|
||||
if (formCtrl && formCtrl->ControlType() == NS_FORM_BUTTON_BUTTON) {
|
||||
nsCOMPtr<Element> element = do_QueryInterface(formCtrl);
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm && element) {
|
||||
fm->SetFocus(element, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
nsGenericHTMLElement::Focus(aError);
|
||||
}
|
||||
|
||||
#if !defined(ANDROID) && !defined(XP_MACOSX)
|
||||
|
@ -3651,8 +3628,7 @@ bool HTMLInputElement::ShouldPreventDOMActivateDispatch(
|
|||
|
||||
return target->GetParent() == this &&
|
||||
target->IsRootOfNativeAnonymousSubtree() &&
|
||||
target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
|
||||
nsGkAtoms::button, eCaseMatters);
|
||||
target->IsHTMLElement(nsGkAtoms::button);
|
||||
}
|
||||
|
||||
nsresult HTMLInputElement::MaybeInitPickers(EventChainPostVisitor& aVisitor) {
|
||||
|
@ -3910,6 +3886,7 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
|
|||
case NS_FORM_INPUT_BUTTON:
|
||||
case NS_FORM_INPUT_RESET:
|
||||
case NS_FORM_INPUT_SUBMIT:
|
||||
case NS_FORM_INPUT_FILE:
|
||||
case NS_FORM_INPUT_IMAGE: // Bug 34418
|
||||
case NS_FORM_INPUT_COLOR: {
|
||||
DispatchSimulatedClick(this, aVisitor.mEvent->IsTrusted(),
|
||||
|
@ -6324,18 +6301,13 @@ bool HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
|
|||
const bool defaultFocusable = true;
|
||||
#endif
|
||||
|
||||
if (mType == NS_FORM_INPUT_FILE || mType == NS_FORM_INPUT_NUMBER ||
|
||||
mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) {
|
||||
if (mType == NS_FORM_INPUT_NUMBER || mType == NS_FORM_INPUT_TIME ||
|
||||
mType == NS_FORM_INPUT_DATE) {
|
||||
if (aTabIndex) {
|
||||
// We only want our native anonymous child to be tabable to, not ourself.
|
||||
*aTabIndex = -1;
|
||||
}
|
||||
if (mType == NS_FORM_INPUT_NUMBER || mType == NS_FORM_INPUT_TIME ||
|
||||
mType == NS_FORM_INPUT_DATE) {
|
||||
*aIsFocusable = true;
|
||||
} else {
|
||||
*aIsFocusable = defaultFocusable;
|
||||
}
|
||||
*aIsFocusable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -899,8 +899,9 @@ static bool WasmExtractCode(JSContext* cx, unsigned argc, Value* vp) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool WasmHasTier2CompilationCompleted(JSContext* cx, unsigned argc,
|
||||
Value* vp) {
|
||||
enum class Flag { Tier2Complete, Deserialized };
|
||||
|
||||
static bool WasmReturnFlag(JSContext* cx, unsigned argc, Value* vp, Flag flag) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (!args.get(0).isObject()) {
|
||||
|
@ -915,10 +916,29 @@ static bool WasmHasTier2CompilationCompleted(JSContext* cx, unsigned argc,
|
|||
return false;
|
||||
}
|
||||
|
||||
args.rval().set(BooleanValue(!module->module().testingTier2Active()));
|
||||
bool b;
|
||||
switch (flag) {
|
||||
case Flag::Tier2Complete:
|
||||
b = !module->module().testingTier2Active();
|
||||
break;
|
||||
case Flag::Deserialized:
|
||||
b = module->module().loggingDeserialized();
|
||||
break;
|
||||
}
|
||||
|
||||
args.rval().set(BooleanValue(b));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool WasmHasTier2CompilationCompleted(JSContext* cx, unsigned argc,
|
||||
Value* vp) {
|
||||
return WasmReturnFlag(cx, argc, vp, Flag::Tier2Complete);
|
||||
}
|
||||
|
||||
static bool WasmLoadedFromCache(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return WasmReturnFlag(cx, argc, vp, Flag::Deserialized);
|
||||
}
|
||||
|
||||
static bool IsLazyFunction(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() != 1) {
|
||||
|
@ -6041,6 +6061,11 @@ gc::ZealModeHelpText),
|
|||
" Returns a boolean indicating whether a given module has finished compiled code for tier2. \n"
|
||||
"This will return true early if compilation isn't two-tiered. "),
|
||||
|
||||
JS_FN_HELP("wasmLoadedFromCache", WasmLoadedFromCache, 1, 0,
|
||||
"wasmLoadedFromCache(module)",
|
||||
" Returns a boolean indicating whether a given module was deserialized directly from a\n"
|
||||
" cache (as opposed to compiled from bytecode)."),
|
||||
|
||||
JS_FN_HELP("wasmReftypesEnabled", WasmReftypesEnabled, 1, 0,
|
||||
"wasmReftypesEnabled()",
|
||||
" Returns a boolean indicating whether the WebAssembly reftypes proposal is enabled."),
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// |jit-test| skip-if: !wasmStreamingIsSupported()
|
||||
// |jit-test| skip-if: !wasmCachingIsSupported()
|
||||
|
||||
const {Module, Instance, compileStreaming} = WebAssembly;
|
||||
load(libdir + "wasm-binary.js");
|
||||
|
||||
const {Module, Instance, compileStreaming, RuntimeError} = WebAssembly;
|
||||
|
||||
function testCached(code, imports, test) {
|
||||
if (typeof code === 'string')
|
||||
|
@ -12,20 +14,21 @@ function testCached(code, imports, test) {
|
|||
compileStreaming(cache)
|
||||
.then(m => {
|
||||
test(new Instance(m, imports));
|
||||
assertEq(wasmLoadedFromCache(m), false);
|
||||
while (!wasmHasTier2CompilationCompleted(m)) {
|
||||
sleep(1);
|
||||
}
|
||||
assertEq(cache.cached, wasmCachingIsSupported());
|
||||
assertEq(cache.cached, true);
|
||||
return compileStreaming(cache);
|
||||
})
|
||||
.then(m => {
|
||||
test(new Instance(m, imports));
|
||||
assertEq(cache.cached, wasmCachingIsSupported());
|
||||
assertEq(wasmLoadedFromCache(m), true);
|
||||
assertEq(cache.cached, true);
|
||||
|
||||
if (wasmCachingIsSupported()) {
|
||||
let m2 = wasmCompileInSeparateProcess(code);
|
||||
test(new Instance(m2, imports));
|
||||
}
|
||||
let m2 = wasmCompileInSeparateProcess(code);
|
||||
test(new Instance(m2, imports));
|
||||
assertEq(wasmLoadedFromCache(m2), true);
|
||||
|
||||
success = true;
|
||||
})
|
||||
|
@ -78,4 +81,16 @@ testCached(
|
|||
}
|
||||
);
|
||||
|
||||
testCached(
|
||||
moduleWithSections([
|
||||
sigSection([{args:[], ret:VoidCode}]),
|
||||
declSection([0]),
|
||||
exportSection([{funcIndex:0, name:"run"}]),
|
||||
bodySection([funcBody({locals:[], body:[UnreachableCode]})]),
|
||||
nameSection([funcNameSubsection([{name:"wee"}])])
|
||||
]),
|
||||
undefined,
|
||||
i => assertErrorMessage(() => i.exports.run(), RuntimeError, /unreachable/)
|
||||
);
|
||||
|
||||
// Note: a fuller behavioral test of caching is in bench/wasm_box2d.js.
|
||||
|
|
|
@ -2778,6 +2778,12 @@ static bool Reject(JSContext* cx, const CompileArgs& args,
|
|||
return PromiseObject::reject(cx, promise, rejectionValue);
|
||||
}
|
||||
|
||||
static void LogAsync(JSContext* cx, const char* funcName,
|
||||
const Module& module) {
|
||||
Log(cx, "async %s succeeded%s", funcName,
|
||||
module.loggingDeserialized() ? " (loaded from cache)" : "");
|
||||
}
|
||||
|
||||
enum class Ret { Pair, Instance };
|
||||
|
||||
class AsyncInstantiateTask : public OffThreadPromiseTask {
|
||||
|
@ -2840,7 +2846,7 @@ class AsyncInstantiateTask : public OffThreadPromiseTask {
|
|||
return RejectWithPendingException(cx, promise);
|
||||
}
|
||||
|
||||
Log(cx, "async instantiate succeeded");
|
||||
LogAsync(cx, "instantiate", *module_);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -2875,7 +2881,7 @@ static bool ResolveCompile(JSContext* cx, const Module& module,
|
|||
return RejectWithPendingException(cx, promise);
|
||||
}
|
||||
|
||||
Log(cx, "async compile succeeded");
|
||||
LogAsync(cx, "compile", module);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -286,14 +286,6 @@ MutableModule Module::deserialize(const uint8_t* begin, size_t size,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (metadata->nameCustomSectionIndex) {
|
||||
metadata->namePayload =
|
||||
customSections[*metadata->nameCustomSectionIndex].payload;
|
||||
} else {
|
||||
MOZ_RELEASE_ASSERT(!metadata->moduleName);
|
||||
MOZ_RELEASE_ASSERT(metadata->funcNames.empty());
|
||||
}
|
||||
|
||||
SharedCode code;
|
||||
cursor = Code::deserialize(cursor, linkData, *metadata, &code);
|
||||
if (!cursor) {
|
||||
|
@ -303,9 +295,18 @@ MutableModule Module::deserialize(const uint8_t* begin, size_t size,
|
|||
MOZ_RELEASE_ASSERT(cursor == begin + size);
|
||||
MOZ_RELEASE_ASSERT(!!maybeMetadata == code->metadata().isAsmJS());
|
||||
|
||||
if (metadata->nameCustomSectionIndex) {
|
||||
metadata->namePayload =
|
||||
customSections[*metadata->nameCustomSectionIndex].payload;
|
||||
} else {
|
||||
MOZ_RELEASE_ASSERT(!metadata->moduleName);
|
||||
MOZ_RELEASE_ASSERT(metadata->funcNames.empty());
|
||||
}
|
||||
|
||||
return js_new<Module>(*code, std::move(imports), std::move(exports),
|
||||
std::move(dataSegments), std::move(elemSegments),
|
||||
std::move(customSections));
|
||||
std::move(customSections), nullptr, nullptr, nullptr,
|
||||
/* loggingDeserialized = */ true);
|
||||
}
|
||||
|
||||
void Module::serialize(const LinkData& linkData,
|
||||
|
|
|
@ -101,6 +101,11 @@ class Module : public JS::WasmModule {
|
|||
|
||||
mutable Tier2Listener tier2Listener_;
|
||||
|
||||
// This flag is used for logging (and testing) purposes to indicate
|
||||
// whether the module was deserialized (from a cache).
|
||||
|
||||
const bool loggingDeserialized_;
|
||||
|
||||
// This flag is only used for testing purposes and is cleared on success or
|
||||
// failure. The field is racily polled from various threads.
|
||||
|
||||
|
@ -140,7 +145,8 @@ class Module : public JS::WasmModule {
|
|||
CustomSectionVector&& customSections,
|
||||
UniqueConstBytes debugUnlinkedCode = nullptr,
|
||||
UniqueLinkData debugLinkData = nullptr,
|
||||
const ShareableBytes* debugBytecode = nullptr)
|
||||
const ShareableBytes* debugBytecode = nullptr,
|
||||
bool loggingDeserialized = false)
|
||||
: code_(&code),
|
||||
imports_(std::move(imports)),
|
||||
exports_(std::move(exports)),
|
||||
|
@ -151,6 +157,7 @@ class Module : public JS::WasmModule {
|
|||
debugUnlinkedCode_(std::move(debugUnlinkedCode)),
|
||||
debugLinkData_(std::move(debugLinkData)),
|
||||
debugBytecode_(debugBytecode),
|
||||
loggingDeserialized_(loggingDeserialized),
|
||||
testingTier2Active_(false) {
|
||||
MOZ_ASSERT_IF(metadata().debugEnabled,
|
||||
debugUnlinkedCode_ && debugLinkData_);
|
||||
|
@ -194,6 +201,7 @@ class Module : public JS::WasmModule {
|
|||
JS::OptimizedEncodingListener& listener) const;
|
||||
static RefPtr<Module> deserialize(const uint8_t* begin, size_t size,
|
||||
Metadata* maybeMetadata = nullptr);
|
||||
bool loggingDeserialized() const { return loggingDeserialized_; }
|
||||
|
||||
// JS API and JS::WasmModule implementation:
|
||||
|
||||
|
|
|
@ -212,8 +212,6 @@ static already_AddRefed<Element> MakeAnonButton(Document* aDoc,
|
|||
// NOTE: SetIsNativeAnonymousRoot() has to be called before setting any
|
||||
// attribute.
|
||||
button->SetIsNativeAnonymousRoot();
|
||||
button->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
|
||||
NS_LITERAL_STRING("button"), false);
|
||||
|
||||
// Set the file picking button text depending on the current locale.
|
||||
nsAutoString buttonTxt;
|
||||
|
@ -241,11 +239,8 @@ static already_AddRefed<Element> MakeAnonButton(Document* aDoc,
|
|||
buttonElement->SetAccessKey(aAccessKey, IgnoreErrors());
|
||||
}
|
||||
|
||||
// Both elements are given the same tab index so that the user can tab
|
||||
// to the file control at the correct index, and then between the two
|
||||
// buttons.
|
||||
buttonElement->SetTabIndex(aInputElement->TabIndex(), IgnoreErrors());
|
||||
|
||||
// We allow tabbing over the input itself, not the button.
|
||||
buttonElement->SetTabIndex(-1, IgnoreErrors());
|
||||
return button.forget();
|
||||
}
|
||||
|
||||
|
@ -277,7 +272,7 @@ nsresult nsFileControlFrame::CreateAnonymousContent(
|
|||
|
||||
// Update the displayed text to reflect the current element's value.
|
||||
nsAutoString value;
|
||||
HTMLInputElement::FromNode(mContent)->GetDisplayFileName(value);
|
||||
fileContent->GetDisplayFileName(value);
|
||||
UpdateDisplayedValue(value, false);
|
||||
|
||||
aElements.AppendElement(mTextContent);
|
||||
|
|
|
@ -26,7 +26,7 @@ window.oTarget = null;
|
|||
window.fileInputGotClick = false;
|
||||
|
||||
function test() {
|
||||
// Try to find the 'Browse...' using tabbing.
|
||||
// Try to find the '<input>' using tabbing.
|
||||
var i = 0;
|
||||
while (!window.oTarget && i < 100) {
|
||||
++i;
|
||||
|
@ -39,8 +39,7 @@ function test() {
|
|||
return;
|
||||
}
|
||||
|
||||
ok(window.oTarget instanceof HTMLButtonElement, "Should have focused an input element!")
|
||||
ok(SpecialPowers.wrap(window.oTarget).type == "button", "Should have focused 'Browse...' button!");
|
||||
ok(window.oTarget instanceof HTMLInputElement, "Should have focused the input element!");
|
||||
var e = document.createEvent("mouseevents");
|
||||
e.initMouseEvent("click", true, true, window, 0, 1, 1, 1, 1,
|
||||
false, false, false, false, 0, null);
|
||||
|
|
|
@ -495,7 +495,7 @@ input[type="file"] > label {
|
|||
}
|
||||
|
||||
/* button part of file selector */
|
||||
input[type="file"] > button[type="button"] {
|
||||
input[type="file"] > button {
|
||||
block-size: inherit;
|
||||
font-size: unset;
|
||||
letter-spacing: unset;
|
||||
|
@ -703,8 +703,7 @@ button::-moz-focus-inner,
|
|||
input[type="color"]::-moz-focus-inner,
|
||||
input[type="reset"]::-moz-focus-inner,
|
||||
input[type="button"]::-moz-focus-inner,
|
||||
input[type="submit"]::-moz-focus-inner,
|
||||
input[type="file"] > button[type="button"]::-moz-focus-inner {
|
||||
input[type="submit"]::-moz-focus-inner {
|
||||
/* Note this padding only affects the -moz-focus-inner ring, not the button itself */
|
||||
padding-block-start: 0px;
|
||||
padding-inline-end: 2px;
|
||||
|
@ -717,8 +716,7 @@ button:-moz-focusring::-moz-focus-inner,
|
|||
input[type="color"]:-moz-focusring::-moz-focus-inner,
|
||||
input[type="reset"]:-moz-focusring::-moz-focus-inner,
|
||||
input[type="button"]:-moz-focusring::-moz-focus-inner,
|
||||
input[type="submit"]:-moz-focusring::-moz-focus-inner,
|
||||
input[type="file"] > button[type="button"]:-moz-focusring::-moz-focus-inner {
|
||||
input[type="submit"]:-moz-focusring::-moz-focus-inner {
|
||||
border-color: ButtonText;
|
||||
}
|
||||
|
||||
|
|
|
@ -715,7 +715,8 @@ canvas {
|
|||
/* focusable content: anything w/ tabindex >=0 is focusable, but we
|
||||
skip drawing a focus outline on a few things that handle it
|
||||
themselves. */
|
||||
:-moz-focusring:not(input):not(button):not(select):not(textarea):not(iframe):not(frame):not(body):not(html) {
|
||||
:-moz-focusring:not(input):not(button):not(select):not(textarea):not(iframe):not(frame):not(body):not(html),
|
||||
input[type="file"]:-moz-focusring {
|
||||
/* Don't specify the outline-color, we should always use initial value. */
|
||||
outline: 1px dotted;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>HTML Test: file input can be programatically focused before layout</title>
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#focus">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=505355">
|
||||
<link rel="author" title="Mozilla" href="https://mozilla.org/">
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<input type="file">
|
||||
<script>
|
||||
test(function() {
|
||||
let input = document.querySelector("input");
|
||||
assert_not_equals(document.activeElement, input);
|
||||
input.focus();
|
||||
assert_equals(document.activeElement, input);
|
||||
});
|
||||
</script>
|
|
@ -399,7 +399,7 @@ function runBasicTest(aIsEditable, aInDesignMode, aDescription) {
|
|||
description: "input[type=file]",
|
||||
focusable: !aInDesignMode,
|
||||
focusEventNotFired: aIsEditable && !aInDesignMode,
|
||||
expectedEnabled: kEnabledStateOnReadonlyField },
|
||||
expectedEnabled: kEnabledStateOnNonEditableElement },
|
||||
{ id: "button",
|
||||
description: "input[type=button]",
|
||||
focusable: !aInDesignMode,
|
||||
|
|
Загрузка…
Ссылка в новой задаче