mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to b2g-inbound
This commit is contained in:
commit
bc6e90f6e6
2
.clang-format-ignore
Normal file
2
.clang-format-ignore
Normal file
@ -0,0 +1,2 @@
|
||||
\mfbt/
|
||||
\js/
|
@ -16,8 +16,8 @@ support-files =
|
||||
[browser_toolbox_options.js]
|
||||
[browser_toolbox_options_disable_cache.js]
|
||||
[browser_toolbox_options_disable_js.js]
|
||||
[browser_toolbox_raise.js]
|
||||
skip-if = os == "win"
|
||||
# [browser_toolbox_raise.js] # Bug 962258
|
||||
# skip-if = os == "win"
|
||||
[browser_toolbox_ready.js]
|
||||
[browser_toolbox_select_event.js]
|
||||
[browser_toolbox_sidebar.js]
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
@ -989,7 +989,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
rv = aPrincipal->GetOrigin(getter_Copies(origin));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JSString*> originValue(cx, JS_InternString(cx, origin.get()));
|
||||
JS::Rooted<JSString*> originValue(cx, JS_NewStringCopyN(cx, origin.get(), origin.Length()));
|
||||
JS_DefineProperty(cx, principalObj, "origin", STRING_TO_JSVAL(originValue), nullptr, nullptr, JSPROP_ENUMERATE);
|
||||
|
||||
bool browser;
|
||||
|
@ -3429,7 +3429,7 @@ nsObjectLoadingContent::TeardownProtoChain()
|
||||
bool
|
||||
nsObjectLoadingContent::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
JS::MutableHandle<JSPropertyDescriptor> aDesc)
|
||||
{
|
||||
// We don't resolve anything; we just try to make sure we're instantiated
|
||||
|
||||
|
@ -156,7 +156,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
// Helper for WebIDL newResolve
|
||||
bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
JS::MutableHandle<JSPropertyDescriptor> aDesc);
|
||||
// Helper for WebIDL enumeration
|
||||
void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& /* unused */,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
@ -841,7 +841,7 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
|
||||
JS::CompileOptions options(cx);
|
||||
FillCompileOptionsForRequest(aRequest, global, &options);
|
||||
|
||||
if (!JS::CanCompileOffThread(cx, options)) {
|
||||
if (!JS::CanCompileOffThread(cx, options, aRequest->mScriptText.Length())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -2078,7 +2078,9 @@ HTMLInputElement::GetStepBase() const
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLInputElement::GetValueIfStepped(int32_t aStep, Decimal* aNextStep)
|
||||
HTMLInputElement::GetValueIfStepped(int32_t aStep,
|
||||
StepCallerType aCallerType,
|
||||
Decimal* aNextStep)
|
||||
{
|
||||
if (!DoStepDownStepUpApply()) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
@ -2086,7 +2088,11 @@ HTMLInputElement::GetValueIfStepped(int32_t aStep, Decimal* aNextStep)
|
||||
|
||||
Decimal step = GetStep();
|
||||
if (step == kStepAny) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
if (aCallerType != CALLED_FOR_USER_EVENT) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
// Allow the spin buttons and up/down arrow keys to do something sensible:
|
||||
step = GetDefaultStep();
|
||||
}
|
||||
|
||||
Decimal value = GetValueAsDecimal();
|
||||
@ -2168,7 +2174,7 @@ HTMLInputElement::ApplyStep(int32_t aStep)
|
||||
{
|
||||
Decimal nextStep = Decimal::nan(); // unchanged if value will not change
|
||||
|
||||
nsresult rv = GetValueIfStepped(aStep, &nextStep);
|
||||
nsresult rv = GetValueIfStepped(aStep, CALLED_FOR_SCRIPT, &nextStep);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && nextStep.isFinite()) {
|
||||
SetValue(nextStep);
|
||||
@ -3603,7 +3609,7 @@ HTMLInputElement::StepNumberControlForUserEvent(int32_t aDirection)
|
||||
{
|
||||
Decimal newValue = Decimal::nan(); // unchanged if value will not change
|
||||
|
||||
nsresult rv = GetValueIfStepped(aDirection, &newValue);
|
||||
nsresult rv = GetValueIfStepped(aDirection, CALLED_FOR_USER_EVENT, &newValue);
|
||||
|
||||
if (NS_FAILED(rv) || !newValue.isFinite()) {
|
||||
return; // value should not or will not change
|
||||
|
@ -1112,6 +1112,11 @@ protected:
|
||||
*/
|
||||
Decimal GetDefaultStep() const;
|
||||
|
||||
enum StepCallerType {
|
||||
CALLED_FOR_USER_EVENT,
|
||||
CALLED_FOR_SCRIPT
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the aValue outparam to the value that this input would take if
|
||||
* someone tries to step aStep steps and this input's value would change as
|
||||
@ -1124,7 +1129,9 @@ protected:
|
||||
* was initiated by a stepUp()/stepDown() call from script under conditions
|
||||
* that such a call should throw.
|
||||
*/
|
||||
nsresult GetValueIfStepped(int32_t aStep, Decimal* aNextStep);
|
||||
nsresult GetValueIfStepped(int32_t aStepCount,
|
||||
StepCallerType aCallerType,
|
||||
Decimal* aNextStep);
|
||||
|
||||
/**
|
||||
* Apply a step change from stepUp or stepDown by multiplying aStep by the
|
||||
|
@ -82,7 +82,7 @@ function expectedValueAfterStepUpOrDown(stepFactor, element) {
|
||||
}
|
||||
var step = getStep(element);
|
||||
if (step == "any") {
|
||||
return value;
|
||||
step = 1;
|
||||
}
|
||||
|
||||
var minimum = getMinimum(element);
|
||||
@ -187,6 +187,15 @@ function test() {
|
||||
expectedVal = 0;
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for number control where scripted preventDefault() should prevent the value changing");
|
||||
|
||||
// Test step="any" behavior:
|
||||
var oldStep = elem.step;
|
||||
elem.step = "any";
|
||||
oldVal = elem.value = 0;
|
||||
expectedVal = expectedValAfterKeyEvent(key, elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for number control with value set to the midpoint and step='any' (" + oldVal + ")");
|
||||
elem.step = oldStep; // restore
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,20 @@ function test() {
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
|
||||
is(input.value, 0, "Test mouseup on spin-down button");
|
||||
|
||||
// Test step="any" behavior:
|
||||
input.value = 0;
|
||||
var oldStep = input.step;
|
||||
input.step = "any";
|
||||
synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" });
|
||||
is(input.value, 1, "Test step-up on mousedown on spin-up button with step='any'");
|
||||
synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" });
|
||||
is(input.value, 1, "Test mouseup on spin-up button with step='any'");
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" });
|
||||
is(input.value, 0, "Test step-down on mousedown on spin-down button with step='any'");
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
|
||||
is(input.value, 0, "Test mouseup on spin-down button with step='any'");
|
||||
input.step = oldStep; // restore
|
||||
|
||||
// Test that preventDefault() works:
|
||||
function preventDefault(e) {
|
||||
e.preventDefault();
|
||||
|
@ -2656,7 +2656,7 @@ nsXULPrototypeScript::Compile(const char16_t* aText,
|
||||
JS::ExposeObjectToActiveJS(scope);
|
||||
}
|
||||
|
||||
if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options)) {
|
||||
if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options, aTextLength)) {
|
||||
if (!JS::CompileOffThread(cx, scope, options,
|
||||
static_cast<const jschar*>(aText), aTextLength,
|
||||
OffThreadScriptReceiverCallback,
|
||||
|
@ -17,13 +17,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=929236
|
||||
|
||||
<script>
|
||||
var jsFuns = SpecialPowers.Cu.getJSTestingFunctions();
|
||||
ok(jsFuns.isAsmJSCompilationAvailable());
|
||||
ok(jsFuns.isAsmJSCompilationAvailable(), "asm.js compilation is available");
|
||||
|
||||
// generate a big ol asm.js module and compile it async so that we can hit
|
||||
// the asm.js cache.
|
||||
|
||||
var code = "function f() { 'use asm';\n";
|
||||
for (var i = 0; i < 1000; i++)
|
||||
for (var i = 0; i < 5000; i++)
|
||||
code += "function g" + i + "() { return " + i + "}\n";
|
||||
code += "return g42 }\n";
|
||||
code += "ok(jsFuns.isAsmJSModule(f), 'f is an asm.js module')\n";
|
||||
@ -31,7 +31,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=929236
|
||||
code += "ok(jsFuns.isAsmJSFunction(g42), 'g42 is an asm.js function')\n";
|
||||
code += "ok(g42() === 42, 'g42 returns the correct result')\n";
|
||||
code += "finishedEvalAsync(f);";
|
||||
ok(code.length > 10000);
|
||||
ok(code.length > 100000, "code is long enough to definitely hit the cache");
|
||||
|
||||
function evalAsync(code) {
|
||||
var blob = new Blob([code], {type:"application/javascript"});
|
||||
|
@ -23,9 +23,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=944821
|
||||
// so that we can hit the asm.js cache.
|
||||
|
||||
var code = "function f() { 'use asm';\n";
|
||||
for (var i = 0; i < 1000; i++)
|
||||
for (var i = 0; i < 5000; i++)
|
||||
code += "function g" + i + "() { return " + i + "}\n";
|
||||
ok(code.length > 10000, "code is long enough");
|
||||
ok(code.length > 100000, "code is long enough to definitely hit the cache");
|
||||
|
||||
const N = 4;
|
||||
|
||||
|
@ -20,10 +20,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=941830
|
||||
ok(jsFuns.isAsmJSCompilationAvailable());
|
||||
|
||||
var asmjsCode = "function f() { 'use asm';";
|
||||
for (var i = 0; i < 1000; i++)
|
||||
for (var i = 0; i < 5000; i++)
|
||||
asmjsCode += "function g" + i + "() { return " + i + "}";
|
||||
asmjsCode += "return g42 }";
|
||||
ok(asmjsCode.length > 10000);
|
||||
ok(asmjsCode.length > 100000, "code is long enough to definitely hit the cache");
|
||||
|
||||
var workerCode = asmjsCode;
|
||||
workerCode += "if (f()() !== 42) postMessage('fail'); else postMessage('ok');";
|
||||
|
@ -1488,7 +1488,7 @@ Navigator::GetMozAudioChannelManager(ErrorResult& aRv)
|
||||
bool
|
||||
Navigator::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
JS::MutableHandle<JSPropertyDescriptor> aDesc)
|
||||
{
|
||||
if (!JSID_IS_STRING(aId)) {
|
||||
return true;
|
||||
@ -1534,14 +1534,14 @@ Navigator::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
bool hasPermission = CheckPermission("settings-read") ||
|
||||
CheckPermission("settings-write");
|
||||
if (!hasPermission) {
|
||||
aValue.setNull();
|
||||
FillPropertyDescriptor(aDesc, aObject, JS::NullValue(), false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (name.EqualsLiteral("mozDownloadManager")) {
|
||||
if (!CheckPermission("downloads")) {
|
||||
aValue.setNull();
|
||||
FillPropertyDescriptor(aDesc, aObject, JS::NullValue(), false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1556,7 +1556,7 @@ Navigator::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
return false;
|
||||
}
|
||||
|
||||
aValue.setObject(*domObject);
|
||||
FillPropertyDescriptor(aDesc, aObject, JS::ObjectValue(*domObject), false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1597,7 +1597,7 @@ Navigator::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
return Throw(aCx, NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
aValue.set(prop_val);
|
||||
FillPropertyDescriptor(aDesc, aObject, prop_val, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -232,7 +232,8 @@ public:
|
||||
ErrorResult& aRv);
|
||||
#endif // MOZ_MEDIA_NAVIGATOR
|
||||
bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId, JS::MutableHandle<JS::Value> aValue);
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JSPropertyDescriptor> aDesc);
|
||||
void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
|
||||
ErrorResult& aRv);
|
||||
|
||||
|
@ -3341,46 +3341,14 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
return DefineComponentsShim(cx, obj, win);
|
||||
}
|
||||
|
||||
nsIScriptContext *my_context = win->GetContextInternal();
|
||||
|
||||
// Don't resolve standard classes on XrayWrappers, only resolve them if we're
|
||||
// resolving on the real global object.
|
||||
if (!xpc::WrapperFactory::IsXrayWrapper(obj)) {
|
||||
bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj);
|
||||
if (!isXray) {
|
||||
bool did_resolve = false;
|
||||
bool ok = true;
|
||||
JS::Rooted<JS::Value> exn(cx, JSVAL_VOID);
|
||||
|
||||
{
|
||||
// Resolve standard classes on my_context's JSContext (or on cx,
|
||||
// if we don't have a my_context yet), in case the two contexts
|
||||
// have different origins. We want lazy standard class
|
||||
// initialization to behave as if it were done eagerly, on each
|
||||
// window's own context (not on some other window-caller's
|
||||
// context).
|
||||
AutoPushJSContext my_cx(my_context ? my_context->GetNativeContext() : cx);
|
||||
JSAutoCompartment ac(my_cx, obj);
|
||||
|
||||
ok = JS_ResolveStandardClass(my_cx, obj, id, &did_resolve);
|
||||
|
||||
if (!ok) {
|
||||
// Trust the JS engine (or the script security manager) to set
|
||||
// the exception in the JS engine.
|
||||
|
||||
if (!JS_GetPendingException(my_cx, &exn)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Return NS_OK to avoid stomping over the exception that was passed
|
||||
// down from the ResolveStandardClass call.
|
||||
// Note that the order of the JS_ClearPendingException and
|
||||
// JS_SetPendingException is important in the case that my_cx == cx.
|
||||
|
||||
JS_ClearPendingException(my_cx);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
JS_SetPendingException(cx, exn);
|
||||
if (!JS_ResolveStandardClass(cx, obj, id, &did_resolve)) {
|
||||
// Return NS_OK to avoid stomping over the exception that was passed
|
||||
// down from the ResolveStandardClass call.
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3391,14 +3359,10 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
}
|
||||
}
|
||||
|
||||
if (!my_context || !my_context->IsContextInitialized()) {
|
||||
// The context is not yet initialized so there's nothing we can do
|
||||
// here yet.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (sLocation_id == id) {
|
||||
// WebIDL quickstubs handle location for us, but Xrays don't see those. So if
|
||||
// we're an Xray, we have to resolve stuff here to make "window.location =
|
||||
// someString" work.
|
||||
if (sLocation_id == id && isXray) {
|
||||
// This must be done even if we're just getting the value of
|
||||
// window.location (i.e. no checking flags & JSRESOLVE_ASSIGNING
|
||||
// here) since we must define window.location to prevent the
|
||||
@ -3429,7 +3393,10 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (sTop_id == id) {
|
||||
// WebIDL quickstubs handle "top" for us, but Xrays don't see those. So if
|
||||
// we're an Xray and we want "top" to be JSPROP_PERMANENT, we need to resolve
|
||||
// it here.
|
||||
if (sTop_id == id && isXray) {
|
||||
nsCOMPtr<nsIDOMWindow> top;
|
||||
nsresult rv = win->GetScriptableTop(getter_AddRefs(top));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -6001,14 +6001,20 @@ class CGNewResolveHook(CGAbstractBindingMethod):
|
||||
|
||||
def generate_code(self):
|
||||
return CGIndenter(CGGeneric(
|
||||
"JS::Rooted<JS::Value> value(cx);\n"
|
||||
"if (!self->DoNewResolve(cx, obj, id, &value)) {\n"
|
||||
"JS::Rooted<JSPropertyDescriptor> desc(cx);\n"
|
||||
"if (!self->DoNewResolve(cx, obj, id, &desc)) {\n"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
"if (value.isUndefined()) {\n"
|
||||
"if (!desc.object()) {\n"
|
||||
" return true;\n"
|
||||
"}\n"
|
||||
"if (!JS_DefinePropertyById(cx, obj, id, value, nullptr, nullptr, JSPROP_ENUMERATE)) {\n"
|
||||
"// If desc.value() is undefined, then the DoNewResolve call\n"
|
||||
"// has already defined it on the object. Don't try to also\n"
|
||||
"// define it.\n"
|
||||
"if (!desc.value().isUndefined() &&\n"
|
||||
" !JS_DefinePropertyById(cx, obj, id, desc.value(),\n"
|
||||
" desc.getter(), desc.setter(),\n"
|
||||
" desc.attributes())) {\n"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
"objp.set(obj);\n"
|
||||
@ -7722,14 +7728,7 @@ class CGResolveOwnPropertyViaNewresolve(CGAbstractBindingMethod):
|
||||
callArgs="")
|
||||
def generate_code(self):
|
||||
return CGIndenter(CGGeneric(
|
||||
"JS::Rooted<JS::Value> value(cx);\n"
|
||||
"if (!self->DoNewResolve(cx, obj, id, &value)) {\n"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
"if (!value.isUndefined()) {\n"
|
||||
" FillPropertyDescriptor(desc, wrapper, value, /* readonly = */ false);\n"
|
||||
"}\n"
|
||||
"return true;"))
|
||||
"return self->DoNewResolve(cx, wrapper, id, desc);"))
|
||||
|
||||
class CGEnumerateOwnProperties(CGAbstractStaticMethod):
|
||||
def __init__(self, descriptor):
|
||||
|
@ -510,6 +510,12 @@ ok(!e.isTrusted, "Event should not be trusted");
|
||||
is(e.value, 1, "value should be 1");
|
||||
document.dispatchEvent(e);
|
||||
is(receivedEvent, e, "Wrong event!");
|
||||
e = new DeviceLightEvent("hello", {value: Infinity} );
|
||||
is(e.value, Infinity, "value should be positive infinity");
|
||||
e = new DeviceLightEvent("hello", {value: -Infinity} );
|
||||
is(e.value, -Infinity, "value should be negative infinity");
|
||||
e = new DeviceLightEvent("hello");
|
||||
is(e.value, Infinity, "Uninitialized value should be positive infinity");
|
||||
|
||||
// DeviceOrientationEvent
|
||||
e = new DeviceOrientationEvent("hello");
|
||||
|
@ -7,7 +7,7 @@
|
||||
[Constructor(DOMString type, optional DeviceLightEventInit eventInitDict)]
|
||||
interface DeviceLightEvent : Event
|
||||
{
|
||||
readonly attribute double value;
|
||||
readonly attribute unrestricted double value;
|
||||
};
|
||||
|
||||
dictionary DeviceLightEventInit : EventInit
|
||||
|
@ -586,6 +586,8 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
WriteParam(aMsg, aParam.mIsRoot);
|
||||
WriteParam(aMsg, aParam.mHasScrollgrab);
|
||||
WriteParam(aMsg, aParam.mUpdateScrollOffset);
|
||||
WriteParam(aMsg, aParam.mDisableScrollingX);
|
||||
WriteParam(aMsg, aParam.mDisableScrollingY);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
@ -605,7 +607,9 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mIsRoot) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasScrollgrab) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset));
|
||||
ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDisableScrollingX) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDisableScrollingY));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -12,6 +12,10 @@
|
||||
#include "mozilla/gfx/Rect.h" // for RoundedIn
|
||||
#include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor
|
||||
|
||||
namespace IPC {
|
||||
template <typename T> struct ParamTraits;
|
||||
} // namespace IPC
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
@ -32,6 +36,7 @@ typedef gfx::ScaleFactor<ParentLayerPixel, ScreenPixel> ParentLayerToScreenScale
|
||||
* atomically with new pixels.
|
||||
*/
|
||||
struct FrameMetrics {
|
||||
friend struct IPC::ParamTraits<mozilla::layers::FrameMetrics>;
|
||||
public:
|
||||
// We use IDs to identify frames across processes.
|
||||
typedef uint64_t ViewID;
|
||||
@ -51,11 +56,13 @@ public:
|
||||
, mCumulativeResolution(1)
|
||||
, mZoom(1)
|
||||
, mDevPixelsPerCSSPixel(1)
|
||||
, mMayHaveTouchListeners(false)
|
||||
, mPresShellId(-1)
|
||||
, mMayHaveTouchListeners(false)
|
||||
, mIsRoot(false)
|
||||
, mHasScrollgrab(false)
|
||||
, mUpdateScrollOffset(false)
|
||||
, mDisableScrollingX(false)
|
||||
, mDisableScrollingY(false)
|
||||
{}
|
||||
|
||||
// Default copy ctor and operator= are fine
|
||||
@ -75,6 +82,9 @@ public:
|
||||
mMayHaveTouchListeners == aOther.mMayHaveTouchListeners &&
|
||||
mPresShellId == aOther.mPresShellId &&
|
||||
mIsRoot == aOther.mIsRoot &&
|
||||
mHasScrollgrab == aOther.mHasScrollgrab &&
|
||||
mDisableScrollingX == aOther.mDisableScrollingX &&
|
||||
mDisableScrollingY == aOther.mDisableScrollingY &&
|
||||
mUpdateScrollOffset == aOther.mUpdateScrollOffset;
|
||||
}
|
||||
bool operator!=(const FrameMetrics& aOther) const
|
||||
@ -277,11 +287,11 @@ public:
|
||||
// resolution.
|
||||
CSSToLayoutDeviceScale mDevPixelsPerCSSPixel;
|
||||
|
||||
uint32_t mPresShellId;
|
||||
|
||||
// Whether or not this frame may have touch listeners.
|
||||
bool mMayHaveTouchListeners;
|
||||
|
||||
uint32_t mPresShellId;
|
||||
|
||||
// Whether or not this is the root scroll frame for the root content document.
|
||||
bool mIsRoot;
|
||||
|
||||
@ -291,6 +301,36 @@ public:
|
||||
// Whether mScrollOffset was updated by something other than the APZ code, and
|
||||
// if the APZC receiving this metrics should update its local copy.
|
||||
bool mUpdateScrollOffset;
|
||||
|
||||
public:
|
||||
bool GetDisableScrollingX() const
|
||||
{
|
||||
return mDisableScrollingX;
|
||||
}
|
||||
|
||||
void SetDisableScrollingX(bool aDisableScrollingX)
|
||||
{
|
||||
mDisableScrollingX = aDisableScrollingX;
|
||||
}
|
||||
|
||||
bool GetDisableScrollingY() const
|
||||
{
|
||||
return mDisableScrollingY;
|
||||
}
|
||||
|
||||
void SetDisableScrollingY(bool aDisableScrollingY)
|
||||
{
|
||||
mDisableScrollingY = aDisableScrollingY;
|
||||
}
|
||||
|
||||
private:
|
||||
// New fields from now on should be made private and old fields should
|
||||
// be refactored to be private.
|
||||
|
||||
// Allow disabling scrolling in individual axis to support
|
||||
// |overflow: hidden|.
|
||||
bool mDisableScrollingX;
|
||||
bool mDisableScrollingY;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -169,12 +169,12 @@ TextureClient::InitIPDLActor(CompositableForwarder* aForwarder)
|
||||
return false;
|
||||
}
|
||||
|
||||
mActor = static_cast<TextureChild*>(aForwarder->CreateEmptyTextureChild());
|
||||
mActor = static_cast<TextureChild*>(aForwarder->CreateTexture(desc, GetFlags()));
|
||||
MOZ_ASSERT(mActor);
|
||||
mActor->mForwarder = aForwarder;
|
||||
mActor->mTextureClient = this;
|
||||
mShared = true;
|
||||
return mActor->IPCOpen() &&
|
||||
mActor->SendInit(desc, GetFlags());
|
||||
return mActor->IPCOpen();
|
||||
}
|
||||
|
||||
PTextureChild*
|
||||
|
@ -36,8 +36,8 @@ public:
|
||||
|
||||
~TextureParent();
|
||||
|
||||
bool RecvInit(const SurfaceDescriptor& aSharedData,
|
||||
const TextureFlags& aFlags) MOZ_OVERRIDE;
|
||||
bool Init(const SurfaceDescriptor& aSharedData,
|
||||
const TextureFlags& aFlags);
|
||||
|
||||
virtual bool RecvRemoveTexture() MOZ_OVERRIDE;
|
||||
|
||||
@ -53,9 +53,14 @@ public:
|
||||
|
||||
// static
|
||||
PTextureParent*
|
||||
TextureHost::CreateIPDLActor(ISurfaceAllocator* aAllocator)
|
||||
TextureHost::CreateIPDLActor(ISurfaceAllocator* aAllocator,
|
||||
const SurfaceDescriptor& aSharedData,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
return new TextureParent(aAllocator);
|
||||
TextureParent* actor = new TextureParent(aAllocator);
|
||||
DebugOnly<bool> status = actor->Init(aSharedData, aFlags);
|
||||
MOZ_ASSERT(status);
|
||||
return actor;
|
||||
}
|
||||
|
||||
// static
|
||||
@ -679,8 +684,8 @@ TextureParent::~TextureParent()
|
||||
}
|
||||
|
||||
bool
|
||||
TextureParent::RecvInit(const SurfaceDescriptor& aSharedData,
|
||||
const TextureFlags& aFlags)
|
||||
TextureParent::Init(const SurfaceDescriptor& aSharedData,
|
||||
const TextureFlags& aFlags)
|
||||
{
|
||||
mTextureHost = TextureHost::Create(aSharedData,
|
||||
mAllocator,
|
||||
|
@ -379,7 +379,9 @@ public:
|
||||
* are for use with the managing IPDL protocols only (so that they can
|
||||
* implement AllocPTextureParent and DeallocPTextureParent).
|
||||
*/
|
||||
static PTextureParent* CreateIPDLActor(ISurfaceAllocator* aAllocator);
|
||||
static PTextureParent* CreateIPDLActor(ISurfaceAllocator* aAllocator,
|
||||
const SurfaceDescriptor& aSharedData,
|
||||
TextureFlags aFlags);
|
||||
static bool DestroyIPDLActor(PTextureParent* actor);
|
||||
|
||||
/**
|
||||
|
@ -763,7 +763,7 @@ nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEve
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
if (!mZoomConstraints.mAllowZoom) {
|
||||
if (!AllowZoom()) {
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
@ -930,7 +930,7 @@ nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEven
|
||||
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||
// If mZoomConstraints.mAllowZoom is true we wait for a call to OnSingleTapConfirmed before
|
||||
// sending event to content
|
||||
if (controller && !mZoomConstraints.mAllowZoom) {
|
||||
if (controller && !AllowZoom()) {
|
||||
int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
|
||||
CSSIntPoint geckoScreenPoint;
|
||||
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
|
||||
@ -959,7 +959,7 @@ nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent)
|
||||
APZC_LOG("%p got a double-tap in state %d\n", this, mState);
|
||||
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||
if (controller) {
|
||||
if (mZoomConstraints.mAllowZoom) {
|
||||
if (AllowZoom()) {
|
||||
int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
|
||||
CSSIntPoint geckoScreenPoint;
|
||||
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
|
||||
@ -997,10 +997,10 @@ void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle, TouchBe
|
||||
if ((aBehavior & AllowedTouchBehavior::VERTICAL_PAN) && (aBehavior & AllowedTouchBehavior::HORIZONTAL_PAN)) {
|
||||
if (mX.Scrollable() && mY.Scrollable()) {
|
||||
if (IsCloseToHorizontal(aAngle, AXIS_LOCK_ANGLE)) {
|
||||
mY.SetScrollingDisabled(true);
|
||||
mY.SetAxisLocked(true);
|
||||
SetState(PANNING_LOCKED_X);
|
||||
} else if (IsCloseToVertical(aAngle, AXIS_LOCK_ANGLE)) {
|
||||
mX.SetScrollingDisabled(true);
|
||||
mX.SetAxisLocked(true);
|
||||
SetState(PANNING_LOCKED_Y);
|
||||
} else {
|
||||
SetState(PANNING);
|
||||
@ -1014,7 +1014,7 @@ void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle, TouchBe
|
||||
// Using bigger angle for panning to keep behavior consistent
|
||||
// with IE.
|
||||
if (IsCloseToHorizontal(aAngle, ALLOWED_DIRECT_PAN_ANGLE)) {
|
||||
mY.SetScrollingDisabled(true);
|
||||
mY.SetAxisLocked(true);
|
||||
SetState(PANNING_LOCKED_X);
|
||||
mPanDirRestricted = true;
|
||||
} else {
|
||||
@ -1024,7 +1024,7 @@ void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle, TouchBe
|
||||
}
|
||||
} else if (aBehavior & AllowedTouchBehavior::VERTICAL_PAN) {
|
||||
if (IsCloseToVertical(aAngle, ALLOWED_DIRECT_PAN_ANGLE)) {
|
||||
mX.SetScrollingDisabled(true);
|
||||
mX.SetAxisLocked(true);
|
||||
SetState(PANNING_LOCKED_Y);
|
||||
mPanDirRestricted = true;
|
||||
} else {
|
||||
@ -1039,20 +1039,20 @@ void AsyncPanZoomController::HandlePanning(double aAngle) {
|
||||
if (!gCrossSlideEnabled && (!mX.Scrollable() || !mY.Scrollable())) {
|
||||
SetState(PANNING);
|
||||
} else if (IsCloseToHorizontal(aAngle, AXIS_LOCK_ANGLE)) {
|
||||
mY.SetScrollingDisabled(true);
|
||||
mY.SetAxisLocked(true);
|
||||
if (mX.Scrollable()) {
|
||||
SetState(PANNING_LOCKED_X);
|
||||
} else {
|
||||
SetState(CROSS_SLIDING_X);
|
||||
mX.SetScrollingDisabled(true);
|
||||
mX.SetAxisLocked(true);
|
||||
}
|
||||
} else if (IsCloseToVertical(aAngle, AXIS_LOCK_ANGLE)) {
|
||||
mX.SetScrollingDisabled(true);
|
||||
mX.SetAxisLocked(true);
|
||||
if (mY.Scrollable()) {
|
||||
SetState(PANNING_LOCKED_Y);
|
||||
} else {
|
||||
SetState(CROSS_SLIDING_Y);
|
||||
mY.SetScrollingDisabled(true);
|
||||
mY.SetAxisLocked(true);
|
||||
}
|
||||
} else {
|
||||
SetState(PANNING);
|
||||
@ -1107,6 +1107,7 @@ void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput&
|
||||
void AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
||||
const ScreenPoint& aEndPoint,
|
||||
uint32_t aOverscrollHandoffChainIndex) {
|
||||
|
||||
// "start - end" rather than "end - start" because e.g. moving your finger
|
||||
// down (*positive* direction along y axis) causes the vertical scroll offset
|
||||
// to *decrease* as the page follows your finger.
|
||||
@ -1123,8 +1124,12 @@ void AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
||||
CSSPoint cssDisplacement = displacement / zoom;
|
||||
|
||||
CSSPoint cssOverscroll;
|
||||
gfx::Point scrollOffset(mX.AdjustDisplacement(cssDisplacement.x, cssOverscroll.x),
|
||||
mY.AdjustDisplacement(cssDisplacement.y, cssOverscroll.y));
|
||||
gfx::Point scrollOffset(mX.AdjustDisplacement(cssDisplacement.x,
|
||||
cssOverscroll.x,
|
||||
mFrameMetrics.GetDisableScrollingX()),
|
||||
mY.AdjustDisplacement(cssDisplacement.y,
|
||||
cssOverscroll.y,
|
||||
mFrameMetrics.GetDisableScrollingY()));
|
||||
overscroll = cssOverscroll * zoom;
|
||||
|
||||
if (fabs(scrollOffset.x) > EPSILON || fabs(scrollOffset.y) > EPSILON) {
|
||||
@ -1182,12 +1187,12 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
|
||||
if (fabs(dx) > breakThreshold || fabs(dy) > breakThreshold) {
|
||||
if (mState == PANNING_LOCKED_X || mState == CROSS_SLIDING_X) {
|
||||
if (!IsCloseToHorizontal(angle, AXIS_BREAKOUT_ANGLE)) {
|
||||
mY.SetScrollingDisabled(false);
|
||||
mY.SetAxisLocked(false);
|
||||
SetState(PANNING);
|
||||
}
|
||||
} else if (mState == PANNING_LOCKED_Y || mState == CROSS_SLIDING_Y) {
|
||||
if (!IsCloseToVertical(angle, AXIS_BREAKOUT_ANGLE)) {
|
||||
mX.SetScrollingDisabled(false);
|
||||
mX.SetAxisLocked(false);
|
||||
SetState(PANNING);
|
||||
}
|
||||
}
|
||||
@ -1220,8 +1225,10 @@ bool FlingAnimation::Sample(FrameMetrics& aFrameMetrics,
|
||||
// a larger swipe should move you a shorter distance).
|
||||
CSSPoint cssOffset = offset / aFrameMetrics.mZoom;
|
||||
aFrameMetrics.mScrollOffset += CSSPoint::FromUnknownPoint(gfx::Point(
|
||||
mX.AdjustDisplacement(cssOffset.x, overscroll.x),
|
||||
mY.AdjustDisplacement(cssOffset.y, overscroll.y)
|
||||
mX.AdjustDisplacement(cssOffset.x, overscroll.x,
|
||||
aFrameMetrics.GetDisableScrollingX()),
|
||||
mY.AdjustDisplacement(cssOffset.y, overscroll.y,
|
||||
aFrameMetrics.GetDisableScrollingX())
|
||||
));
|
||||
|
||||
return true;
|
||||
@ -1571,6 +1578,8 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
|
||||
mFrameMetrics.mResolution = aLayerMetrics.mResolution;
|
||||
mFrameMetrics.mCumulativeResolution = aLayerMetrics.mCumulativeResolution;
|
||||
mFrameMetrics.mHasScrollgrab = aLayerMetrics.mHasScrollgrab;
|
||||
mFrameMetrics.SetDisableScrollingX(aLayerMetrics.GetDisableScrollingX());
|
||||
mFrameMetrics.SetDisableScrollingY(aLayerMetrics.GetDisableScrollingY());
|
||||
|
||||
// If the layers update was not triggered by our own repaint request, then
|
||||
// we want to take the new scroll offset.
|
||||
@ -1812,6 +1821,14 @@ bool AsyncPanZoomController::IsPanningState(PanZoomState aState) {
|
||||
return (aState == PANNING || aState == PANNING_LOCKED_X || aState == PANNING_LOCKED_Y);
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::AllowZoom() {
|
||||
// In addition to looking at the zoom constraints, which comes from the meta
|
||||
// viewport tag, disallow zooming if we are overflow:hidden in either direction.
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
return mZoomConstraints.mAllowZoom
|
||||
&& !(mFrameMetrics.GetDisableScrollingX() || mFrameMetrics.GetDisableScrollingY());
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::TimeoutContentResponse() {
|
||||
mContentResponseTimeoutTask = nullptr;
|
||||
ContentReceivedTouch(false);
|
||||
|
@ -580,6 +580,8 @@ private:
|
||||
bool IsTransformingState(PanZoomState aState);
|
||||
bool IsPanningState(PanZoomState mState);
|
||||
|
||||
bool AllowZoom();
|
||||
|
||||
enum AxisLockMode {
|
||||
FREE, /* No locking at all */
|
||||
STANDARD, /* Default axis locking mode that remains locked until pan ends*/
|
||||
|
@ -101,14 +101,14 @@ Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
|
||||
: mPos(0),
|
||||
mVelocity(0.0f),
|
||||
mAcceleration(0),
|
||||
mScrollingDisabled(false),
|
||||
mAxisLocked(false),
|
||||
mAsyncPanZoomController(aAsyncPanZoomController)
|
||||
{
|
||||
InitAxisPrefs();
|
||||
}
|
||||
|
||||
void Axis::UpdateWithTouchAtDevicePoint(int32_t aPos, const TimeDuration& aTimeDelta) {
|
||||
float newVelocity = mScrollingDisabled ? 0 : (mPos - aPos) / aTimeDelta.ToMilliseconds();
|
||||
float newVelocity = mAxisLocked ? 0 : (mPos - aPos) / aTimeDelta.ToMilliseconds();
|
||||
|
||||
bool curVelocityBelowThreshold = fabsf(newVelocity) < gVelocityThreshold;
|
||||
bool directionChange = (mVelocity > 0) != (newVelocity > 0);
|
||||
@ -132,15 +132,23 @@ void Axis::UpdateWithTouchAtDevicePoint(int32_t aPos, const TimeDuration& aTimeD
|
||||
void Axis::StartTouch(int32_t aPos) {
|
||||
mStartPos = aPos;
|
||||
mPos = aPos;
|
||||
mScrollingDisabled = false;
|
||||
mAxisLocked = false;
|
||||
}
|
||||
|
||||
float Axis::AdjustDisplacement(float aDisplacement, float& aOverscrollAmountOut) {
|
||||
if (mScrollingDisabled) {
|
||||
float Axis::AdjustDisplacement(float aDisplacement, float& aOverscrollAmountOut,
|
||||
bool aScrollingDisabled) {
|
||||
if (mAxisLocked) {
|
||||
aOverscrollAmountOut = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (aScrollingDisabled) {
|
||||
// Scrolling is disabled on this axis, stop scrolling.
|
||||
aOverscrollAmountOut = aDisplacement;
|
||||
mAcceleration = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fabsf(mVelocity) < gVelocityThreshold) {
|
||||
mAcceleration = 0;
|
||||
}
|
||||
@ -192,7 +200,7 @@ void Axis::CancelTouch() {
|
||||
}
|
||||
|
||||
bool Axis::Scrollable() {
|
||||
if (mScrollingDisabled) {
|
||||
if (mAxisLocked) {
|
||||
return false;
|
||||
}
|
||||
return GetCompositionLength() < GetPageLength();
|
||||
@ -291,7 +299,7 @@ float Axis::ScaleWillOverscrollAmount(float aScale, float aFocus) {
|
||||
}
|
||||
|
||||
float Axis::GetVelocity() {
|
||||
return mScrollingDisabled ? 0 : mVelocity;
|
||||
return mAxisLocked ? 0 : mVelocity;
|
||||
}
|
||||
|
||||
float Axis::GetAccelerationFactor() {
|
||||
|
@ -77,8 +77,12 @@ public:
|
||||
* prevent any displacement from happening). If overscroll ocurred, its amount
|
||||
* is written to |aOverscrollAmountOut|.
|
||||
* The adjusted displacement is returned.
|
||||
*
|
||||
* aScrollingDisabled is used to indicate that no scrolling should happen
|
||||
* in this axis. This is used to implement overflow: hidden;
|
||||
*/
|
||||
float AdjustDisplacement(float aDisplacement, float& aOverscrollAmountOut);
|
||||
float AdjustDisplacement(float aDisplacement, float& aOverscrollAmountOut,
|
||||
bool aScrollingDisabled);
|
||||
|
||||
/**
|
||||
* Gets the distance between the starting position of the touch supplied in
|
||||
@ -107,7 +111,7 @@ public:
|
||||
*/
|
||||
bool Scrollable();
|
||||
|
||||
void SetScrollingDisabled(bool aDisabled) { mScrollingDisabled = aDisabled; }
|
||||
void SetAxisLocked(bool aAxisLocked) { mAxisLocked = aAxisLocked; }
|
||||
|
||||
/**
|
||||
* Gets the overscroll state of the axis in its current position.
|
||||
@ -190,7 +194,7 @@ protected:
|
||||
// they are flinging multiple times in a row very quickly, probably trying to
|
||||
// reach one of the extremes of the page.
|
||||
int32_t mAcceleration;
|
||||
bool mScrollingDisabled; // Whether movement on this axis is locked.
|
||||
bool mAxisLocked; // Whether movement on this axis is locked.
|
||||
AsyncPanZoomController* mAsyncPanZoomController;
|
||||
nsTArray<float> mVelocityQueue;
|
||||
};
|
||||
|
@ -96,12 +96,9 @@ public:
|
||||
const SurfaceDescriptorTiles& aTiledDescriptor) = 0;
|
||||
|
||||
/**
|
||||
* Create an unitialized TextureChild.
|
||||
*
|
||||
* This does not trigger the the creation of a TextureHost on the compositor
|
||||
* side (see PTexture::Init).
|
||||
* Create a TextureChild/Parent pair as as well as the TextureHost on the parent side.
|
||||
*/
|
||||
virtual PTextureChild* CreateEmptyTextureChild() = 0;
|
||||
virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData, TextureFlags aFlags) = 0;
|
||||
|
||||
/**
|
||||
* Communicate to the compositor that the texture identified by aCompositable
|
||||
|
@ -897,7 +897,8 @@ ImageBridgeChild::AllocGrallocBuffer(const IntSize& aSize,
|
||||
}
|
||||
|
||||
PTextureChild*
|
||||
ImageBridgeChild::AllocPTextureChild()
|
||||
ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
|
||||
const TextureFlags&)
|
||||
{
|
||||
return TextureClient::CreateIPDLActor();
|
||||
}
|
||||
@ -909,9 +910,10 @@ ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
|
||||
}
|
||||
|
||||
PTextureChild*
|
||||
ImageBridgeChild::CreateEmptyTextureChild()
|
||||
ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
return SendPTextureConstructor();
|
||||
return SendPTextureConstructor(aSharedData, aFlags);
|
||||
}
|
||||
|
||||
static void RemoveTextureSync(TextureClient* aTexture, ReentrantMonitor* aBarrier, bool* aDone)
|
||||
|
@ -195,7 +195,7 @@ public:
|
||||
DeallocPGrallocBufferChild(PGrallocBufferChild* actor) MOZ_OVERRIDE;
|
||||
|
||||
virtual PTextureChild*
|
||||
AllocPTextureChild() MOZ_OVERRIDE;
|
||||
AllocPTextureChild(const SurfaceDescriptor& aSharedData, const TextureFlags& aFlags) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
|
||||
@ -372,7 +372,8 @@ public:
|
||||
*/
|
||||
virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem);
|
||||
|
||||
virtual PTextureChild* CreateEmptyTextureChild() MOZ_OVERRIDE;
|
||||
virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
|
||||
TextureFlags aFlags) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
ImageBridgeChild();
|
||||
|
@ -191,9 +191,10 @@ bool ImageBridgeParent::DeallocPCompositableParent(PCompositableParent* aActor)
|
||||
}
|
||||
|
||||
PTextureParent*
|
||||
ImageBridgeParent::AllocPTextureParent()
|
||||
ImageBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
|
||||
const TextureFlags& aFlags)
|
||||
{
|
||||
return TextureHost::CreateIPDLActor(this);
|
||||
return TextureHost::CreateIPDLActor(this, aSharedData, aFlags);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -64,7 +64,8 @@ public:
|
||||
uint64_t*) MOZ_OVERRIDE;
|
||||
bool DeallocPCompositableParent(PCompositableParent* aActor) MOZ_OVERRIDE;
|
||||
|
||||
virtual PTextureParent* AllocPTextureParent() MOZ_OVERRIDE;
|
||||
virtual PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
|
||||
const TextureFlags& aFlags) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPTextureParent(PTextureParent* actor) MOZ_OVERRIDE;
|
||||
|
||||
bool RecvStop() MOZ_OVERRIDE;
|
||||
|
@ -98,7 +98,8 @@ LayerTransactionChild::ActorDestroy(ActorDestroyReason why)
|
||||
}
|
||||
|
||||
PTextureChild*
|
||||
LayerTransactionChild::AllocPTextureChild()
|
||||
LayerTransactionChild::AllocPTextureChild(const SurfaceDescriptor&,
|
||||
const TextureFlags&)
|
||||
{
|
||||
return TextureClient::CreateIPDLActor();
|
||||
}
|
||||
|
@ -58,7 +58,8 @@ protected:
|
||||
virtual PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPCompositableChild(PCompositableChild* actor) MOZ_OVERRIDE;
|
||||
|
||||
virtual PTextureChild* AllocPTextureChild() MOZ_OVERRIDE;
|
||||
virtual PTextureChild* AllocPTextureChild(const SurfaceDescriptor& aSharedData,
|
||||
const TextureFlags& aFlags) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
|
||||
|
@ -603,9 +603,10 @@ LayerTransactionParent::DeallocPCompositableParent(PCompositableParent* actor)
|
||||
}
|
||||
|
||||
PTextureParent*
|
||||
LayerTransactionParent::AllocPTextureParent()
|
||||
LayerTransactionParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
|
||||
const TextureFlags& aFlags)
|
||||
{
|
||||
return TextureHost::CreateIPDLActor(this);
|
||||
return TextureHost::CreateIPDLActor(this, aSharedData, aFlags);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -107,7 +107,8 @@ protected:
|
||||
virtual PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPCompositableParent(PCompositableParent* actor) MOZ_OVERRIDE;
|
||||
|
||||
virtual PTextureParent* AllocPTextureParent() MOZ_OVERRIDE;
|
||||
virtual PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
|
||||
const TextureFlags& aFlags) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPTextureParent(PTextureParent* actor) MOZ_OVERRIDE;
|
||||
|
||||
void Attach(ShadowLayerParent* aLayerParent,
|
||||
|
@ -51,7 +51,7 @@ parent:
|
||||
sync Stop();
|
||||
|
||||
sync PCompositable(TextureInfo aInfo) returns (uint64_t id);
|
||||
async PTexture();
|
||||
async PTexture(SurfaceDescriptor aSharedData, uint32_t aTextureFlags);
|
||||
};
|
||||
|
||||
|
||||
|
@ -68,7 +68,7 @@ parent:
|
||||
returns (MaybeMagicGrallocBufferHandle handle);
|
||||
async PLayer();
|
||||
async PCompositable(TextureInfo aTextureInfo);
|
||||
async PTexture();
|
||||
async PTexture(SurfaceDescriptor aSharedData, uint32_t aTextureFlags);
|
||||
|
||||
// The isFirstPaint flag can be used to indicate that this is the first update
|
||||
// for a particular document.
|
||||
|
@ -26,10 +26,6 @@ child:
|
||||
async __delete__();
|
||||
|
||||
parent:
|
||||
/**
|
||||
* Set the shared data and create the TextureHost on the parent side.
|
||||
*/
|
||||
async Init(SurfaceDescriptor aSharedData, uint32_t aTextureFlags);
|
||||
|
||||
/**
|
||||
* Asynchronously tell the Compositor side to remove the texture.
|
||||
|
@ -963,9 +963,10 @@ void ShadowLayerForwarder::AttachAsyncCompositable(uint64_t aCompositableID,
|
||||
}
|
||||
|
||||
PTextureChild*
|
||||
ShadowLayerForwarder::CreateEmptyTextureChild()
|
||||
ShadowLayerForwarder::CreateTexture(const SurfaceDescriptor& aSharedData,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
return mShadowManager->SendPTextureConstructor();
|
||||
return mShadowManager->SendPTextureConstructor(aSharedData, aFlags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -148,7 +148,8 @@ public:
|
||||
*/
|
||||
void Connect(CompositableClient* aCompositable);
|
||||
|
||||
virtual PTextureChild* CreateEmptyTextureChild() MOZ_OVERRIDE;
|
||||
virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
|
||||
TextureFlags aFlags) MOZ_OVERRIDE;
|
||||
|
||||
virtual void CreatedSingleBuffer(CompositableClient* aCompositable,
|
||||
const SurfaceDescriptor& aDescriptor,
|
||||
|
@ -1023,7 +1023,7 @@ gfxPlatform::CreateOffscreenContentDrawTarget(const IntSize& aSize, SurfaceForma
|
||||
RefPtr<DrawTarget>
|
||||
gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat)
|
||||
{
|
||||
NS_ASSERTION(mPreferredCanvasBackend != BackendType::NONE, "No backend.");
|
||||
NS_ASSERTION(mContentBackend != BackendType::NONE, "No backend.");
|
||||
if (mContentBackend == BackendType::CAIRO) {
|
||||
nsRefPtr<gfxImageSurface> image = new gfxImageSurface(aData, gfxIntSize(aSize.width, aSize.height), aStride, SurfaceFormatToImageFormat(aFormat));
|
||||
return Factory::CreateDrawTargetForCairoSurface(image->CairoSurface(), aSize);
|
||||
|
@ -1195,7 +1195,7 @@ RasterImage::ApplyDecodeFlags(uint32_t aNewFlags)
|
||||
// decode.
|
||||
if (!(aNewFlags & FLAG_SYNC_DECODE))
|
||||
return false;
|
||||
if (!CanForciblyDiscard() || mDecoder || mAnim)
|
||||
if (!CanForciblyDiscardAndRedecode())
|
||||
return false;
|
||||
ForceDiscard();
|
||||
}
|
||||
@ -1938,6 +1938,14 @@ RasterImage::CanForciblyDiscard() {
|
||||
mHasSourceData; // ...have the source data...
|
||||
}
|
||||
|
||||
bool
|
||||
RasterImage::CanForciblyDiscardAndRedecode() {
|
||||
return mDiscardable && // ...Enabled at creation time...
|
||||
mHasSourceData && // ...have the source data...
|
||||
!mDecoder && // Can't discard with an open decoder
|
||||
!mAnim; // Can never discard animated images
|
||||
}
|
||||
|
||||
// Helper method to tell us whether the clock is currently running for
|
||||
// discarding this image. Mainly for assertions.
|
||||
bool
|
||||
@ -2374,6 +2382,15 @@ RasterImage::SyncDecode()
|
||||
if (mDecoder && mDecoder->GetDecodeFlags() != mFrameDecodeFlags) {
|
||||
nsresult rv = FinishedSomeDecoding(eShutdownIntent_NotNeeded);
|
||||
CONTAINER_ENSURE_SUCCESS(rv);
|
||||
|
||||
if (mDecoded) {
|
||||
// If we've finished decoding we need to discard so we can re-decode
|
||||
// with the new flags. If we can't discard then there isn't
|
||||
// anything we can do.
|
||||
if (!CanForciblyDiscardAndRedecode())
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
ForceDiscard();
|
||||
}
|
||||
}
|
||||
|
||||
// If we're currently waiting on a new frame for this image, we have to create
|
||||
@ -2602,7 +2619,7 @@ RasterImage::Draw(gfxContext *aContext,
|
||||
|
||||
// We can only draw with the default decode flags
|
||||
if (mFrameDecodeFlags != DECODE_FLAGS_DEFAULT) {
|
||||
if (!CanForciblyDiscard() || mDecoder || mAnim)
|
||||
if (!CanForciblyDiscardAndRedecode())
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
ForceDiscard();
|
||||
|
||||
@ -2725,7 +2742,7 @@ RasterImage::UnlockImage()
|
||||
NS_IMETHODIMP
|
||||
RasterImage::RequestDiscard()
|
||||
{
|
||||
if (CanDiscard() && !mDecoder && !mAnim) {
|
||||
if (CanDiscard() && CanForciblyDiscardAndRedecode()) {
|
||||
ForceDiscard();
|
||||
}
|
||||
|
||||
|
@ -762,6 +762,7 @@ private: // data
|
||||
// Helpers
|
||||
bool CanDiscard();
|
||||
bool CanForciblyDiscard();
|
||||
bool CanForciblyDiscardAndRedecode();
|
||||
bool DiscardingActive();
|
||||
bool StoringSourceData() const;
|
||||
|
||||
|
@ -77,7 +77,7 @@ class ScriptAnalysis
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool analyzeBytecode(JSContext *cx);
|
||||
|
||||
/*
|
||||
@ -89,9 +89,9 @@ class ScriptAnalysis
|
||||
bool isReachable(const jsbytecode *pc) { return maybeCode(pc); }
|
||||
|
||||
private:
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool analyzeSSA(JSContext *cx);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool analyzeLifetimes(JSContext *cx);
|
||||
|
||||
/* Accessors for bytecode information. */
|
||||
@ -154,49 +154,49 @@ class ScriptAnalysis
|
||||
void printTypes(JSContext *cx);
|
||||
|
||||
/* Bytecode helpers */
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline bool addJump(JSContext *cx, unsigned offset,
|
||||
unsigned *currentOffset, unsigned *forwardJump, unsigned *forwardLoop,
|
||||
unsigned stackDepth);
|
||||
|
||||
/* Lifetime helpers */
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline bool addVariable(JSContext *cx, LifetimeVariable &var, unsigned offset,
|
||||
LifetimeVariable **&saved, unsigned &savedCount);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline bool killVariable(JSContext *cx, LifetimeVariable &var, unsigned offset,
|
||||
LifetimeVariable **&saved, unsigned &savedCount);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline bool extendVariable(JSContext *cx, LifetimeVariable &var, unsigned start, unsigned end);
|
||||
|
||||
inline void ensureVariable(LifetimeVariable &var, unsigned until);
|
||||
|
||||
/* SSA helpers */
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool makePhi(JSContext *cx, uint32_t slot, uint32_t offset, SSAValue *pv);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool insertPhi(JSContext *cx, SSAValue &phi, const SSAValue &v);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool mergeValue(JSContext *cx, uint32_t offset, const SSAValue &v, SlotValue *pv);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool checkPendingValue(JSContext *cx, const SSAValue &v, uint32_t slot,
|
||||
Vector<SlotValue> *pending);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool checkBranchTarget(JSContext *cx, uint32_t targetOffset, Vector<uint32_t> &branchTargets,
|
||||
SSAValueInfo *values, uint32_t stackDepth);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool checkExceptionTarget(JSContext *cx, uint32_t catchOffset,
|
||||
Vector<uint32_t> &exceptionTargets);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool mergeBranchTarget(JSContext *cx, SSAValueInfo &value, uint32_t slot,
|
||||
const Vector<uint32_t> &branchTargets, uint32_t currentOffset);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool mergeExceptionTarget(JSContext *cx, const SSAValue &value, uint32_t slot,
|
||||
const Vector<uint32_t> &exceptionTargets);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool mergeAllExceptionTargets(JSContext *cx, SSAValueInfo *values,
|
||||
const Vector<uint32_t> &exceptionTargets);
|
||||
JS_WARN_UNUSED_RESULT
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool freezeNewValues(JSContext *cx, uint32_t offset);
|
||||
|
||||
typedef Vector<SSAValue, 16> SeenVector;
|
||||
|
@ -4442,8 +4442,26 @@ JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optio
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options)
|
||||
JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length)
|
||||
{
|
||||
static const unsigned TINY_LENGTH = 1000;
|
||||
static const unsigned HUGE_LENGTH = 100*1000;
|
||||
|
||||
// These are heuristics which the caller may choose to ignore (e.g., for
|
||||
// testing purposes).
|
||||
if (!options.forceAsync) {
|
||||
// Compiling off the main thread inolves creating a new Zone and other
|
||||
// significant overheads. Don't bother if the script is tiny.
|
||||
if (length < TINY_LENGTH)
|
||||
return false;
|
||||
|
||||
// If the parsing task would have to wait for GC to complete, it'll probably
|
||||
// be faster to just start it synchronously on the main thread unless the
|
||||
// script is huge.
|
||||
if (OffThreadParsingMustWaitForGC(cx->runtime()) && length < HUGE_LENGTH)
|
||||
return false;
|
||||
}
|
||||
|
||||
return cx->runtime()->canUseParallelParsing();
|
||||
}
|
||||
|
||||
@ -4452,7 +4470,7 @@ JS::CompileOffThread(JSContext *cx, Handle<JSObject*> obj, const ReadOnlyCompile
|
||||
const jschar *chars, size_t length,
|
||||
OffThreadCompileCallback callback, void *callbackData)
|
||||
{
|
||||
JS_ASSERT(CanCompileOffThread(cx, options));
|
||||
JS_ASSERT(CanCompileOffThread(cx, options, length));
|
||||
return StartOffThreadParseScript(cx, options, chars, length, obj, callback, callbackData);
|
||||
}
|
||||
|
||||
|
@ -3466,6 +3466,7 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
||||
extraWarningsOption(false),
|
||||
werrorOption(false),
|
||||
asmJSOption(false),
|
||||
forceAsync(false),
|
||||
sourcePolicy(SAVE_SOURCE)
|
||||
{ }
|
||||
|
||||
@ -3498,6 +3499,7 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
||||
bool extraWarningsOption;
|
||||
bool werrorOption;
|
||||
bool asmJSOption;
|
||||
bool forceAsync;
|
||||
enum SourcePolicy {
|
||||
NO_SOURCE,
|
||||
LAZY_SOURCE,
|
||||
@ -3647,7 +3649,7 @@ extern JS_PUBLIC_API(JSScript *)
|
||||
Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, const char *filename);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options);
|
||||
CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length);
|
||||
|
||||
/*
|
||||
* Off thread compilation control flow.
|
||||
|
@ -126,70 +126,68 @@ Shape::removeChild(Shape *child)
|
||||
}
|
||||
|
||||
Shape *
|
||||
PropertyTree::getChild(ExclusiveContext *cx, Shape *parent_, const StackShape &child)
|
||||
PropertyTree::getChild(ExclusiveContext *cx, Shape *parentArg, const StackShape &child)
|
||||
{
|
||||
{
|
||||
Shape *shape = nullptr;
|
||||
RootedShape parent(cx, parentArg);
|
||||
JS_ASSERT(parent);
|
||||
|
||||
JS_ASSERT(parent_);
|
||||
Shape *existingShape = nullptr;
|
||||
|
||||
/*
|
||||
* The property tree has extremely low fan-out below its root in
|
||||
* popular embeddings with real-world workloads. Patterns such as
|
||||
* defining closures that capture a constructor's environment as
|
||||
* getters or setters on the new object that is passed in as
|
||||
* |this| can significantly increase fan-out below the property
|
||||
* tree root -- see bug 335700 for details.
|
||||
*/
|
||||
KidsPointer *kidp = &parent_->kids;
|
||||
if (kidp->isShape()) {
|
||||
Shape *kid = kidp->toShape();
|
||||
if (kid->matches(child))
|
||||
shape = kid;
|
||||
} else if (kidp->isHash()) {
|
||||
if (KidsHash::Ptr p = kidp->toHash()->lookup(child))
|
||||
shape = *p;
|
||||
} else {
|
||||
/* If kidp->isNull(), we always insert. */
|
||||
}
|
||||
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (shape) {
|
||||
JS::Zone *zone = shape->zone();
|
||||
if (zone->needsBarrier()) {
|
||||
/*
|
||||
* We need a read barrier for the shape tree, since these are weak
|
||||
* pointers.
|
||||
*/
|
||||
Shape *tmp = shape;
|
||||
MarkShapeUnbarriered(zone->barrierTracer(), &tmp, "read barrier");
|
||||
JS_ASSERT(tmp == shape);
|
||||
} else if (zone->isGCSweeping() && !shape->isMarked() &&
|
||||
!shape->arenaHeader()->allocatedDuringIncremental)
|
||||
{
|
||||
/*
|
||||
* The shape we've found is unreachable and due to be finalized, so
|
||||
* remove our weak reference to it and don't use it.
|
||||
*/
|
||||
JS_ASSERT(parent_->isMarked());
|
||||
parent_->removeChild(shape);
|
||||
shape = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (shape)
|
||||
return shape;
|
||||
/*
|
||||
* The property tree has extremely low fan-out below its root in
|
||||
* popular embeddings with real-world workloads. Patterns such as
|
||||
* defining closures that capture a constructor's environment as
|
||||
* getters or setters on the new object that is passed in as
|
||||
* |this| can significantly increase fan-out below the property
|
||||
* tree root -- see bug 335700 for details.
|
||||
*/
|
||||
KidsPointer *kidp = &parent->kids;
|
||||
if (kidp->isShape()) {
|
||||
Shape *kid = kidp->toShape();
|
||||
if (kid->matches(child))
|
||||
existingShape = kid;
|
||||
} else if (kidp->isHash()) {
|
||||
if (KidsHash::Ptr p = kidp->toHash()->lookup(child))
|
||||
existingShape = *p;
|
||||
} else {
|
||||
/* If kidp->isNull(), we always insert. */
|
||||
}
|
||||
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (existingShape) {
|
||||
JS::Zone *zone = existingShape->zone();
|
||||
if (zone->needsBarrier()) {
|
||||
/*
|
||||
* We need a read barrier for the shape tree, since these are weak
|
||||
* pointers.
|
||||
*/
|
||||
Shape *tmp = existingShape;
|
||||
MarkShapeUnbarriered(zone->barrierTracer(), &tmp, "read barrier");
|
||||
JS_ASSERT(tmp == existingShape);
|
||||
} else if (zone->isGCSweeping() && !existingShape->isMarked() &&
|
||||
!existingShape->arenaHeader()->allocatedDuringIncremental)
|
||||
{
|
||||
/*
|
||||
* The shape we've found is unreachable and due to be finalized, so
|
||||
* remove our weak reference to it and don't use it.
|
||||
*/
|
||||
JS_ASSERT(parent->isMarked());
|
||||
parent->removeChild(existingShape);
|
||||
existingShape = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (existingShape)
|
||||
return existingShape;
|
||||
|
||||
StackShape::AutoRooter childRoot(cx, &child);
|
||||
RootedShape parent(cx, parent_);
|
||||
|
||||
Shape *shape = newShape(cx);
|
||||
if (!shape)
|
||||
return nullptr;
|
||||
|
||||
new (shape) Shape(child, child.numFixedSlots());
|
||||
new (shape) Shape(child, parent->numFixedSlots());
|
||||
|
||||
if (!insertChild(cx, parent, shape))
|
||||
return nullptr;
|
||||
|
@ -82,24 +82,35 @@ Bindings::initWithTemporaryStorage(ExclusiveContext *cx, InternalBindingsHandle
|
||||
self->numArgs_ = numArgs;
|
||||
self->numVars_ = numVars;
|
||||
|
||||
/*
|
||||
* Get the initial shape to use when creating CallObjects for this script.
|
||||
* Since unaliased variables are, by definition, only accessed by local
|
||||
* operations and never through the scope chain, only give shapes to
|
||||
* aliased variables. While the debugger may observe any scope object at
|
||||
* any time, such accesses are mediated by DebugScopeProxy (see
|
||||
* DebugScopeProxy::handleUnaliasedAccess).
|
||||
*/
|
||||
// Get the initial shape to use when creating CallObjects for this script.
|
||||
// After creation, a CallObject's shape may change completely (via direct eval() or
|
||||
// other operations that mutate the lexical scope). However, since the
|
||||
// lexical bindings added to the initial shape are permanent and the
|
||||
// allocKind/nfixed of a CallObject cannot change, one may assume that the
|
||||
// slot location (whether in the fixed or dynamic slots) of a variable is
|
||||
// the same as in the initial shape. (This is assumed by the interpreter and
|
||||
// JITs when interpreting/compiling aliasedvar ops.)
|
||||
|
||||
JS_STATIC_ASSERT(CallObject::RESERVED_SLOTS == 2);
|
||||
gc::AllocKind allocKind = gc::FINALIZE_OBJECT2_BACKGROUND;
|
||||
JS_ASSERT(gc::GetGCKindSlots(allocKind) == CallObject::RESERVED_SLOTS);
|
||||
RootedShape initial(cx,
|
||||
// Since unaliased variables are, by definition, only accessed by local
|
||||
// operations and never through the scope chain, only give shapes to
|
||||
// aliased variables. While the debugger may observe any scope object at
|
||||
// any time, such accesses are mediated by DebugScopeProxy (see
|
||||
// DebugScopeProxy::handleUnaliasedAccess).
|
||||
uint32_t nslots = CallObject::RESERVED_SLOTS;
|
||||
for (BindingIter bi(self); bi; bi++) {
|
||||
if (bi->aliased())
|
||||
nslots++;
|
||||
}
|
||||
|
||||
// Put as many of nslots inline into the object header as possible.
|
||||
uint32_t nfixed = gc::GetGCKindSlots(gc::GetGCObjectKind(nslots));
|
||||
|
||||
// Start with the empty shape and then append one shape per aliased binding.
|
||||
RootedShape shape(cx,
|
||||
EmptyShape::getInitialShape(cx, &CallObject::class_, nullptr, nullptr, nullptr,
|
||||
allocKind, BaseShape::VAROBJ | BaseShape::DELEGATE));
|
||||
if (!initial)
|
||||
nfixed, BaseShape::VAROBJ | BaseShape::DELEGATE));
|
||||
if (!shape)
|
||||
return false;
|
||||
self->callObjShape_.init(initial);
|
||||
|
||||
#ifdef DEBUG
|
||||
HashSet<PropertyName *> added(cx);
|
||||
@ -107,44 +118,41 @@ Bindings::initWithTemporaryStorage(ExclusiveContext *cx, InternalBindingsHandle
|
||||
return false;
|
||||
#endif
|
||||
|
||||
BindingIter bi(self);
|
||||
uint32_t slot = CallObject::RESERVED_SLOTS;
|
||||
for (uint32_t i = 0, n = self->count(); i < n; i++, bi++) {
|
||||
for (BindingIter bi(self); bi; bi++) {
|
||||
if (!bi->aliased())
|
||||
continue;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* The caller ensures no duplicate aliased names. */
|
||||
// The caller ensures no duplicate aliased names.
|
||||
JS_ASSERT(!added.has(bi->name()));
|
||||
if (!added.put(bi->name()))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
StackBaseShape base(cx, &CallObject::class_, cx->global(), nullptr,
|
||||
BaseShape::VAROBJ | BaseShape::DELEGATE);
|
||||
StackBaseShape stackBase(cx, &CallObject::class_, nullptr, nullptr,
|
||||
BaseShape::VAROBJ | BaseShape::DELEGATE);
|
||||
|
||||
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
|
||||
if (!nbase)
|
||||
UnownedBaseShape *base = BaseShape::getUnowned(cx, stackBase);
|
||||
if (!base)
|
||||
return false;
|
||||
|
||||
RootedId id(cx, NameToId(bi->name()));
|
||||
uint32_t nfixed = gc::GetGCKindSlots(gc::GetGCObjectKind(slot + 1));
|
||||
unsigned attrs = JSPROP_PERMANENT | JSPROP_ENUMERATE |
|
||||
unsigned attrs = JSPROP_PERMANENT |
|
||||
JSPROP_ENUMERATE |
|
||||
(bi->kind() == CONSTANT ? JSPROP_READONLY : 0);
|
||||
StackShape child(base, NameToId(bi->name()), slot, attrs, 0, 0);
|
||||
|
||||
StackShape child(nbase, id, slot, nfixed, attrs, 0, 0);
|
||||
|
||||
Shape *shape = cx->compartment()->propertyTree.getChild(cx, self->callObjShape_, child);
|
||||
shape = cx->compartment()->propertyTree.getChild(cx, shape, child);
|
||||
if (!shape)
|
||||
return false;
|
||||
|
||||
self->callObjShape_ = shape;
|
||||
JS_ASSERT(slot < nslots);
|
||||
slot++;
|
||||
}
|
||||
JS_ASSERT(slot == nslots);
|
||||
|
||||
JS_ASSERT(!self->callObjShape_->inDictionary());
|
||||
JS_ASSERT(!bi);
|
||||
|
||||
JS_ASSERT(!shape->inDictionary());
|
||||
self->callObjShape_.init(shape);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1114,7 +1114,7 @@ class StringSegmentRange
|
||||
: stack(cx), cur(cx)
|
||||
{}
|
||||
|
||||
JS_WARN_UNUSED_RESULT bool init(JSString *str) {
|
||||
MOZ_WARN_UNUSED_RESULT bool init(JSString *str) {
|
||||
JS_ASSERT(stack.empty());
|
||||
return settle(str);
|
||||
}
|
||||
@ -1128,7 +1128,7 @@ class StringSegmentRange
|
||||
return cur;
|
||||
}
|
||||
|
||||
JS_WARN_UNUSED_RESULT bool popFront() {
|
||||
MOZ_WARN_UNUSED_RESULT bool popFront() {
|
||||
JS_ASSERT(!empty());
|
||||
if (stack.empty()) {
|
||||
cur = nullptr;
|
||||
|
@ -102,14 +102,6 @@
|
||||
#define JS_NEVER_INLINE MOZ_NEVER_INLINE
|
||||
#endif
|
||||
|
||||
#ifndef JS_WARN_UNUSED_RESULT
|
||||
# if defined __GNUC__
|
||||
# define JS_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
# else
|
||||
# define JS_WARN_UNUSED_RESULT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JS_BEGIN_MACRO
|
||||
** JS_END_MACRO
|
||||
|
@ -229,6 +229,18 @@ ParseTask::~ParseTask()
|
||||
js_delete(errors[i]);
|
||||
}
|
||||
|
||||
bool
|
||||
js::OffThreadParsingMustWaitForGC(JSRuntime *rt)
|
||||
{
|
||||
// Off thread parsing can't occur during incremental collections on the
|
||||
// atoms compartment, to avoid triggering barriers. (Outside the atoms
|
||||
// compartment, the compilation will use a new zone that is never
|
||||
// collected.) If an atoms-zone GC is in progress, hold off on executing the
|
||||
// parse task until the atoms-zone GC completes (see
|
||||
// EnqueuePendingParseTasksAfterGC).
|
||||
return rt->activeGCInAtomsZone();
|
||||
}
|
||||
|
||||
bool
|
||||
js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &options,
|
||||
const jschar *chars, size_t length, HandleObject scopeChain,
|
||||
@ -299,13 +311,7 @@ js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &optio
|
||||
WorkerThreadState &state = *cx->runtime()->workerThreadState;
|
||||
JS_ASSERT(state.numThreads);
|
||||
|
||||
// Off thread parsing can't occur during incremental collections on the
|
||||
// atoms compartment, to avoid triggering barriers. (Outside the atoms
|
||||
// compartment, the compilation will use a new zone which doesn't require
|
||||
// barriers itself.) If an atoms-zone GC is in progress, hold off on
|
||||
// executing the parse task until the atoms-zone GC completes (see
|
||||
// EnqueuePendingParseTasksAfterGC).
|
||||
if (cx->runtime()->activeGCInAtomsZone()) {
|
||||
if (OffThreadParsingMustWaitForGC(cx->runtime())) {
|
||||
if (!state.parseWaitingOnGC.append(task.get()))
|
||||
return false;
|
||||
} else {
|
||||
@ -327,7 +333,7 @@ js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &optio
|
||||
void
|
||||
js::EnqueuePendingParseTasksAfterGC(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(!rt->activeGCInAtomsZone());
|
||||
JS_ASSERT(!OffThreadParsingMustWaitForGC(rt));
|
||||
|
||||
if (!rt->workerThreadState || rt->workerThreadState->parseWaitingOnGC.empty())
|
||||
return;
|
||||
|
@ -371,6 +371,11 @@ struct ParseTask
|
||||
~ParseTask();
|
||||
};
|
||||
|
||||
// Return whether, if a new parse task was started, it would need to wait for
|
||||
// an in-progress GC to complete before starting.
|
||||
extern bool
|
||||
OffThreadParsingMustWaitForGC(JSRuntime *rt);
|
||||
|
||||
// Compression tasks are allocated on the stack by their triggering thread,
|
||||
// which will block on the compression completing as the task goes out of scope
|
||||
// to ensure it completes at the required time.
|
||||
|
@ -3304,16 +3304,20 @@ OffThreadCompileScript(JSContext *cx, unsigned argc, jsval *vp)
|
||||
.setCompileAndGo(true)
|
||||
.setSourcePolicy(CompileOptions::SAVE_SOURCE);
|
||||
|
||||
if (!JS::CanCompileOffThread(cx, options)) {
|
||||
JS_ReportError(cx, "cannot compile code on worker thread");
|
||||
return false;
|
||||
}
|
||||
// We assume the caller wants caching if at all possible, ignoring
|
||||
// heuristics that make sense for a real browser.
|
||||
options.forceAsync = true;
|
||||
|
||||
const jschar *chars = JS_GetStringCharsZ(cx, scriptContents);
|
||||
if (!chars)
|
||||
return false;
|
||||
size_t length = JS_GetStringLength(scriptContents);
|
||||
|
||||
if (!JS::CanCompileOffThread(cx, options, length)) {
|
||||
JS_ReportError(cx, "cannot compile code on worker thread");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!offThreadState.startIfIdle(cx, scriptContents)) {
|
||||
JS_ReportError(cx, "called offThreadCompileScript without calling runOffThreadScript"
|
||||
" to receive prior off-thread compilation");
|
||||
|
@ -684,7 +684,7 @@ GlobalObject::addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value)
|
||||
RootedShape last(cx, holder->lastProperty());
|
||||
Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
|
||||
|
||||
StackShape child(base, id, slot, holder->numFixedSlots(), 0, 0, 0);
|
||||
StackShape child(base, id, slot, 0, 0, 0);
|
||||
RootedShape shape(cx, cx->compartment()->propertyTree.getChild(cx, last, child));
|
||||
if (!shape)
|
||||
return false;
|
||||
|
@ -620,7 +620,7 @@ JSObject::addPropertyInternal(typename ExecutionModeTraits<mode>::ExclusiveConte
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StackShape child(nbase, id, slot, obj->numFixedSlots(), attrs, flags, shortid);
|
||||
StackShape child(nbase, id, slot, attrs, flags, shortid);
|
||||
shape = getOrLookupChildProperty<mode>(cx, obj, last, child);
|
||||
}
|
||||
|
||||
@ -704,7 +704,7 @@ js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StackShape child(nbase, id, i, res->numFixedSlots(), JSPROP_ENUMERATE, 0, 0);
|
||||
StackShape child(nbase, id, i, JSPROP_ENUMERATE, 0, 0);
|
||||
newShape = cx->compartment()->propertyTree.getChild(cx, newShape, child);
|
||||
if (!newShape)
|
||||
return nullptr;
|
||||
@ -840,7 +840,7 @@ JSObject::putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextType c
|
||||
* Now that we've possibly preserved slot, check whether all members match.
|
||||
* If so, this is a redundant "put" and we can return without more work.
|
||||
*/
|
||||
if (shape->matchesParamsAfterId(nbase, slot, obj->numFixedSlots(), attrs, flags, shortid))
|
||||
if (shape->matchesParamsAfterId(nbase, slot, attrs, flags, shortid))
|
||||
return shape;
|
||||
|
||||
/*
|
||||
@ -901,7 +901,7 @@ JSObject::putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextType c
|
||||
JS_ASSERT(shape == obj->lastProperty());
|
||||
|
||||
/* Find or create a property tree node labeled by our arguments. */
|
||||
StackShape child(nbase, id, slot, obj->numFixedSlots(), attrs, flags, shortid);
|
||||
StackShape child(nbase, id, slot, attrs, flags, shortid);
|
||||
RootedShape parent(cx, shape->parent);
|
||||
Shape *newShape = getOrLookupChildProperty<mode>(cx, obj, parent, child);
|
||||
|
||||
|
@ -1146,18 +1146,17 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
|
||||
bool matches(const Shape *other) const {
|
||||
return propid_.get() == other->propid_.get() &&
|
||||
matchesParamsAfterId(other->base(), other->maybeSlot(), other->numFixedSlots(),
|
||||
other->attrs, other->flags, other->shortid_);
|
||||
matchesParamsAfterId(other->base(), other->maybeSlot(), other->attrs, other->flags,
|
||||
other->shortid_);
|
||||
}
|
||||
|
||||
inline bool matches(const StackShape &other) const;
|
||||
|
||||
bool matchesParamsAfterId(BaseShape *base, uint32_t aslot, uint32_t afixed, unsigned aattrs,
|
||||
unsigned aflags, int ashortid) const
|
||||
bool matchesParamsAfterId(BaseShape *base, uint32_t aslot, unsigned aattrs, unsigned aflags,
|
||||
int ashortid) const
|
||||
{
|
||||
return base->unowned() == this->base()->unowned() &&
|
||||
maybeSlot() == aslot &&
|
||||
numFixedSlots() == afixed &&
|
||||
attrs == aattrs &&
|
||||
((flags ^ aflags) & PUBLIC_FLAGS) == 0 &&
|
||||
shortid_ == ashortid;
|
||||
@ -1502,17 +1501,15 @@ struct StackShape
|
||||
UnownedBaseShape *base;
|
||||
jsid propid;
|
||||
uint32_t slot_;
|
||||
uint32_t nfixed_;
|
||||
uint8_t attrs;
|
||||
uint8_t flags;
|
||||
int16_t shortid;
|
||||
|
||||
explicit StackShape(UnownedBaseShape *base, jsid propid, uint32_t slot,
|
||||
uint32_t nfixed, unsigned attrs, unsigned flags, int shortid)
|
||||
unsigned attrs, unsigned flags, int shortid)
|
||||
: base(base),
|
||||
propid(propid),
|
||||
slot_(slot),
|
||||
nfixed_(nfixed),
|
||||
attrs(uint8_t(attrs)),
|
||||
flags(uint8_t(flags)),
|
||||
shortid(int16_t(shortid))
|
||||
@ -1526,7 +1523,6 @@ struct StackShape
|
||||
: base(shape->base()->unowned()),
|
||||
propid(shape->propidRef()),
|
||||
slot_(shape->maybeSlot()),
|
||||
nfixed_(shape->numFixedSlots()),
|
||||
attrs(shape->attrs),
|
||||
flags(shape->flags),
|
||||
shortid(shape->shortid_)
|
||||
@ -1548,10 +1544,6 @@ struct StackShape
|
||||
slot_ = slot;
|
||||
}
|
||||
|
||||
uint32_t numFixedSlots() const {
|
||||
return nfixed_;
|
||||
}
|
||||
|
||||
HashNumber hash() const {
|
||||
HashNumber hash = uintptr_t(base);
|
||||
|
||||
@ -1560,7 +1552,6 @@ struct StackShape
|
||||
hash = mozilla::RotateLeft(hash, 4) ^ attrs;
|
||||
hash = mozilla::RotateLeft(hash, 4) ^ shortid;
|
||||
hash = mozilla::RotateLeft(hash, 4) ^ slot_;
|
||||
hash = mozilla::RotateLeft(hash, 4) ^ nfixed_;
|
||||
hash = mozilla::RotateLeft(hash, 4) ^ JSID_BITS(propid);
|
||||
return hash;
|
||||
}
|
||||
@ -1710,8 +1701,7 @@ inline bool
|
||||
Shape::matches(const StackShape &other) const
|
||||
{
|
||||
return propid_.get() == other.propid &&
|
||||
matchesParamsAfterId(other.base, other.slot_, other.nfixed_, other.attrs, other.flags,
|
||||
other.shortid);
|
||||
matchesParamsAfterId(other.base, other.slot_, other.attrs, other.flags, other.shortid);
|
||||
}
|
||||
|
||||
template<> struct RootKind<Shape *> : SpecificRootKind<Shape *, THING_ROOT_SHAPE> {};
|
||||
|
@ -327,74 +327,45 @@ nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj,
|
||||
MOZ_CRASH();
|
||||
|
||||
AutoJSContext cx;
|
||||
JSObject2WrappedJSMap* map;
|
||||
nsXPCWrappedJS* root = nullptr;
|
||||
nsXPCWrappedJS* wrapper = nullptr;
|
||||
nsRefPtr<nsXPCWrappedJSClass> clasp;
|
||||
XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
|
||||
bool release_root = false;
|
||||
|
||||
map = rt->GetWrappedJSMap();
|
||||
JSObject2WrappedJSMap* map = rt->GetWrappedJSMap();
|
||||
if (!map) {
|
||||
MOZ_ASSERT(map,"bad map");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<nsXPCWrappedJSClass> clasp;
|
||||
nsXPCWrappedJSClass::GetNewOrUsed(cx, aIID, getter_AddRefs(clasp));
|
||||
if (!clasp)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// always find the root JSObject
|
||||
JS::RootedObject rootJSObj(cx, clasp->GetRootJSObject(cx, jsObj));
|
||||
if (!rootJSObj)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
root = map->Find(rootJSObj);
|
||||
nsRefPtr<nsXPCWrappedJS> root = map->Find(rootJSObj);
|
||||
if (root) {
|
||||
wrapper = root->FindOrFindInherited(aIID);
|
||||
nsRefPtr<nsXPCWrappedJS> wrapper = root->FindOrFindInherited(aIID);
|
||||
if (wrapper) {
|
||||
NS_ADDREF(wrapper);
|
||||
*wrapperResult = wrapper;
|
||||
wrapper.forget(wrapperResult);
|
||||
return NS_OK;
|
||||
}
|
||||
} else {
|
||||
// build the root wrapper
|
||||
if (rootJSObj == jsObj) {
|
||||
// the root will do double duty as the interface wrapper
|
||||
wrapper = root = new nsXPCWrappedJS(cx, jsObj, clasp, nullptr);
|
||||
} else if (rootJSObj != jsObj) {
|
||||
|
||||
map->Add(cx, root);
|
||||
// Make a new root wrapper, because there is no existing
|
||||
// root wrapper, and the wrapper we are trying to make isn't
|
||||
// a root.
|
||||
nsRefPtr<nsXPCWrappedJSClass> rootClasp;
|
||||
nsXPCWrappedJSClass::GetNewOrUsed(cx, NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(rootClasp));
|
||||
if (!rootClasp)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*wrapperResult = wrapper;
|
||||
return NS_OK;
|
||||
} else {
|
||||
// just a root wrapper
|
||||
nsXPCWrappedJSClass* rootClasp = nullptr;
|
||||
nsXPCWrappedJSClass::GetNewOrUsed(cx, NS_GET_IID(nsISupports),
|
||||
&rootClasp);
|
||||
if (!rootClasp)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
root = new nsXPCWrappedJS(cx, rootJSObj, rootClasp, nullptr);
|
||||
NS_RELEASE(rootClasp);
|
||||
|
||||
release_root = true;
|
||||
|
||||
map->Add(cx, root);
|
||||
}
|
||||
root = new nsXPCWrappedJS(cx, rootJSObj, rootClasp, nullptr);
|
||||
}
|
||||
|
||||
// at this point we have a root and may need to build the specific wrapper
|
||||
MOZ_ASSERT(root, "bad root");
|
||||
MOZ_ASSERT(clasp, "bad clasp");
|
||||
MOZ_ASSERT(!wrapper, "no wrapper found yet");
|
||||
|
||||
wrapper = new nsXPCWrappedJS(cx, jsObj, clasp, root);
|
||||
|
||||
if (release_root)
|
||||
NS_RELEASE(root);
|
||||
|
||||
*wrapperResult = wrapper;
|
||||
nsRefPtr<nsXPCWrappedJS> wrapper = new nsXPCWrappedJS(cx, jsObj, clasp, root);
|
||||
wrapper.forget(wrapperResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -413,9 +384,10 @@ nsXPCWrappedJS::nsXPCWrappedJS(JSContext* cx,
|
||||
// that are subject to finalization. See the top of the file for more
|
||||
// details.
|
||||
NS_ADDREF_THIS();
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
if (!IsRootWrapper()) {
|
||||
if (IsRootWrapper()) {
|
||||
nsXPConnect::GetRuntimeInstance()->GetWrappedJSMap()->Add(cx, this);
|
||||
} else {
|
||||
NS_ADDREF(mRoot);
|
||||
mNext = mRoot->mNext;
|
||||
mRoot->mNext = this;
|
||||
|
@ -623,10 +623,10 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
|
||||
if (scrollableFrame) {
|
||||
nsRect contentBounds = scrollableFrame->GetScrollRange();
|
||||
if (scrollableFrame->GetScrollbarStyles().mVertical == NS_STYLE_OVERFLOW_HIDDEN) {
|
||||
contentBounds.height = 0;
|
||||
metrics.SetDisableScrollingY(true);
|
||||
}
|
||||
if (scrollableFrame->GetScrollbarStyles().mHorizontal == NS_STYLE_OVERFLOW_HIDDEN) {
|
||||
contentBounds.width = 0;
|
||||
metrics.SetDisableScrollingX(true);
|
||||
}
|
||||
contentBounds.width += scrollableFrame->GetScrollPortRect().width;
|
||||
contentBounds.height += scrollableFrame->GetScrollPortRect().height;
|
||||
|
5
layout/forms/crashtests/949891.xhtml
Normal file
5
layout/forms/crashtests/949891.xhtml
Normal file
@ -0,0 +1,5 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<body>
|
||||
<input type="number"> </input>
|
||||
</body>
|
||||
</html>
|
@ -53,4 +53,5 @@ asserts(0-1) load 669767.html
|
||||
load 682684.xhtml
|
||||
load 865602.html
|
||||
load 944198.html
|
||||
load 949891.xhtml
|
||||
load 960277-2.html
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
|
||||
virtual void ContentStatesChanged(nsEventStates aStates);
|
||||
virtual bool IsLeaf() const MOZ_OVERRIDE { return false; }
|
||||
virtual bool IsLeaf() const MOZ_OVERRIDE { return true; }
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
|
||||
|
@ -22,6 +22,13 @@
|
||||
using namespace mozilla::css;
|
||||
using namespace mozilla::layout;
|
||||
|
||||
// Convenience typedefs for helper classes that we forward-declare in .h file
|
||||
// (so that nsFlexContainerFrame methods can use them as parameters):
|
||||
typedef nsFlexContainerFrame::FlexItem FlexItem;
|
||||
typedef nsFlexContainerFrame::FlexLine FlexLine;
|
||||
typedef nsFlexContainerFrame::FlexboxAxisTracker FlexboxAxisTracker;
|
||||
typedef nsFlexContainerFrame::StrutInfo StrutInfo;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo*
|
||||
GetFlexContainerLog()
|
||||
@ -198,7 +205,7 @@ MarginComponentForSide(nsMargin& aMargin, Side aSide)
|
||||
IsAxisHorizontal((axisTracker_).GetCrossAxis()) ? (width_) : (height_)
|
||||
|
||||
// Encapsulates our flex container's main & cross axes.
|
||||
class MOZ_STACK_CLASS FlexboxAxisTracker {
|
||||
class MOZ_STACK_CLASS nsFlexContainerFrame::FlexboxAxisTracker {
|
||||
public:
|
||||
FlexboxAxisTracker(nsFlexContainerFrame* aFlexContainerFrame);
|
||||
|
||||
@ -273,8 +280,9 @@ private:
|
||||
// Represents a flex item.
|
||||
// Includes the various pieces of input that the Flexbox Layout Algorithm uses
|
||||
// to resolve a flexible width.
|
||||
class FlexItem {
|
||||
class nsFlexContainerFrame::FlexItem {
|
||||
public:
|
||||
// Normal constructor:
|
||||
FlexItem(nsIFrame* aChildFrame,
|
||||
float aFlexGrow, float aFlexShrink, nscoord aMainBaseSize,
|
||||
nscoord aMainMinSize, nscoord aMainMaxSize,
|
||||
@ -282,6 +290,9 @@ public:
|
||||
nsMargin aMargin, nsMargin aBorderPadding,
|
||||
const FlexboxAxisTracker& aAxisTracker);
|
||||
|
||||
// Simplified constructor, to be used only for generating "struts":
|
||||
FlexItem(nsIFrame* aChildFrame, nscoord aCrossSize);
|
||||
|
||||
// Accessors
|
||||
nsIFrame* Frame() const { return mFrame; }
|
||||
nscoord GetFlexBaseSize() const { return mFlexBaseSize; }
|
||||
@ -323,6 +334,10 @@ public:
|
||||
// cross axis).
|
||||
bool IsStretched() const { return mIsStretched; }
|
||||
|
||||
// Indicates whether this item is a "strut" left behind by an element with
|
||||
// visibility:collapse.
|
||||
bool IsStrut() const { return mIsStrut; }
|
||||
|
||||
uint8_t GetAlignSelf() const { return mAlignSelf; }
|
||||
|
||||
// Returns the flex weight that we should use in the "resolving flexible
|
||||
@ -540,6 +555,8 @@ protected:
|
||||
bool mHadMeasuringReflow; // Did this item get a preliminary reflow,
|
||||
// to measure its desired height?
|
||||
bool mIsStretched; // See IsStretched() documentation
|
||||
bool mIsStrut; // Is this item a "strut" left behind by an element
|
||||
// with visibility:collapse?
|
||||
uint8_t mAlignSelf; // My "align-self" computed value (with "auto"
|
||||
// swapped out for parent"s "align-items" value,
|
||||
// in our constructor).
|
||||
@ -547,7 +564,7 @@ protected:
|
||||
|
||||
// Represents a single flex line in a flex container.
|
||||
// Manages an array of the FlexItems that are in the line.
|
||||
class FlexLine {
|
||||
class nsFlexContainerFrame::FlexLine {
|
||||
public:
|
||||
FlexLine()
|
||||
: mTotalInnerHypotheticalMainSize(0),
|
||||
@ -611,6 +628,43 @@ private:
|
||||
nscoord mBaselineOffsetFromCrossStart;
|
||||
};
|
||||
|
||||
// Information about a strut left behind by a FlexItem that's been collapsed
|
||||
// using "visibility:collapse".
|
||||
struct nsFlexContainerFrame::StrutInfo {
|
||||
StrutInfo(uint32_t aItemIdx, nscoord aStrutCrossSize)
|
||||
: mItemIdx(aItemIdx),
|
||||
mStrutCrossSize(aStrutCrossSize)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t mItemIdx; // Index in the child list.
|
||||
nscoord mStrutCrossSize; // The cross-size of this strut.
|
||||
};
|
||||
|
||||
static void
|
||||
BuildStrutInfoFromCollapsedItems(nsTArray<FlexLine>& aLines,
|
||||
nsTArray<StrutInfo>& aStruts)
|
||||
{
|
||||
MOZ_ASSERT(aStruts.IsEmpty(),
|
||||
"We should only build up StrutInfo once per reflow, so "
|
||||
"aStruts should be empty when this is called");
|
||||
|
||||
uint32_t itemIdxInContainer = 0;
|
||||
for (uint32_t lineIdx = 0; lineIdx < aLines.Length(); lineIdx++) {
|
||||
FlexLine& line = aLines[lineIdx];
|
||||
for (uint32_t i = 0; i < line.mItems.Length(); ++i) {
|
||||
FlexItem& item = line.mItems[i];
|
||||
if (NS_STYLE_VISIBILITY_COLLAPSE ==
|
||||
item.Frame()->StyleVisibility()->mVisible) {
|
||||
// Note the cross size of the line as the item's strut size.
|
||||
aStruts.AppendElement(StrutInfo(itemIdxInContainer,
|
||||
line.GetLineCrossSize()));
|
||||
}
|
||||
itemIdxInContainer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper-function to find the first non-anonymous-box descendent of aFrame.
|
||||
static nsIFrame*
|
||||
GetFirstNonAnonBoxDescendant(nsIFrame* aFrame)
|
||||
@ -995,9 +1049,12 @@ FlexItem::FlexItem(nsIFrame* aChildFrame,
|
||||
mHadMaxViolation(false),
|
||||
mHadMeasuringReflow(false),
|
||||
mIsStretched(false),
|
||||
mIsStrut(false),
|
||||
mAlignSelf(aChildFrame->StylePosition()->mAlignSelf)
|
||||
{
|
||||
MOZ_ASSERT(aChildFrame, "expecting a non-null child frame");
|
||||
MOZ_ASSERT(mFrame, "expecting a non-null child frame");
|
||||
MOZ_ASSERT(!mFrame->IsAbsolutelyPositioned(),
|
||||
"abspos child frames should not be treated as flex items");
|
||||
|
||||
SetFlexBaseSizeAndMainSize(aFlexBaseSize);
|
||||
|
||||
@ -1037,6 +1094,42 @@ FlexItem::FlexItem(nsIFrame* aChildFrame,
|
||||
}
|
||||
}
|
||||
|
||||
// Simplified constructor for creating a special "strut" FlexItem, for a child
|
||||
// with visibility:collapse. The strut has 0 main-size, and it only exists to
|
||||
// impose a minimum cross size on whichever FlexLine it ends up in.
|
||||
FlexItem::FlexItem(nsIFrame* aChildFrame, nscoord aCrossSize)
|
||||
: mFrame(aChildFrame),
|
||||
mFlexGrow(0.0f),
|
||||
mFlexShrink(0.0f),
|
||||
// mBorderPadding uses default constructor,
|
||||
// mMargin uses default constructor,
|
||||
mFlexBaseSize(0),
|
||||
mMainMinSize(0),
|
||||
mMainMaxSize(0),
|
||||
mCrossMinSize(0),
|
||||
mCrossMaxSize(0),
|
||||
mMainSize(0),
|
||||
mMainPosn(0),
|
||||
mCrossSize(aCrossSize),
|
||||
mCrossPosn(0),
|
||||
mAscent(0),
|
||||
mShareOfFlexWeightSoFar(0.0f),
|
||||
mIsFrozen(true),
|
||||
mHadMinViolation(false),
|
||||
mHadMaxViolation(false),
|
||||
mHadMeasuringReflow(false),
|
||||
mIsStretched(false),
|
||||
mIsStrut(true), // (this is the constructor for making struts, after all)
|
||||
mAlignSelf(NS_STYLE_ALIGN_ITEMS_FLEX_START)
|
||||
{
|
||||
MOZ_ASSERT(mFrame, "expecting a non-null child frame");
|
||||
MOZ_ASSERT(NS_STYLE_VISIBILITY_COLLAPSE ==
|
||||
mFrame->StyleVisibility()->mVisible,
|
||||
"Should only make struts for children with 'visibility:collapse'");
|
||||
MOZ_ASSERT(!mFrame->IsAbsolutelyPositioned(),
|
||||
"abspos child frames should not be treated as flex items");
|
||||
}
|
||||
|
||||
nscoord
|
||||
FlexItem::GetBaselineOffsetFromOuterCrossStart(
|
||||
AxisOrientationType aCrossAxis) const
|
||||
@ -2175,6 +2268,7 @@ nsFlexContainerFrame::GenerateFlexLines(
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nscoord aContentBoxMainSize,
|
||||
nscoord aAvailableHeightForContent,
|
||||
const nsTArray<StrutInfo>& aStruts,
|
||||
const FlexboxAxisTracker& aAxisTracker,
|
||||
nsTArray<FlexLine>& aLines)
|
||||
{
|
||||
@ -2219,6 +2313,14 @@ nsFlexContainerFrame::GenerateFlexLines(
|
||||
}
|
||||
}
|
||||
|
||||
// Tracks the index of the next strut, in aStruts (and when this hits
|
||||
// aStruts.Length(), that means there are no more struts):
|
||||
uint32_t nextStrutIdx = 0;
|
||||
|
||||
// Overall index of the current flex item in the flex container. (This gets
|
||||
// checked against entries in aStruts.)
|
||||
uint32_t itemIdxInContainer = 0;
|
||||
|
||||
for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
|
||||
nsIFrame* childFrame = e.get();
|
||||
|
||||
@ -2228,13 +2330,24 @@ nsFlexContainerFrame::GenerateFlexLines(
|
||||
curLine = aLines.AppendElement();
|
||||
}
|
||||
|
||||
FlexItem* item = curLine->mItems.AppendElement(
|
||||
GenerateFlexItemForChild(aPresContext, childFrame,
|
||||
aReflowState, aAxisTracker));
|
||||
FlexItem* item;
|
||||
if (nextStrutIdx < aStruts.Length() &&
|
||||
aStruts[nextStrutIdx].mItemIdx == itemIdxInContainer) {
|
||||
|
||||
// Use the simplified "strut" FlexItem constructor:
|
||||
item = curLine->mItems.AppendElement(
|
||||
FlexItem(childFrame, aStruts[nextStrutIdx].mStrutCrossSize));
|
||||
nextStrutIdx++;
|
||||
} else {
|
||||
item = curLine->mItems.AppendElement(
|
||||
GenerateFlexItemForChild(aPresContext, childFrame,
|
||||
aReflowState, aAxisTracker));
|
||||
|
||||
nsresult rv = ResolveFlexItemMaxContentSizing(aPresContext, *item,
|
||||
aReflowState, aAxisTracker);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
}
|
||||
|
||||
nsresult rv = ResolveFlexItemMaxContentSizing(aPresContext, *item,
|
||||
aReflowState, aAxisTracker);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
nscoord itemInnerHypotheticalMainSize = item->GetMainSize();
|
||||
nscoord itemOuterHypotheticalMainSize = item->GetMainSize() +
|
||||
item->GetMarginBorderPaddingSizeInAxis(aAxisTracker.GetMainAxis());
|
||||
@ -2272,6 +2385,7 @@ nsFlexContainerFrame::GenerateFlexLines(
|
||||
childFrame->StyleDisplay()->mBreakAfter) {
|
||||
curLine = aLines.AppendElement();
|
||||
}
|
||||
itemIdxInContainer++;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -2608,8 +2722,6 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
// We (and our children) can only depend on our ancestor's height if we have
|
||||
// a percent-height, or if we're positioned and we have "top" and "bottom"
|
||||
// set and have height:auto. (There are actually other cases, too -- e.g. if
|
||||
@ -2646,9 +2758,6 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
const FlexboxAxisTracker axisTracker(this);
|
||||
|
||||
nscoord contentBoxMainSize = GetMainSizeFromReflowState(aReflowState,
|
||||
axisTracker);
|
||||
|
||||
// If we're being fragmented into a constrained height, subtract off
|
||||
// borderpadding-top from it, to get the available height for our
|
||||
// content box. (Don't subtract if we're skipping top border/padding,
|
||||
@ -2661,20 +2770,51 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
availableHeightForContent = std::max(availableHeightForContent, 0);
|
||||
}
|
||||
|
||||
nscoord contentBoxMainSize = GetMainSizeFromReflowState(aReflowState,
|
||||
axisTracker);
|
||||
|
||||
nsAutoTArray<StrutInfo, 1> struts;
|
||||
nsresult rv = DoFlexLayout(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
contentBoxMainSize, availableHeightForContent,
|
||||
struts, axisTracker);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !struts.IsEmpty()) {
|
||||
// We're restarting flex layout, with new knowledge of collapsed items.
|
||||
rv = DoFlexLayout(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
contentBoxMainSize, availableHeightForContent,
|
||||
struts, axisTracker);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nscoord aContentBoxMainSize,
|
||||
nscoord aAvailableHeightForContent,
|
||||
nsTArray<StrutInfo>& aStruts,
|
||||
const FlexboxAxisTracker& aAxisTracker)
|
||||
{
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
// Generate an array of our flex items (already sorted), in a FlexLine.
|
||||
nsAutoTArray<FlexLine, 1> lines;
|
||||
nsresult rv = GenerateFlexLines(aPresContext, aReflowState,
|
||||
contentBoxMainSize, availableHeightForContent,
|
||||
axisTracker, lines);
|
||||
aContentBoxMainSize,
|
||||
aAvailableHeightForContent,
|
||||
aStruts, aAxisTracker, lines);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
contentBoxMainSize =
|
||||
ClampFlexContainerMainSize(aReflowState, axisTracker,
|
||||
contentBoxMainSize, availableHeightForContent,
|
||||
aContentBoxMainSize =
|
||||
ClampFlexContainerMainSize(aReflowState, aAxisTracker,
|
||||
aContentBoxMainSize, aAvailableHeightForContent,
|
||||
lines, aStatus);
|
||||
|
||||
for (uint32_t i = 0; i < lines.Length(); i++) {
|
||||
lines[i].ResolveFlexibleLengths(contentBoxMainSize);
|
||||
lines[i].ResolveFlexibleLengths(aContentBoxMainSize);
|
||||
}
|
||||
|
||||
// Cross Size Determination - Flexbox spec section 9.4
|
||||
@ -2685,21 +2825,21 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
for (uint32_t i = 0; i < line.mItems.Length(); ++i) {
|
||||
FlexItem& curItem = line.mItems[i];
|
||||
|
||||
// (If the item's already been stretched, then it already knows its
|
||||
// cross size. Don't bother trying to recalculate it.)
|
||||
if (!curItem.IsStretched()) {
|
||||
// (If the item's already been stretched, or it's a strut, then it
|
||||
// already knows its cross size. Don't bother trying to recalculate it.)
|
||||
if (!curItem.IsStretched() && !curItem.IsStrut()) {
|
||||
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
|
||||
curItem.Frame(),
|
||||
nsSize(aReflowState.ComputedWidth(),
|
||||
NS_UNCONSTRAINEDSIZE));
|
||||
// Override computed main-size
|
||||
if (IsAxisHorizontal(axisTracker.GetMainAxis())) {
|
||||
if (IsAxisHorizontal(aAxisTracker.GetMainAxis())) {
|
||||
childReflowState.SetComputedWidth(curItem.GetMainSize());
|
||||
} else {
|
||||
childReflowState.SetComputedHeight(curItem.GetMainSize());
|
||||
}
|
||||
|
||||
nsresult rv = SizeItemInCrossAxis(aPresContext, axisTracker,
|
||||
nsresult rv = SizeItemInCrossAxis(aPresContext, aAxisTracker,
|
||||
childReflowState, curItem);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@ -2709,19 +2849,32 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
// Calculate the cross size and (if necessary) baseline-alignment position
|
||||
// for each of our flex lines:
|
||||
for (uint32_t lineIdx = 0; lineIdx < lines.Length(); ++lineIdx) {
|
||||
lines[lineIdx].ComputeCrossSizeAndBaseline(axisTracker);
|
||||
lines[lineIdx].ComputeCrossSizeAndBaseline(aAxisTracker);
|
||||
}
|
||||
|
||||
bool isCrossSizeDefinite;
|
||||
const nscoord contentBoxCrossSize =
|
||||
ComputeCrossSize(aReflowState, axisTracker, lines,
|
||||
availableHeightForContent, &isCrossSizeDefinite, aStatus);
|
||||
ComputeCrossSize(aReflowState, aAxisTracker, lines,
|
||||
aAvailableHeightForContent, &isCrossSizeDefinite, aStatus);
|
||||
|
||||
// Set up state for cross-axis alignment, at a high level (outside the
|
||||
// scope of a particular flex line)
|
||||
CrossAxisPositionTracker
|
||||
crossAxisPosnTracker(lines, aReflowState.mStylePosition->mAlignContent,
|
||||
contentBoxCrossSize, isCrossSizeDefinite, axisTracker);
|
||||
contentBoxCrossSize, isCrossSizeDefinite,
|
||||
aAxisTracker);
|
||||
|
||||
// Now that we know the cross size of each line (including
|
||||
// "align-content:stretch" adjustments, from the CrossAxisPositionTracker
|
||||
// constructor), we can create struts for any flex items with
|
||||
// "visibility: collapse" (and restart flex layout).
|
||||
if (aStruts.IsEmpty()) { // (Don't make struts if we already did)
|
||||
BuildStrutInfoFromCollapsedItems(lines, aStruts);
|
||||
if (!aStruts.IsEmpty()) {
|
||||
// Restart flex layout, using our struts.
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the flex container's baseline, from the baseline-alignment position
|
||||
// of the first line's baseline-aligned items.
|
||||
@ -2744,7 +2897,7 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
flexContainerAscent = aReflowState.ComputedPhysicalBorderPadding().top +
|
||||
PhysicalPosFromLogicalPos(firstLineBaselineOffsetWRTContainer,
|
||||
contentBoxCrossSize,
|
||||
axisTracker.GetCrossAxis());
|
||||
aAxisTracker.GetCrossAxis());
|
||||
}
|
||||
|
||||
for (uint32_t lineIdx = 0; lineIdx < lines.Length(); ++lineIdx) {
|
||||
@ -2753,13 +2906,13 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
// Main-Axis Alignment - Flexbox spec section 9.5
|
||||
// ==============================================
|
||||
line.PositionItemsInMainAxis(aReflowState.mStylePosition->mJustifyContent,
|
||||
contentBoxMainSize,
|
||||
axisTracker);
|
||||
aContentBoxMainSize,
|
||||
aAxisTracker);
|
||||
|
||||
// Cross-Axis Alignment - Flexbox spec section 9.6
|
||||
// ===============================================
|
||||
line.PositionItemsInCrossAxis(crossAxisPosnTracker.GetPosition(),
|
||||
axisTracker);
|
||||
aAxisTracker);
|
||||
crossAxisPosnTracker.TraverseLine(line);
|
||||
crossAxisPosnTracker.TraversePackingSpace();
|
||||
}
|
||||
@ -2779,10 +2932,10 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
for (uint32_t i = 0; i < line.mItems.Length(); ++i) {
|
||||
FlexItem& curItem = line.mItems[i];
|
||||
|
||||
nsPoint physicalPosn = axisTracker.PhysicalPointFromLogicalPoint(
|
||||
nsPoint physicalPosn = aAxisTracker.PhysicalPointFromLogicalPoint(
|
||||
curItem.GetMainPosition(),
|
||||
curItem.GetCrossPosition(),
|
||||
contentBoxMainSize,
|
||||
aContentBoxMainSize,
|
||||
contentBoxCrossSize);
|
||||
// Adjust physicalPosn to be relative to the container's border-box
|
||||
// (i.e. its frame rect), instead of the container's content-box:
|
||||
@ -2799,7 +2952,7 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
bool didOverrideComputedHeight = false;
|
||||
|
||||
// Override computed main-size
|
||||
if (IsAxisHorizontal(axisTracker.GetMainAxis())) {
|
||||
if (IsAxisHorizontal(aAxisTracker.GetMainAxis())) {
|
||||
childReflowState.SetComputedWidth(curItem.GetMainSize());
|
||||
didOverrideComputedWidth = true;
|
||||
} else {
|
||||
@ -2811,7 +2964,7 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
if (curItem.IsStretched()) {
|
||||
MOZ_ASSERT(curItem.GetAlignSelf() == NS_STYLE_ALIGN_ITEMS_STRETCH,
|
||||
"stretched item w/o 'align-self: stretch'?");
|
||||
if (IsAxisHorizontal(axisTracker.GetCrossAxis())) {
|
||||
if (IsAxisHorizontal(aAxisTracker.GetCrossAxis())) {
|
||||
childReflowState.SetComputedWidth(curItem.GetCrossSize());
|
||||
didOverrideComputedWidth = true;
|
||||
} else {
|
||||
@ -2884,8 +3037,8 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
nsSize desiredContentBoxSize =
|
||||
axisTracker.PhysicalSizeFromLogicalSizes(contentBoxMainSize,
|
||||
contentBoxCrossSize);
|
||||
aAxisTracker.PhysicalSizeFromLogicalSizes(aContentBoxMainSize,
|
||||
contentBoxCrossSize);
|
||||
|
||||
aDesiredSize.Width() = desiredContentBoxSize.width +
|
||||
containerBorderPadding.LeftRight();
|
||||
|
@ -17,11 +17,6 @@ nsIFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell,
|
||||
|
||||
typedef nsContainerFrame nsFlexContainerFrameSuper;
|
||||
|
||||
class FlexItem;
|
||||
class FlexLine;
|
||||
class FlexboxAxisTracker;
|
||||
class MainAxisPositionTracker;
|
||||
class SingleLineCrossAxisPositionTracker;
|
||||
template <class T> class nsTArray;
|
||||
|
||||
class nsFlexContainerFrame : public nsFlexContainerFrameSuper {
|
||||
@ -34,6 +29,12 @@ class nsFlexContainerFrame : public nsFlexContainerFrameSuper {
|
||||
nsStyleContext* aContext);
|
||||
|
||||
public:
|
||||
// Forward-decls of helper classes
|
||||
class FlexItem;
|
||||
class FlexLine;
|
||||
class FlexboxAxisTracker;
|
||||
class StrutInfo;
|
||||
|
||||
// nsIFrame overrides
|
||||
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
@ -64,6 +65,29 @@ protected:
|
||||
{}
|
||||
virtual ~nsFlexContainerFrame();
|
||||
|
||||
/*
|
||||
* This method does the bulk of the flex layout, implementing the algorithm
|
||||
* described at:
|
||||
* http://dev.w3.org/csswg/css-flexbox/#layout-algorithm
|
||||
* (with a few initialization pieces happening in the caller, Reflow().
|
||||
*
|
||||
* Since this is a helper for Reflow(), this takes all the same parameters
|
||||
* as Reflow(), plus a few more parameters that Reflow() sets up for us.
|
||||
*
|
||||
* (The logic behind the division of work between Reflow and DoFlexLayout is
|
||||
* as follows: DoFlexLayout() begins at the step that we have to jump back
|
||||
* to, if we find any visibility:collapse children, and Reflow() does
|
||||
* everything before that point.)
|
||||
*/
|
||||
nsresult DoFlexLayout(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nscoord aContentBoxMainSize,
|
||||
nscoord aAvailableHeightForContent,
|
||||
nsTArray<StrutInfo>& aStruts,
|
||||
const FlexboxAxisTracker& aAxisTracker);
|
||||
|
||||
/**
|
||||
* Checks whether our child-frame list "mFrames" is sorted, using the given
|
||||
* IsLessThanOrEqual function, and sorts it if it's not already sorted.
|
||||
@ -98,6 +122,7 @@ protected:
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nscoord aContentBoxMainSize,
|
||||
nscoord aAvailableHeightForContent,
|
||||
const nsTArray<StrutInfo>& aStruts,
|
||||
const FlexboxAxisTracker& aAxisTracker,
|
||||
nsTArray<FlexLine>& aLines);
|
||||
|
||||
|
@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!-- In this reference case, we get each container to be sized the same as
|
||||
in the testcase, without any visible baseline alignemnt, by using some
|
||||
hidden flex items.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Reftest Reference</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
width: 50px;
|
||||
background: yellow;
|
||||
border: 1px dotted black;
|
||||
margin: 5px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.hiddenItemForSizing {
|
||||
width: 0;
|
||||
color: transparent;
|
||||
align-self: baseline;
|
||||
}
|
||||
.largeFont {
|
||||
font-size: 20px;
|
||||
background: lightblue;
|
||||
/* Our flex items get padding on opposite sides (top/bottom) so that they
|
||||
produce a large combined height when baseline-aligned: */
|
||||
padding-top: 5px;
|
||||
}
|
||||
.smallFont {
|
||||
font-size: 10px;
|
||||
background: pink;
|
||||
/* Our flex items get padding on opposite sides (top/bottom) so that they
|
||||
produce a large combined height when baseline-aligned: */
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="flexContainer">
|
||||
<div class="largeFont">a</div>
|
||||
<!-- Hidden flex items used to determine container's cross size,
|
||||
based on their baseline-aligned combined cross size: -->
|
||||
<div class="largeFont hiddenItemForSizing">a</div>
|
||||
<div class="smallFont hiddenItemForSizing">b</div>
|
||||
</div>
|
||||
|
||||
<div class="flexContainer">
|
||||
<div class="smallFont">b</div>
|
||||
<!-- Hidden flex items used to determine container's cross size,
|
||||
based on their baseline-aligned combined cross size: -->
|
||||
<div class="largeFont hiddenItemForSizing">a</div>
|
||||
<div class="smallFont hiddenItemForSizing">b</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: Testing that a collapsed flex item participates in baseline alignment only for the purpose of establishing container's cross size</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<link rel="help" href="http://www.w3.org/TR/css3-flexbox/#algo-visibility">
|
||||
<link rel="match" href="flexbox-collapsed-item-baseline-1-ref.html">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
width: 50px;
|
||||
background: yellow;
|
||||
border: 1px dotted black;
|
||||
margin: 5px;
|
||||
align-items: baseline;
|
||||
}
|
||||
.collapse {
|
||||
visibility: collapse;
|
||||
}
|
||||
.largeFont {
|
||||
font-size: 20px;
|
||||
background: lightblue;
|
||||
/* Our flex items get padding on opposite sides (top/bottom) so that they
|
||||
produce a large combined height when baseline-aligned: */
|
||||
padding-top: 5px;
|
||||
}
|
||||
.smallFont {
|
||||
font-size: 10px;
|
||||
background: pink;
|
||||
/* Our flex items get padding on opposite sides (top/bottom) so that they
|
||||
produce a large combined height when baseline-aligned: */
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Second item collapsed: -->
|
||||
<div class="flexContainer">
|
||||
<div class="largeFont">a</div>
|
||||
<div class="smallFont collapse">b</div>
|
||||
</div>
|
||||
|
||||
<!-- First item collapsed: -->
|
||||
<div class="flexContainer">
|
||||
<div class="largeFont collapse">a</div>
|
||||
<div class="smallFont">b</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!-- In this reference case, we have blocks in place of the testcase's
|
||||
flex containers. The testcase's collapsed flex items are entirely
|
||||
absent here (and the remaining content is sized using exact pixel
|
||||
values).
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Reftest Reference</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
background: yellow;
|
||||
border: 1px dotted black;
|
||||
float: left;
|
||||
margin: 5px;
|
||||
}
|
||||
.flexContainer > * {
|
||||
/* All flex items have 20px base size */
|
||||
width: 20px;
|
||||
}
|
||||
.collapse {
|
||||
flex-basis: 0;
|
||||
height: 20px;
|
||||
}
|
||||
.flexible {
|
||||
flex: 1 auto;
|
||||
}
|
||||
.heightTall {
|
||||
height: 40px;
|
||||
background: purple;
|
||||
}
|
||||
.heightAuto {
|
||||
background: teal;
|
||||
}
|
||||
.heightShort {
|
||||
height: 10px;
|
||||
background: pink;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- FIRST ROW: -->
|
||||
<!-- Just one (collapsed) flex item, which ends up establishing
|
||||
the container's size (even though it's collapsed): -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightTall collapse"></div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
<!-- SECOND ROW: -->
|
||||
<!-- One collapsed flex item, one short flex item.
|
||||
(Container ends up with collapsed item's height) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightTall collapse"></div>
|
||||
<div class="heightShort"></div>
|
||||
</div>
|
||||
<!-- (same, but with items in opposite order) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightShort"></div>
|
||||
<div class="heightTall collapse"></div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
<!-- THIRD ROW: -->
|
||||
<!-- One collapsed flex item, one stretched flex item.
|
||||
(Container and stretched item end up with collapsed item's height) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightTall collapse"></div>
|
||||
<div class="heightAuto"></div>
|
||||
</div>
|
||||
<!-- (again, with items in opposite order) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightAuto"></div>
|
||||
<div class="heightTall collapse"></div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
<!-- FOURTH ROW: -->
|
||||
<!-- One collapsed flex item, one other flex item; both are flexible.
|
||||
(The non-collapsed one should take all of the available width.) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightAuto collapse"></div>
|
||||
<div class="heightTall flexible"></div>
|
||||
</div>
|
||||
<!-- (again, with items in opposite order) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightTall flexible"></div>
|
||||
<div class="heightAuto collapse"></div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,98 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: Testing that visibility:collapse on a flex item in a single-line flex container maintains the containers's cross size, but doesn't otherwise impact flex layout</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<link rel="help" href="http://www.w3.org/TR/css3-flexbox/#algo-visibility">
|
||||
<link rel="match" href="flexbox-collapsed-item-horiz-1-ref.html">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
background: yellow;
|
||||
border: 1px dotted black;
|
||||
float: left;
|
||||
margin: 5px;
|
||||
}
|
||||
.flexContainer > * {
|
||||
/* All flex items have 20px base size */
|
||||
width: 20px;
|
||||
}
|
||||
.collapse {
|
||||
visibility: collapse;
|
||||
}
|
||||
.flexible {
|
||||
flex: 1 auto;
|
||||
}
|
||||
.heightTall {
|
||||
height: 40px;
|
||||
background: purple;
|
||||
}
|
||||
.heightAuto {
|
||||
background: teal;
|
||||
}
|
||||
.heightShort {
|
||||
height: 10px;
|
||||
background: pink;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- FIRST ROW: -->
|
||||
<!-- Just one (collapsed) flex item, which ends up establishing
|
||||
the container's size (even though it's collapsed): -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightTall collapse"></div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
<!-- SECOND ROW: -->
|
||||
<!-- One collapsed flex item, one short flex item.
|
||||
(Container ends up with collapsed item's height) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightTall collapse"></div>
|
||||
<div class="heightShort"></div>
|
||||
</div>
|
||||
<!-- (same, but with items in opposite order) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightShort"></div>
|
||||
<div class="heightTall collapse"></div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
<!-- THIRD ROW: -->
|
||||
<!-- One collapsed flex item, one stretched flex item.
|
||||
(Container and stretched item end up with collapsed item's height) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightTall collapse"></div>
|
||||
<div class="heightAuto"></div>
|
||||
</div>
|
||||
<!-- (again, with items in opposite order) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightAuto"></div>
|
||||
<div class="heightTall collapse"></div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
<!-- FOURTH ROW: -->
|
||||
<!-- One collapsed flex item, one other flex item; both are flexible.
|
||||
(The non-collapsed one should take all of the available width.) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightAuto flexible collapse"></div>
|
||||
<div class="heightTall flexible"></div>
|
||||
</div>
|
||||
<!-- (again, with items in opposite order) -->
|
||||
<div class="flexContainer">
|
||||
<div class="heightTall flexible"></div>
|
||||
<div class="heightAuto flexible collapse"></div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,108 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Reftest Reference</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
/* These let us show where each flex line begins (and hence, how tall
|
||||
the flex lines end up) */
|
||||
align-content: flex-start;
|
||||
align-items: flex-start;
|
||||
|
||||
width: 30px;
|
||||
background: yellow;
|
||||
border: 1px dotted black;
|
||||
float: left;
|
||||
margin: 5px;
|
||||
}
|
||||
.collapsedItem {
|
||||
width: 0;
|
||||
height: 25px;
|
||||
}
|
||||
.halfWidthItem {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background: teal;
|
||||
}
|
||||
.fullWidthItem {
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
background: purple;
|
||||
}
|
||||
.veryTallItem {
|
||||
width: 15px;
|
||||
height: 40px;
|
||||
background: olive;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- FIRST ROW: -->
|
||||
<!-- One collapsed flex item, at the beginning of a flex line, which
|
||||
ends up establishing its flex line's cross size: -->
|
||||
<div class="flexContainer">
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="halfWidthItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
</div>
|
||||
<!-- ...and now with it being at the end of that flex line: -->
|
||||
<div class="flexContainer">
|
||||
<div class="halfWidthItem"></div>
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
<!-- SECOND ROW: -->
|
||||
<!-- One collapsed flex item, initially in its own line. It ends
|
||||
up being merged into another line after it collapses, due to its
|
||||
(post-collapse) zero main-size. -->
|
||||
<div class="flexContainer">
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
</div>
|
||||
<div class="flexContainer">
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
</div>
|
||||
<div class="flexContainer">
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="collapsedItem"></div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
<!-- THIRD ROW: -->
|
||||
<!-- One collapsed flex item, initially in a line with an even-taller item.
|
||||
The collapsed item ends up shifting into another line after it
|
||||
collapses, but it carries the taller item's cross size with it, as its
|
||||
strut size. -->
|
||||
<div class="flexContainer">
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="collapsedItem" style="height: 40px"></div>
|
||||
<div class="veryTallItem"></div>
|
||||
</div>
|
||||
<!-- ...and now with two (differently-sized) struts in first line:
|
||||
(the one that's taller - due to being initially grouped with the tall
|
||||
item - wins out.) -->
|
||||
<div class="flexContainer">
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="collapsedItem" style="height: 40px"></div>
|
||||
<div class="veryTallItem"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,111 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: Testing that visibility:collapse on a flex item in a multi-line flex container creates struts, and that they can migrate between lines</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<link rel="help" href="http://www.w3.org/TR/css3-flexbox/#algo-visibility">
|
||||
<link rel="match" href="flexbox-collapsed-item-horiz-2-ref.html">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
/* These let us show where each flex line begins (and hence, how tall
|
||||
the flex lines end up) */
|
||||
align-content: flex-start;
|
||||
align-items: flex-start;
|
||||
|
||||
width: 30px;
|
||||
background: yellow;
|
||||
border: 1px dotted black;
|
||||
float: left;
|
||||
margin: 5px;
|
||||
}
|
||||
.collapsedItem {
|
||||
visibility: collapse;
|
||||
width: 15px;
|
||||
height: 25px;
|
||||
}
|
||||
.halfWidthItem {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background: teal;
|
||||
}
|
||||
.fullWidthItem {
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
background: purple;
|
||||
}
|
||||
.veryTallItem {
|
||||
width: 15px;
|
||||
height: 40px;
|
||||
background: olive;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- FIRST ROW: -->
|
||||
<!-- One collapsed flex item, at the beginning of a flex line, which
|
||||
ends up establishing its flex line's cross size: -->
|
||||
<div class="flexContainer">
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="halfWidthItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
</div>
|
||||
<!-- ...and now with it being at the end of that flex line: -->
|
||||
<div class="flexContainer">
|
||||
<div class="halfWidthItem"></div>
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
<!-- SECOND ROW: -->
|
||||
<!-- One collapsed flex item, initially in its own line. It ends
|
||||
up being merged into another line after it collapses, due to its
|
||||
(post-collapse) zero main-size. -->
|
||||
<div class="flexContainer">
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
</div>
|
||||
<div class="flexContainer">
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
</div>
|
||||
<div class="flexContainer">
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="collapsedItem"></div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
<!-- THIRD ROW: -->
|
||||
<!-- One collapsed flex item, initially in a line with an even-taller item.
|
||||
The collapsed item ends up shifting into another line after it
|
||||
collapses, but it carries the taller item's cross size with it, as its
|
||||
strut size. -->
|
||||
<div class="flexContainer">
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="veryTallItem"></div>
|
||||
</div>
|
||||
<!-- ...and now with two (differently-sized) struts in first line:
|
||||
(the one that's taller - due to being initially grouped with the tall
|
||||
item - wins out.) -->
|
||||
<div class="flexContainer">
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="fullWidthItem"></div>
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="veryTallItem"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Reftest Reference</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: stretch; /* Initial value; just here for emphasis */
|
||||
width: 25px;
|
||||
height: 60px;
|
||||
background: yellow;
|
||||
border: 1px dotted black;
|
||||
float: left;
|
||||
margin: 5px;
|
||||
}
|
||||
.collapsedItem {
|
||||
width: 0;
|
||||
height: 40px;
|
||||
}
|
||||
.shortItem {
|
||||
width: 25px;
|
||||
height: 10px;
|
||||
background: purple;
|
||||
}
|
||||
.tallItem {
|
||||
width: 10px;
|
||||
height: 30px;
|
||||
background: olive;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="flexContainer">
|
||||
<div class="shortItem"></div>
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="tallItem"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: Testing that strut formation (from visibility:collapse) happens *after* lines have been stretched</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<link rel="help" href="http://www.w3.org/TR/css3-flexbox/#algo-visibility">
|
||||
<link rel="match" href="flexbox-collapsed-item-horiz-3-ref.html">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: stretch; /* Initial value; just here for emphasis */
|
||||
width: 25px;
|
||||
height: 60px;
|
||||
background: yellow;
|
||||
border: 1px dotted black;
|
||||
float: left;
|
||||
margin: 5px;
|
||||
}
|
||||
.collapsedItem {
|
||||
visibility: collapse;
|
||||
width: 10px;
|
||||
}
|
||||
.shortItem {
|
||||
width: 25px;
|
||||
height: 10px;
|
||||
background: purple;
|
||||
}
|
||||
.tallItem {
|
||||
width: 10px;
|
||||
height: 30px;
|
||||
background: olive;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- In this testcase, the first flex line initially has a cross-size of
|
||||
10px, and the second flex line has a cross-size of 30px. Both lines are
|
||||
stretched by 10px each (to hit the container's total cross-size, 60px).
|
||||
Then, we handle "visibility:collapse" and convert the collapsed item
|
||||
into a strut with the second line's stretched cross-size (40px), and we
|
||||
restart flex layout. This strut then ends up in the *first* line (since
|
||||
it has 0 main-size), which means both flex lines end up being 40px tall.
|
||||
-->
|
||||
<div class="flexContainer">
|
||||
<div class="shortItem"></div>
|
||||
<div class="collapsedItem"></div>
|
||||
<div class="tallItem"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -77,6 +77,12 @@ fuzzy-if(Android,158,32) == flexbox-align-self-vert-rtl-1.xhtml flexbox-align-s
|
||||
== flexbox-break-request-vert-2a.html flexbox-break-request-vert-2-ref.html
|
||||
== flexbox-break-request-vert-2b.html flexbox-break-request-vert-2-ref.html
|
||||
|
||||
# Tests for flex items with "visibility:collapse"
|
||||
== flexbox-collapsed-item-baseline-1.html flexbox-collapsed-item-baseline-1-ref.html
|
||||
== flexbox-collapsed-item-horiz-1.html flexbox-collapsed-item-horiz-1-ref.html
|
||||
== flexbox-collapsed-item-horiz-2.html flexbox-collapsed-item-horiz-2-ref.html
|
||||
== flexbox-collapsed-item-horiz-3.html flexbox-collapsed-item-horiz-3-ref.html
|
||||
|
||||
# Tests for flex-flow shorthand property
|
||||
== flexbox-flex-flow-1.html flexbox-flex-flow-1-ref.html
|
||||
|
||||
|
@ -1,41 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/include \
|
||||
-I$(srcdir)/celt \
|
||||
-I$(srcdir)/silk \
|
||||
-I$(srcdir)/src \
|
||||
$(NULL)
|
||||
|
||||
VPATH += \
|
||||
$(srcdir)/celt \
|
||||
$(srcdir)/silk \
|
||||
$(srcdir)/src \
|
||||
$(NULL)
|
||||
|
||||
include $(srcdir)/celt_sources.mk
|
||||
include $(srcdir)/silk_sources.mk
|
||||
include $(srcdir)/opus_sources.mk
|
||||
|
||||
CSRCS = \
|
||||
$(notdir $(CELT_SOURCES)) \
|
||||
$(notdir $(SILK_SOURCES)) \
|
||||
$(notdir $(OPUS_SOURCES)) \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_SAMPLE_TYPE_FLOAT32
|
||||
MOZ_OPUS_FIXED = 1
|
||||
endif
|
||||
|
||||
ifdef MOZ_OPUS_FIXED
|
||||
LOCAL_INCLUDES += -I$(srcdir)/silk/fixed
|
||||
VPATH += $(srcdir)/silk/fixed
|
||||
CSRCS += $(notdir $(SILK_SOURCES_FIXED))
|
||||
else
|
||||
LOCAL_INCLUDES += -I$(srcdir)/silk/float
|
||||
VPATH += $(srcdir)/silk/float
|
||||
CSRCS += $(notdir $(SILK_SOURCES_FLOAT)) \
|
||||
$(notdir $(OPUS_SOURCES_FLOAT))
|
||||
endif
|
@ -1,28 +0,0 @@
|
||||
CELT_SOURCES = celt/bands.c \
|
||||
celt/celt.c \
|
||||
celt/celt_encoder.c \
|
||||
celt/celt_decoder.c \
|
||||
celt/cwrs.c \
|
||||
celt/entcode.c \
|
||||
celt/entdec.c \
|
||||
celt/entenc.c \
|
||||
celt/kiss_fft.c \
|
||||
celt/laplace.c \
|
||||
celt/mathops.c \
|
||||
celt/mdct.c \
|
||||
celt/modes.c \
|
||||
celt/pitch.c \
|
||||
celt/celt_lpc.c \
|
||||
celt/quant_bands.c \
|
||||
celt/rate.c \
|
||||
celt/vq.c
|
||||
|
||||
CELT_SOURCES_ARM = \
|
||||
celt/arm/armcpu.c \
|
||||
celt/arm/arm_celt_map.c
|
||||
|
||||
CELT_SOURCES_ARM_ASM = \
|
||||
celt/arm/celt_pitch_xcorr_arm.s
|
||||
|
||||
CELT_AM_SOURCES_ARM_ASM = \
|
||||
celt/arm/armopts.s.in
|
70
media/libopus/gen-sources.py
Normal file
70
media/libopus/gen-sources.py
Normal file
@ -0,0 +1,70 @@
|
||||
# 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/.
|
||||
|
||||
# This file takes the .mk files from an upstream opus repo and generates the
|
||||
# sources.mozbuild file. It is invoked as part of update.sh
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
||||
def add_value(values, text):
|
||||
text = text.replace('\\', '')
|
||||
text = text.strip()
|
||||
if text:
|
||||
values.append(text)
|
||||
|
||||
def write_values(output, values):
|
||||
for value in sorted(values, key=lambda x: x.lower()):
|
||||
output.write(" '%s',\n" % value)
|
||||
output.write(']\n\n')
|
||||
|
||||
def generate_sources_mozbuild(path):
|
||||
makefiles = [
|
||||
'celt_sources.mk',
|
||||
'opus_sources.mk',
|
||||
'silk_sources.mk',
|
||||
]
|
||||
|
||||
var_definition = re.compile('([A-Z_]*) = (.*)')
|
||||
with open('sources.mozbuild', 'w') as output:
|
||||
|
||||
output.write('# THIS FILE WAS AUTOMATICALLY GENERATED BY %s. DO NOT EDIT.\n' % sys.argv[0])
|
||||
for makefile in makefiles:
|
||||
values = []
|
||||
definition_started = False
|
||||
|
||||
with open('%s/%s' % (path, makefile), 'r') as mk:
|
||||
for line in mk:
|
||||
line = line.rstrip()
|
||||
result = var_definition.match(line)
|
||||
if result:
|
||||
if definition_started:
|
||||
write_values(output, values)
|
||||
values = []
|
||||
definition_started = True
|
||||
|
||||
# Some variable definitions have the first entry on the
|
||||
# first line. Eg:
|
||||
#
|
||||
# CELT_SOURCES = celt/bands.c
|
||||
#
|
||||
# So we treat the first group as the variable name and
|
||||
# the second group as a potential value.
|
||||
#
|
||||
# Note that we write the variable name in lower case (so
|
||||
# "CELT_SOURCES" in the .mk file becomes "celt_sources"
|
||||
# in the .mozbuild file) because moz.build reserves
|
||||
# upper-case variable names for build system outputs.
|
||||
output.write('%s = [\n' % result.group(1).lower())
|
||||
add_value(values, result.group(2))
|
||||
else:
|
||||
add_value(values, line)
|
||||
write_values(output, values)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) != 2:
|
||||
print "Usage: %s /path/to/opus" % (sys.argv[0])
|
||||
sys.exit(1)
|
||||
|
||||
generate_sources_mozbuild(sys.argv[1])
|
@ -37,3 +37,30 @@ if CONFIG['OS_ARCH'] == 'SunOS':
|
||||
if not CONFIG['MOZ_SAMPLE_TYPE_FLOAT32']:
|
||||
DEFINES['FIXED_POINT'] = 1
|
||||
DEFINES['DISABLE_FLOAT_API'] = True
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'celt',
|
||||
'include',
|
||||
'silk',
|
||||
'src',
|
||||
]
|
||||
|
||||
# sources.mozbuild is generated from gen-sources.py when a new libopus is
|
||||
# imported.
|
||||
include('sources.mozbuild')
|
||||
|
||||
SOURCES += celt_sources
|
||||
SOURCES += silk_sources
|
||||
SOURCES += opus_sources
|
||||
|
||||
if CONFIG['MOZ_SAMPLE_TYPE_FLOAT32']:
|
||||
LOCAL_INCLUDES += [
|
||||
'silk/float',
|
||||
]
|
||||
SOURCES += silk_sources_float
|
||||
SOURCES += opus_sources_float
|
||||
else:
|
||||
LOCAL_INCLUDES += [
|
||||
'silk/fixed',
|
||||
]
|
||||
SOURCES += silk_sources_fixed
|
||||
|
@ -1,12 +0,0 @@
|
||||
OPUS_SOURCES = src/opus.c \
|
||||
src/opus_decoder.c \
|
||||
src/opus_encoder.c \
|
||||
src/opus_multistream.c \
|
||||
src/opus_multistream_encoder.c \
|
||||
src/opus_multistream_decoder.c \
|
||||
src/repacketizer.c
|
||||
|
||||
OPUS_SOURCES_FLOAT = \
|
||||
src/analysis.c \
|
||||
src/mlp.c \
|
||||
src/mlp_data.c
|
@ -1,138 +0,0 @@
|
||||
SILK_SOURCES = \
|
||||
silk/CNG.c \
|
||||
silk/code_signs.c \
|
||||
silk/init_decoder.c \
|
||||
silk/decode_core.c \
|
||||
silk/decode_frame.c \
|
||||
silk/decode_parameters.c \
|
||||
silk/decode_indices.c \
|
||||
silk/decode_pulses.c \
|
||||
silk/decoder_set_fs.c \
|
||||
silk/dec_API.c \
|
||||
silk/enc_API.c \
|
||||
silk/encode_indices.c \
|
||||
silk/encode_pulses.c \
|
||||
silk/gain_quant.c \
|
||||
silk/interpolate.c \
|
||||
silk/LP_variable_cutoff.c \
|
||||
silk/NLSF_decode.c \
|
||||
silk/NSQ.c \
|
||||
silk/NSQ_del_dec.c \
|
||||
silk/PLC.c \
|
||||
silk/shell_coder.c \
|
||||
silk/tables_gain.c \
|
||||
silk/tables_LTP.c \
|
||||
silk/tables_NLSF_CB_NB_MB.c \
|
||||
silk/tables_NLSF_CB_WB.c \
|
||||
silk/tables_other.c \
|
||||
silk/tables_pitch_lag.c \
|
||||
silk/tables_pulses_per_block.c \
|
||||
silk/VAD.c \
|
||||
silk/control_audio_bandwidth.c \
|
||||
silk/quant_LTP_gains.c \
|
||||
silk/VQ_WMat_EC.c \
|
||||
silk/HP_variable_cutoff.c \
|
||||
silk/NLSF_encode.c \
|
||||
silk/NLSF_VQ.c \
|
||||
silk/NLSF_unpack.c \
|
||||
silk/NLSF_del_dec_quant.c \
|
||||
silk/process_NLSFs.c \
|
||||
silk/stereo_LR_to_MS.c \
|
||||
silk/stereo_MS_to_LR.c \
|
||||
silk/check_control_input.c \
|
||||
silk/control_SNR.c \
|
||||
silk/init_encoder.c \
|
||||
silk/control_codec.c \
|
||||
silk/A2NLSF.c \
|
||||
silk/ana_filt_bank_1.c \
|
||||
silk/biquad_alt.c \
|
||||
silk/bwexpander_32.c \
|
||||
silk/bwexpander.c \
|
||||
silk/debug.c \
|
||||
silk/decode_pitch.c \
|
||||
silk/inner_prod_aligned.c \
|
||||
silk/lin2log.c \
|
||||
silk/log2lin.c \
|
||||
silk/LPC_analysis_filter.c \
|
||||
silk/LPC_inv_pred_gain.c \
|
||||
silk/table_LSF_cos.c \
|
||||
silk/NLSF2A.c \
|
||||
silk/NLSF_stabilize.c \
|
||||
silk/NLSF_VQ_weights_laroia.c \
|
||||
silk/pitch_est_tables.c \
|
||||
silk/resampler.c \
|
||||
silk/resampler_down2_3.c \
|
||||
silk/resampler_down2.c \
|
||||
silk/resampler_private_AR2.c \
|
||||
silk/resampler_private_down_FIR.c \
|
||||
silk/resampler_private_IIR_FIR.c \
|
||||
silk/resampler_private_up2_HQ.c \
|
||||
silk/resampler_rom.c \
|
||||
silk/sigm_Q15.c \
|
||||
silk/sort.c \
|
||||
silk/sum_sqr_shift.c \
|
||||
silk/stereo_decode_pred.c \
|
||||
silk/stereo_encode_pred.c \
|
||||
silk/stereo_find_predictor.c \
|
||||
silk/stereo_quant_pred.c
|
||||
|
||||
|
||||
SILK_SOURCES_FIXED = \
|
||||
silk/fixed/LTP_analysis_filter_FIX.c \
|
||||
silk/fixed/LTP_scale_ctrl_FIX.c \
|
||||
silk/fixed/corrMatrix_FIX.c \
|
||||
silk/fixed/encode_frame_FIX.c \
|
||||
silk/fixed/find_LPC_FIX.c \
|
||||
silk/fixed/find_LTP_FIX.c \
|
||||
silk/fixed/find_pitch_lags_FIX.c \
|
||||
silk/fixed/find_pred_coefs_FIX.c \
|
||||
silk/fixed/noise_shape_analysis_FIX.c \
|
||||
silk/fixed/prefilter_FIX.c \
|
||||
silk/fixed/process_gains_FIX.c \
|
||||
silk/fixed/regularize_correlations_FIX.c \
|
||||
silk/fixed/residual_energy16_FIX.c \
|
||||
silk/fixed/residual_energy_FIX.c \
|
||||
silk/fixed/solve_LS_FIX.c \
|
||||
silk/fixed/warped_autocorrelation_FIX.c \
|
||||
silk/fixed/apply_sine_window_FIX.c \
|
||||
silk/fixed/autocorr_FIX.c \
|
||||
silk/fixed/burg_modified_FIX.c \
|
||||
silk/fixed/k2a_FIX.c \
|
||||
silk/fixed/k2a_Q16_FIX.c \
|
||||
silk/fixed/pitch_analysis_core_FIX.c \
|
||||
silk/fixed/vector_ops_FIX.c \
|
||||
silk/fixed/schur64_FIX.c \
|
||||
silk/fixed/schur_FIX.c
|
||||
|
||||
SILK_SOURCES_FLOAT = \
|
||||
silk/float/apply_sine_window_FLP.c \
|
||||
silk/float/corrMatrix_FLP.c \
|
||||
silk/float/encode_frame_FLP.c \
|
||||
silk/float/find_LPC_FLP.c \
|
||||
silk/float/find_LTP_FLP.c \
|
||||
silk/float/find_pitch_lags_FLP.c \
|
||||
silk/float/find_pred_coefs_FLP.c \
|
||||
silk/float/LPC_analysis_filter_FLP.c \
|
||||
silk/float/LTP_analysis_filter_FLP.c \
|
||||
silk/float/LTP_scale_ctrl_FLP.c \
|
||||
silk/float/noise_shape_analysis_FLP.c \
|
||||
silk/float/prefilter_FLP.c \
|
||||
silk/float/process_gains_FLP.c \
|
||||
silk/float/regularize_correlations_FLP.c \
|
||||
silk/float/residual_energy_FLP.c \
|
||||
silk/float/solve_LS_FLP.c \
|
||||
silk/float/warped_autocorrelation_FLP.c \
|
||||
silk/float/wrappers_FLP.c \
|
||||
silk/float/autocorrelation_FLP.c \
|
||||
silk/float/burg_modified_FLP.c \
|
||||
silk/float/bwexpander_FLP.c \
|
||||
silk/float/energy_FLP.c \
|
||||
silk/float/inner_product_FLP.c \
|
||||
silk/float/k2a_FLP.c \
|
||||
silk/float/levinsondurbin_FLP.c \
|
||||
silk/float/LPC_inv_pred_gain_FLP.c \
|
||||
silk/float/pitch_analysis_core_FLP.c \
|
||||
silk/float/scale_copy_vector_FLP.c \
|
||||
silk/float/scale_vector_FLP.c \
|
||||
silk/float/schur_FLP.c \
|
||||
silk/float/sort_FLP.c
|
192
media/libopus/sources.mozbuild
Normal file
192
media/libopus/sources.mozbuild
Normal file
@ -0,0 +1,192 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED BY gen-sources.py. DO NOT EDIT.
|
||||
celt_sources = [
|
||||
'celt/bands.c',
|
||||
'celt/celt.c',
|
||||
'celt/celt_decoder.c',
|
||||
'celt/celt_encoder.c',
|
||||
'celt/celt_lpc.c',
|
||||
'celt/cwrs.c',
|
||||
'celt/entcode.c',
|
||||
'celt/entdec.c',
|
||||
'celt/entenc.c',
|
||||
'celt/kiss_fft.c',
|
||||
'celt/laplace.c',
|
||||
'celt/mathops.c',
|
||||
'celt/mdct.c',
|
||||
'celt/modes.c',
|
||||
'celt/pitch.c',
|
||||
'celt/quant_bands.c',
|
||||
'celt/rate.c',
|
||||
'celt/vq.c',
|
||||
]
|
||||
|
||||
celt_sources_arm = [
|
||||
'celt/arm/arm_celt_map.c',
|
||||
'celt/arm/armcpu.c',
|
||||
]
|
||||
|
||||
celt_sources_arm_asm = [
|
||||
'celt/arm/celt_pitch_xcorr_arm.s',
|
||||
]
|
||||
|
||||
celt_am_sources_arm_asm = [
|
||||
'celt/arm/armopts.s.in',
|
||||
]
|
||||
|
||||
opus_sources = [
|
||||
'src/opus.c',
|
||||
'src/opus_decoder.c',
|
||||
'src/opus_encoder.c',
|
||||
'src/opus_multistream.c',
|
||||
'src/opus_multistream_decoder.c',
|
||||
'src/opus_multistream_encoder.c',
|
||||
'src/repacketizer.c',
|
||||
]
|
||||
|
||||
opus_sources_float = [
|
||||
'src/analysis.c',
|
||||
'src/mlp.c',
|
||||
'src/mlp_data.c',
|
||||
]
|
||||
|
||||
silk_sources = [
|
||||
'silk/A2NLSF.c',
|
||||
'silk/ana_filt_bank_1.c',
|
||||
'silk/biquad_alt.c',
|
||||
'silk/bwexpander.c',
|
||||
'silk/bwexpander_32.c',
|
||||
'silk/check_control_input.c',
|
||||
'silk/CNG.c',
|
||||
'silk/code_signs.c',
|
||||
'silk/control_audio_bandwidth.c',
|
||||
'silk/control_codec.c',
|
||||
'silk/control_SNR.c',
|
||||
'silk/debug.c',
|
||||
'silk/dec_API.c',
|
||||
'silk/decode_core.c',
|
||||
'silk/decode_frame.c',
|
||||
'silk/decode_indices.c',
|
||||
'silk/decode_parameters.c',
|
||||
'silk/decode_pitch.c',
|
||||
'silk/decode_pulses.c',
|
||||
'silk/decoder_set_fs.c',
|
||||
'silk/enc_API.c',
|
||||
'silk/encode_indices.c',
|
||||
'silk/encode_pulses.c',
|
||||
'silk/gain_quant.c',
|
||||
'silk/HP_variable_cutoff.c',
|
||||
'silk/init_decoder.c',
|
||||
'silk/init_encoder.c',
|
||||
'silk/inner_prod_aligned.c',
|
||||
'silk/interpolate.c',
|
||||
'silk/lin2log.c',
|
||||
'silk/log2lin.c',
|
||||
'silk/LP_variable_cutoff.c',
|
||||
'silk/LPC_analysis_filter.c',
|
||||
'silk/LPC_inv_pred_gain.c',
|
||||
'silk/NLSF2A.c',
|
||||
'silk/NLSF_decode.c',
|
||||
'silk/NLSF_del_dec_quant.c',
|
||||
'silk/NLSF_encode.c',
|
||||
'silk/NLSF_stabilize.c',
|
||||
'silk/NLSF_unpack.c',
|
||||
'silk/NLSF_VQ.c',
|
||||
'silk/NLSF_VQ_weights_laroia.c',
|
||||
'silk/NSQ.c',
|
||||
'silk/NSQ_del_dec.c',
|
||||
'silk/pitch_est_tables.c',
|
||||
'silk/PLC.c',
|
||||
'silk/process_NLSFs.c',
|
||||
'silk/quant_LTP_gains.c',
|
||||
'silk/resampler.c',
|
||||
'silk/resampler_down2.c',
|
||||
'silk/resampler_down2_3.c',
|
||||
'silk/resampler_private_AR2.c',
|
||||
'silk/resampler_private_down_FIR.c',
|
||||
'silk/resampler_private_IIR_FIR.c',
|
||||
'silk/resampler_private_up2_HQ.c',
|
||||
'silk/resampler_rom.c',
|
||||
'silk/shell_coder.c',
|
||||
'silk/sigm_Q15.c',
|
||||
'silk/sort.c',
|
||||
'silk/stereo_decode_pred.c',
|
||||
'silk/stereo_encode_pred.c',
|
||||
'silk/stereo_find_predictor.c',
|
||||
'silk/stereo_LR_to_MS.c',
|
||||
'silk/stereo_MS_to_LR.c',
|
||||
'silk/stereo_quant_pred.c',
|
||||
'silk/sum_sqr_shift.c',
|
||||
'silk/table_LSF_cos.c',
|
||||
'silk/tables_gain.c',
|
||||
'silk/tables_LTP.c',
|
||||
'silk/tables_NLSF_CB_NB_MB.c',
|
||||
'silk/tables_NLSF_CB_WB.c',
|
||||
'silk/tables_other.c',
|
||||
'silk/tables_pitch_lag.c',
|
||||
'silk/tables_pulses_per_block.c',
|
||||
'silk/VAD.c',
|
||||
'silk/VQ_WMat_EC.c',
|
||||
]
|
||||
|
||||
silk_sources_fixed = [
|
||||
'silk/fixed/apply_sine_window_FIX.c',
|
||||
'silk/fixed/autocorr_FIX.c',
|
||||
'silk/fixed/burg_modified_FIX.c',
|
||||
'silk/fixed/corrMatrix_FIX.c',
|
||||
'silk/fixed/encode_frame_FIX.c',
|
||||
'silk/fixed/find_LPC_FIX.c',
|
||||
'silk/fixed/find_LTP_FIX.c',
|
||||
'silk/fixed/find_pitch_lags_FIX.c',
|
||||
'silk/fixed/find_pred_coefs_FIX.c',
|
||||
'silk/fixed/k2a_FIX.c',
|
||||
'silk/fixed/k2a_Q16_FIX.c',
|
||||
'silk/fixed/LTP_analysis_filter_FIX.c',
|
||||
'silk/fixed/LTP_scale_ctrl_FIX.c',
|
||||
'silk/fixed/noise_shape_analysis_FIX.c',
|
||||
'silk/fixed/pitch_analysis_core_FIX.c',
|
||||
'silk/fixed/prefilter_FIX.c',
|
||||
'silk/fixed/process_gains_FIX.c',
|
||||
'silk/fixed/regularize_correlations_FIX.c',
|
||||
'silk/fixed/residual_energy16_FIX.c',
|
||||
'silk/fixed/residual_energy_FIX.c',
|
||||
'silk/fixed/schur64_FIX.c',
|
||||
'silk/fixed/schur_FIX.c',
|
||||
'silk/fixed/solve_LS_FIX.c',
|
||||
'silk/fixed/vector_ops_FIX.c',
|
||||
'silk/fixed/warped_autocorrelation_FIX.c',
|
||||
]
|
||||
|
||||
silk_sources_float = [
|
||||
'silk/float/apply_sine_window_FLP.c',
|
||||
'silk/float/autocorrelation_FLP.c',
|
||||
'silk/float/burg_modified_FLP.c',
|
||||
'silk/float/bwexpander_FLP.c',
|
||||
'silk/float/corrMatrix_FLP.c',
|
||||
'silk/float/encode_frame_FLP.c',
|
||||
'silk/float/energy_FLP.c',
|
||||
'silk/float/find_LPC_FLP.c',
|
||||
'silk/float/find_LTP_FLP.c',
|
||||
'silk/float/find_pitch_lags_FLP.c',
|
||||
'silk/float/find_pred_coefs_FLP.c',
|
||||
'silk/float/inner_product_FLP.c',
|
||||
'silk/float/k2a_FLP.c',
|
||||
'silk/float/levinsondurbin_FLP.c',
|
||||
'silk/float/LPC_analysis_filter_FLP.c',
|
||||
'silk/float/LPC_inv_pred_gain_FLP.c',
|
||||
'silk/float/LTP_analysis_filter_FLP.c',
|
||||
'silk/float/LTP_scale_ctrl_FLP.c',
|
||||
'silk/float/noise_shape_analysis_FLP.c',
|
||||
'silk/float/pitch_analysis_core_FLP.c',
|
||||
'silk/float/prefilter_FLP.c',
|
||||
'silk/float/process_gains_FLP.c',
|
||||
'silk/float/regularize_correlations_FLP.c',
|
||||
'silk/float/residual_energy_FLP.c',
|
||||
'silk/float/scale_copy_vector_FLP.c',
|
||||
'silk/float/scale_vector_FLP.c',
|
||||
'silk/float/schur_FLP.c',
|
||||
'silk/float/solve_LS_FLP.c',
|
||||
'silk/float/sort_FLP.c',
|
||||
'silk/float/warped_autocorrelation_FLP.c',
|
||||
'silk/float/wrappers_FLP.c',
|
||||
]
|
||||
|
@ -43,7 +43,7 @@ for file in ${SRC_FILES}; do
|
||||
done
|
||||
|
||||
# copy files into the target directory
|
||||
for file in ${STATIC_FILES} ${MK_FILES} ${SRC_FILES} ${HDR_FILES}; do
|
||||
for file in ${STATIC_FILES} ${SRC_FILES} ${HDR_FILES}; do
|
||||
cmd="cp $1/${file} ${TARGET}/${file}"
|
||||
echo ${cmd}
|
||||
${cmd}
|
||||
@ -65,5 +65,7 @@ sed -e "s/DEFINES\['OPUS_VERSION'\][ \t]*=[ \t]*'\".*\"'/DEFINES['OPUS_VERSION']
|
||||
${TARGET}/moz.build > ${TARGET}/moz.build+ && \
|
||||
mv ${TARGET}/moz.build+ ${TARGET}/moz.build
|
||||
|
||||
python gen-sources.py $1
|
||||
|
||||
# apply outstanding local patches
|
||||
# ... no patches to apply ...
|
||||
|
@ -485,22 +485,16 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
||||
}
|
||||
|
||||
switch (msg) {
|
||||
case TITLE:
|
||||
flags.add(UpdateFlags.TITLE);
|
||||
break;
|
||||
|
||||
case START:
|
||||
updateBackButton(tab);
|
||||
updateForwardButton(tab);
|
||||
break;
|
||||
|
||||
case STOP:
|
||||
updateBackButton(tab);
|
||||
updateForwardButton(tab);
|
||||
|
||||
// Reset the title in case we haven't navigated
|
||||
// to a new page yet.
|
||||
flags.add(UpdateFlags.TITLE);
|
||||
// Fall through.
|
||||
case START:
|
||||
case CLOSED:
|
||||
case ADDED:
|
||||
updateBackButton(tab);
|
||||
updateForwardButton(tab);
|
||||
break;
|
||||
|
||||
case SELECTED:
|
||||
@ -510,13 +504,18 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
||||
case LOCATION_CHANGE:
|
||||
// A successful location change will cause Tab to notify
|
||||
// us of a title change, so we don't update the title here.
|
||||
refreshState();
|
||||
break;
|
||||
flags.add(UpdateFlags.FAVICON);
|
||||
flags.add(UpdateFlags.SITE_IDENTITY);
|
||||
flags.add(UpdateFlags.PRIVATE_MODE);
|
||||
|
||||
case CLOSED:
|
||||
case ADDED:
|
||||
updateBackButton(tab);
|
||||
updateForwardButton(tab);
|
||||
|
||||
setPrivateMode(tab.isPrivate());
|
||||
break;
|
||||
|
||||
case TITLE:
|
||||
flags.add(UpdateFlags.TITLE);
|
||||
break;
|
||||
|
||||
case FAVICON:
|
||||
@ -1249,6 +1248,24 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
||||
mActionItemBar.removeView(actionItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrivateMode(boolean isPrivate) {
|
||||
super.setPrivateMode(isPrivate);
|
||||
|
||||
mTabs.setPrivateMode(isPrivate);
|
||||
mMenu.setPrivateMode(isPrivate);
|
||||
mMenuIcon.setPrivateMode(isPrivate);
|
||||
mUrlEditLayout.setPrivateMode(isPrivate);
|
||||
|
||||
if (mBack instanceof BackButton) {
|
||||
((BackButton) mBack).setPrivateMode(isPrivate);
|
||||
}
|
||||
|
||||
if (mForward instanceof ForwardButton) {
|
||||
((ForwardButton) mForward).setPrivateMode(isPrivate);
|
||||
}
|
||||
}
|
||||
|
||||
public void show() {
|
||||
setVisibility(View.VISIBLE);
|
||||
}
|
||||
@ -1257,30 +1274,6 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
||||
setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void refreshState() {
|
||||
Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
if (tab != null) {
|
||||
updateDisplayLayout(tab, EnumSet.of(UpdateFlags.FAVICON,
|
||||
UpdateFlags.SITE_IDENTITY,
|
||||
UpdateFlags.PRIVATE_MODE));
|
||||
updateBackButton(tab);
|
||||
updateForwardButton(tab);
|
||||
|
||||
final boolean isPrivate = tab.isPrivate();
|
||||
setPrivateMode(isPrivate);
|
||||
mTabs.setPrivateMode(isPrivate);
|
||||
mMenu.setPrivateMode(isPrivate);
|
||||
mMenuIcon.setPrivateMode(isPrivate);
|
||||
mUrlEditLayout.setPrivateMode(isPrivate);
|
||||
|
||||
if (mBack instanceof BackButton)
|
||||
((BackButton) mBack).setPrivateMode(isPrivate);
|
||||
|
||||
if (mForward instanceof ForwardButton)
|
||||
((ForwardButton) mForward).setPrivateMode(isPrivate);
|
||||
}
|
||||
}
|
||||
|
||||
public View getDoorHangerAnchor() {
|
||||
return mUrlDisplayLayout.getDoorHangerAnchor();
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
NSPR_4_10_3_BETA1
|
||||
NSPR_4_10_3_BETA2
|
||||
|
@ -10,3 +10,4 @@
|
||||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
@ -1856,7 +1856,11 @@ NSPR_API(PRStatus) PR_CloseFileMap(PRFileMap *fmap);
|
||||
|
||||
/*
|
||||
* Synchronously flush the given memory-mapped address range of the given open
|
||||
* file to disk.
|
||||
* file to disk. The function does not return until all modified data have
|
||||
* been written to disk.
|
||||
*
|
||||
* On some platforms, the function will call PR_Sync(fd) internally if it is
|
||||
* necessary for flushing modified data to disk synchronously.
|
||||
*/
|
||||
NSPR_API(PRStatus) PR_SyncMemMap(
|
||||
PRFileDesc *fd,
|
||||
|
@ -3614,14 +3614,9 @@ PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
|
||||
{
|
||||
if (munmap(addr, len) == 0) {
|
||||
return PR_SUCCESS;
|
||||
} else {
|
||||
if (errno == EINVAL) {
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, errno);
|
||||
} else {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, errno);
|
||||
}
|
||||
return PR_FAILURE;
|
||||
}
|
||||
_PR_MD_MAP_DEFAULT_ERROR(errno);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus _MD_CloseFileMap(PRFileMap *fmap)
|
||||
@ -3643,16 +3638,13 @@ PRStatus _MD_SyncMemMap(
|
||||
void *addr,
|
||||
PRUint32 len)
|
||||
{
|
||||
/* msync(..., MS_SYNC) alone is sufficient to flush modified data to disk
|
||||
* synchronously. It is not necessary to call fsync. */
|
||||
if (msync(addr, len, MS_SYNC) == 0) {
|
||||
return PR_SUCCESS;
|
||||
} else {
|
||||
if (errno == EINVAL) {
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, errno);
|
||||
} else {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, errno);
|
||||
}
|
||||
return PR_FAILURE;
|
||||
}
|
||||
_PR_MD_MAP_DEFAULT_ERROR(errno);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
#if defined(_PR_NEED_FAKE_POLL)
|
||||
|
@ -982,10 +982,9 @@ PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
|
||||
{
|
||||
if (UnmapViewOfFile(addr)) {
|
||||
return PR_SUCCESS;
|
||||
} else {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus _MD_CloseFileMap(PRFileMap *fmap)
|
||||
@ -1000,16 +999,18 @@ PRStatus _MD_SyncMemMap(
|
||||
void *addr,
|
||||
PRUint32 len)
|
||||
{
|
||||
PROsfd osfd;
|
||||
|
||||
osfd = ( fd == (PRFileDesc*)-1 )? -1 : fd->secret->md.osfd;
|
||||
PROsfd osfd = fd->secret->md.osfd;
|
||||
|
||||
/* The FlushViewOfFile page on MSDN says:
|
||||
* To flush all the dirty pages plus the metadata for the file and
|
||||
* ensure that they are physically written to disk, call
|
||||
* FlushViewOfFile and then call the FlushFileBuffers function.
|
||||
*/
|
||||
if (FlushViewOfFile(addr, len) && FlushFileBuffers((HANDLE) osfd)) {
|
||||
return PR_SUCCESS;
|
||||
} else {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -229,7 +229,6 @@ EXPORTS ;-
|
||||
PR_Malloc;
|
||||
PR_MemMap;
|
||||
PR_MemUnmap;
|
||||
PR_SyncMemMap;
|
||||
PR_MicrosecondsToInterval;
|
||||
PR_MillisecondsToInterval;
|
||||
PR_LockOrderedLock;
|
||||
@ -452,3 +451,7 @@ EXPORTS ;-
|
||||
PR_GetThreadName;
|
||||
PR_SetCurrentThreadName;
|
||||
;+} NSPR_4.8.9;
|
||||
;+NSPR_4.10.3 {
|
||||
;+ global:
|
||||
PR_SyncMemMap;
|
||||
;+} NSPR_4.9.2;
|
||||
|
@ -980,10 +980,11 @@ void _PR_InitThreads(
|
||||
* nothing.
|
||||
*/
|
||||
rv = _PT_PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death);
|
||||
if (0 != rv) PR_Abort();
|
||||
if (0 != rv)
|
||||
PR_Assert("0 == rv", __FILE__, __LINE__);
|
||||
pt_book.keyCreated = PR_TRUE;
|
||||
rv = pthread_setspecific(pt_book.key, thred);
|
||||
if (0 != rv) PR_Abort();
|
||||
PR_ASSERT(0 == rv);
|
||||
} /* _PR_InitThreads */
|
||||
|
||||
#ifdef __GNUC__
|
||||
@ -1048,7 +1049,8 @@ void _PR_Fini(void)
|
||||
* PR_Cleanup has been called already. */
|
||||
if (pt_book.keyCreated)
|
||||
{
|
||||
pthread_key_delete(pt_book.key);
|
||||
rv = pthread_key_delete(pt_book.key);
|
||||
PR_ASSERT(0 == rv);
|
||||
pt_book.keyCreated = PR_FALSE;
|
||||
}
|
||||
return;
|
||||
@ -1067,6 +1069,7 @@ void _PR_Fini(void)
|
||||
}
|
||||
rv = pthread_key_delete(pt_book.key);
|
||||
PR_ASSERT(0 == rv);
|
||||
pt_book.keyCreated = PR_FALSE;
|
||||
/* TODO: free other resources used by NSPR */
|
||||
/* _pr_initialized = PR_FALSE; */
|
||||
} /* _PR_Fini */
|
||||
|
@ -197,15 +197,15 @@ PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
|
||||
PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
|
||||
PR_ASSERT(lock != NULL);
|
||||
#ifdef _PR_GLOBAL_THREADS_ONLY
|
||||
PR_ASSERT(lock->owner != me);
|
||||
_PR_MD_LOCK(&lock->ilock);
|
||||
PR_ASSERT(lock->owner == 0);
|
||||
lock->owner = me;
|
||||
return;
|
||||
#else /* _PR_GLOBAL_THREADS_ONLY */
|
||||
|
||||
if (_native_threads_only) {
|
||||
PR_ASSERT(lock->owner != me);
|
||||
_PR_MD_LOCK(&lock->ilock);
|
||||
PR_ASSERT(lock->owner == 0);
|
||||
lock->owner = me;
|
||||
return;
|
||||
}
|
||||
|
@ -226,7 +226,8 @@ int err;
|
||||
/*
|
||||
* update thread's lock rank
|
||||
*/
|
||||
_PR_SET_THREAD_RWLOCK_RANK(rwlock);
|
||||
if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE)
|
||||
_PR_SET_THREAD_RWLOCK_RANK(rwlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -282,7 +283,8 @@ int err;
|
||||
/*
|
||||
* update thread's lock rank
|
||||
*/
|
||||
_PR_SET_THREAD_RWLOCK_RANK(rwlock);
|
||||
if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE)
|
||||
_PR_SET_THREAD_RWLOCK_RANK(rwlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -347,7 +349,8 @@ int err;
|
||||
/*
|
||||
* update thread's lock rank
|
||||
*/
|
||||
_PR_UNSET_THREAD_RWLOCK_RANK(rwlock);
|
||||
if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE)
|
||||
_PR_UNSET_THREAD_RWLOCK_RANK(rwlock);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@ -429,7 +432,8 @@ _PR_GET_THREAD_RWLOCK_RANK(void)
|
||||
{
|
||||
thread_rwlock_stack *lock_stack;
|
||||
|
||||
if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key)) == NULL)
|
||||
lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key);
|
||||
if (lock_stack == NULL || lock_stack->trs_index == 0)
|
||||
return (PR_RWLOCK_RANK_NONE);
|
||||
else
|
||||
return(lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank);
|
||||
@ -452,9 +456,8 @@ _PR_UNSET_THREAD_RWLOCK_RANK(PRRWLock *rwlock)
|
||||
|
||||
PR_ASSERT(lock_stack != NULL);
|
||||
|
||||
index = lock_stack->trs_index - 1;
|
||||
while (index-- >= 0) {
|
||||
if ((lock_stack->trs_stack[index] == rwlock) && !done) {
|
||||
for (index = lock_stack->trs_index - 1; index >= 0; index--) {
|
||||
if (!done && (lock_stack->trs_stack[index] == rwlock)) {
|
||||
/*
|
||||
* reset the slot for rwlock
|
||||
*/
|
||||
@ -465,7 +468,7 @@ _PR_UNSET_THREAD_RWLOCK_RANK(PRRWLock *rwlock)
|
||||
* search for the lowest-numbered empty slot, above which there are
|
||||
* no non-empty slots
|
||||
*/
|
||||
if ((lock_stack->trs_stack[index] != NULL) && !new_index)
|
||||
if (!new_index && (lock_stack->trs_stack[index] != NULL))
|
||||
new_index = index + 1;
|
||||
if (done && new_index)
|
||||
break;
|
||||
|
@ -119,6 +119,7 @@ CSRCS = \
|
||||
randseed.c \
|
||||
reinit.c \
|
||||
rmdir.c \
|
||||
rwlockrank.c \
|
||||
rwlocktest.c \
|
||||
sel_spd.c \
|
||||
selct_er.c \
|
||||
|
120
nsprpub/pr/tests/rwlockrank.c
Normal file
120
nsprpub/pr/tests/rwlockrank.c
Normal file
@ -0,0 +1,120 @@
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
* RWLock rank tests
|
||||
*/
|
||||
|
||||
#include "nspr.h"
|
||||
#include "plgetopt.h"
|
||||
|
||||
static int _debug_on;
|
||||
static PRRWLock *rwlock0;
|
||||
static PRRWLock *rwlock1;
|
||||
static PRRWLock *rwlock2;
|
||||
|
||||
static void rwtest(void *args)
|
||||
{
|
||||
PR_RWLock_Rlock(rwlock1);
|
||||
PR_RWLock_Unlock(rwlock1);
|
||||
|
||||
PR_RWLock_Rlock(rwlock1);
|
||||
PR_RWLock_Unlock(rwlock1);
|
||||
|
||||
// Test correct lock rank.
|
||||
PR_RWLock_Rlock(rwlock1);
|
||||
PR_RWLock_Rlock(rwlock2);
|
||||
PR_RWLock_Unlock(rwlock2);
|
||||
PR_RWLock_Unlock(rwlock1);
|
||||
|
||||
PR_RWLock_Rlock(rwlock1);
|
||||
PR_RWLock_Rlock(rwlock2);
|
||||
PR_RWLock_Unlock(rwlock1);
|
||||
PR_RWLock_Unlock(rwlock2);
|
||||
|
||||
PR_RWLock_Rlock(rwlock1);
|
||||
PR_RWLock_Rlock(rwlock0);
|
||||
PR_RWLock_Rlock(rwlock2);
|
||||
PR_RWLock_Unlock(rwlock2);
|
||||
PR_RWLock_Unlock(rwlock0);
|
||||
PR_RWLock_Unlock(rwlock1);
|
||||
|
||||
#if 0
|
||||
// Test incorrect lock rank.
|
||||
PR_RWLock_Rlock(rwlock2);
|
||||
PR_RWLock_Rlock(rwlock1);
|
||||
PR_RWLock_Unlock(rwlock1);
|
||||
PR_RWLock_Unlock(rwlock2);
|
||||
|
||||
PR_RWLock_Rlock(rwlock2);
|
||||
PR_RWLock_Rlock(rwlock0);
|
||||
PR_RWLock_Rlock(rwlock1);
|
||||
PR_RWLock_Unlock(rwlock1);
|
||||
PR_RWLock_Unlock(rwlock0);
|
||||
PR_RWLock_Unlock(rwlock2);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
PRStatus rc;
|
||||
PRThread *thread;
|
||||
PLOptStatus os;
|
||||
PLOptState *opt = PL_CreateOptState(argc, argv, "d");
|
||||
|
||||
while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
|
||||
if (PL_OPT_BAD == os) continue;
|
||||
switch (opt->option) {
|
||||
case 'd': /* debug mode */
|
||||
_debug_on = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
PL_DestroyOptState(opt);
|
||||
|
||||
rwlock0 = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "Lock 0");
|
||||
if (rwlock0 == NULL) {
|
||||
fprintf(stderr, "PR_NewRWLock failed - error %d\n",
|
||||
(int)PR_GetError());
|
||||
return 1;
|
||||
}
|
||||
rwlock1 = PR_NewRWLock(1, "Lock 1");
|
||||
if (rwlock1 == NULL) {
|
||||
fprintf(stderr, "PR_NewRWLock failed - error %d\n",
|
||||
(int)PR_GetError());
|
||||
return 1;
|
||||
}
|
||||
rwlock2 = PR_NewRWLock(2, "Lock 2");
|
||||
if (rwlock2 == NULL) {
|
||||
fprintf(stderr, "PR_NewRWLock failed - error %d\n",
|
||||
(int)PR_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
thread = PR_CreateThread(PR_USER_THREAD, rwtest, NULL, PR_PRIORITY_NORMAL,
|
||||
PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
|
||||
if (thread == NULL) {
|
||||
fprintf(stderr, "PR_CreateThread failed - error %d\n",
|
||||
(int)PR_GetError());
|
||||
PR_ProcessExit(2);
|
||||
}
|
||||
if (_debug_on) {
|
||||
printf("%s: created thread = %p\n", argv[0], thread);
|
||||
}
|
||||
|
||||
rc = PR_JoinThread(thread);
|
||||
PR_ASSERT(rc == PR_SUCCESS);
|
||||
|
||||
PR_DestroyRWLock(rwlock0);
|
||||
rwlock0 = NULL;
|
||||
PR_DestroyRWLock(rwlock1);
|
||||
rwlock1 = NULL;
|
||||
PR_DestroyRWLock(rwlock2);
|
||||
rwlock2 = NULL;
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
@ -132,7 +132,7 @@ int main(int argc, char **argv)
|
||||
PR_ProcessExit(2);
|
||||
}
|
||||
if (_debug_on)
|
||||
PR_fprintf(output,"%s: created thread = 0x%x\n", argv[0],
|
||||
PR_fprintf(output,"%s: created thread = %p\n", argv[0],
|
||||
threads[cnt]);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,10 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
import os
|
||||
import stat
|
||||
import platform
|
||||
import urllib2
|
||||
|
||||
from mach.decorators import (
|
||||
CommandArgument,
|
||||
@ -216,7 +220,6 @@ class PastebinProvider(object):
|
||||
def pastebin(self, language, poster, duration, file):
|
||||
import sys
|
||||
import urllib
|
||||
import urllib2
|
||||
|
||||
URL = 'http://pastebin.mozilla.org/'
|
||||
|
||||
@ -306,3 +309,69 @@ class ReviewboardToolsProvider(MachCommandBase):
|
||||
# we fake it out.
|
||||
sys.argv = ['rbt'] + args
|
||||
return main()
|
||||
|
||||
@CommandProvider
|
||||
class FormatProvider(MachCommandBase):
|
||||
@Command('clang-format', category='devenv', allow_all_args=True,
|
||||
description='Run clang-format on current changes')
|
||||
@CommandArgument('args', nargs='...', help='Arguments to clang-format tool')
|
||||
def clang_format(self, args):
|
||||
if not args:
|
||||
args = ['help']
|
||||
|
||||
fmt = "clang-format-3.5"
|
||||
fmt_diff = "clang-format-diff-3.5"
|
||||
|
||||
# We are currently using a modified verion of clang-format hosted on people.mozilla.org.
|
||||
# This is a temporary work around until we upstream the necessary changes and we can use
|
||||
# a system version of clang-format. See bug 961541.
|
||||
self.prompt = 1
|
||||
plat = platform.system()
|
||||
if plat == "Windows":
|
||||
fmt += ".exe"
|
||||
else:
|
||||
arch = os.uname()[4]
|
||||
if plat != "Linux" or arch != 'x86_64':
|
||||
print("Unsupported platform " + plat + "/" + arch +
|
||||
". Supported platforms are Windows/* and Linux/x86_64")
|
||||
return 1
|
||||
|
||||
os.chdir(self.topsrcdir)
|
||||
|
||||
try:
|
||||
if not self.locate_or_fetch(fmt):
|
||||
return 1
|
||||
clang_format_diff = self.locate_or_fetch(fmt_diff)
|
||||
if not clang_format_diff:
|
||||
return 1
|
||||
|
||||
except urllib2.HTTPError as e:
|
||||
print("HTTP error {0}: {1}".format(e.code, e.reason))
|
||||
return 1
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
p1 = Popen(["hg", "diff", "-U0", "-r", "tip^", "--include", "glob:**.c", "--include", "glob:**.cpp",
|
||||
"--include", "glob:**.h", "--exclude", "listfile:.clang-format-ignore"], stdout=PIPE)
|
||||
p2 = Popen([sys.executable, clang_format_diff, "-i", "-p1", "-style=Mozilla"], stdin=p1.stdout)
|
||||
return p2.communicate()[0]
|
||||
|
||||
def locate_or_fetch(self, root):
|
||||
target = os.path.join(self._mach_context.state_dir, root)
|
||||
if not os.path.exists(target):
|
||||
site = "http://people.mozilla.org/~ajones/clang-format/"
|
||||
if self.prompt and raw_input("Download clang-format executables from {0} (yN)? ".format(site)).lower() != 'y':
|
||||
print("Download aborted.")
|
||||
return 1
|
||||
self.prompt = 0
|
||||
|
||||
u = site + root
|
||||
print("Downloading {0} to {1}".format(u, target))
|
||||
data = urllib2.urlopen(url=u).read()
|
||||
temp = target + ".tmp"
|
||||
with open(temp, "wb") as fh:
|
||||
fh.write(data)
|
||||
fh.close()
|
||||
os.chmod(temp, os.stat(temp).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
||||
os.rename(temp, target)
|
||||
return target
|
||||
|
||||
|
@ -70,11 +70,9 @@ NS_IMETHODIMP nsColorPicker::Open(nsIColorPickerShownCallback *aColorPickerShown
|
||||
title.Adopt(ToNewUTF8String(mTitle));
|
||||
GtkWidget *color_chooser = gtk_color_selection_dialog_new(title);
|
||||
|
||||
GtkWindow *window = GTK_WINDOW(color_chooser);
|
||||
gtk_window_set_modal(window, TRUE);
|
||||
|
||||
GtkWindow *parent_window = GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET));
|
||||
if (parent_window) {
|
||||
GtkWindow *window = GTK_WINDOW(color_chooser);
|
||||
gtk_window_set_transient_for(window, parent_window);
|
||||
gtk_window_set_destroy_with_parent(window, TRUE);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user