зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to s-c, certainly nothing to do with Australis.
This commit is contained in:
Коммит
21a96f60c5
|
@ -0,0 +1,2 @@
|
|||
\mfbt/
|
||||
\js/
|
|
@ -12,7 +12,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8d18b1e2fd06c84a879f99f6e8ca1f104eeacb13"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a6f1bc96ac9e0a32022c75f0ee7771a2ab9050db"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8d18b1e2fd06c84a879f99f6e8ca1f104eeacb13"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a6f1bc96ac9e0a32022c75f0ee7771a2ab9050db"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="e2f73049f8d52fb06cb9b5d923c1280557aa9238"/>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8d18b1e2fd06c84a879f99f6e8ca1f104eeacb13"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a6f1bc96ac9e0a32022c75f0ee7771a2ab9050db"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "98abf6bda1c12b45389ec6bc2acd3e3e901e3163",
|
||||
"revision": "0f4f24675eee8a4211d2535a1cfa280365d581dc",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8d18b1e2fd06c84a879f99f6e8ca1f104eeacb13"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a6f1bc96ac9e0a32022c75f0ee7771a2ab9050db"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8d18b1e2fd06c84a879f99f6e8ca1f104eeacb13"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a6f1bc96ac9e0a32022c75f0ee7771a2ab9050db"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8d18b1e2fd06c84a879f99f6e8ca1f104eeacb13"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a6f1bc96ac9e0a32022c75f0ee7771a2ab9050db"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8d18b1e2fd06c84a879f99f6e8ca1f104eeacb13"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a6f1bc96ac9e0a32022c75f0ee7771a2ab9050db"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8d18b1e2fd06c84a879f99f6e8ca1f104eeacb13"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a6f1bc96ac9e0a32022c75f0ee7771a2ab9050db"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="e2f73049f8d52fb06cb9b5d923c1280557aa9238"/>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8d18b1e2fd06c84a879f99f6e8ca1f104eeacb13"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a6f1bc96ac9e0a32022c75f0ee7771a2ab9050db"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
|
|
@ -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]
|
||||
|
|
Двоичные данные
browser/themes/osx/Toolbar.png
Двоичные данные
browser/themes/osx/Toolbar.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 26 KiB После Ширина: | Высота: | Размер: 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);
|
||||
|
||||
|
|
|
@ -164,10 +164,6 @@
|
|||
#include "FMRadio.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G_BT
|
||||
#include "BluetoothDevice.h"
|
||||
#endif
|
||||
|
||||
#include "nsIDOMCameraManager.h"
|
||||
#include "nsIDOMGlobalObjectConstructor.h"
|
||||
#include "nsIDOMLockedFile.h"
|
||||
|
@ -488,11 +484,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G_BT
|
||||
NS_DEFINE_CLASSINFO_DATA(BluetoothDevice, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
#endif
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(CameraCapabilities, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
|
@ -1203,12 +1194,6 @@ nsDOMClassInfo::Init()
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G_BT
|
||||
DOM_CLASSINFO_MAP_BEGIN(BluetoothDevice, nsIDOMBluetoothDevice)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothDevice)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
#endif
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(CameraCapabilities, nsICameraCapabilities)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsICameraCapabilities)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
@ -3356,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;
|
||||
}
|
||||
|
@ -3406,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
|
||||
|
@ -3444,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);
|
||||
|
|
|
@ -108,10 +108,6 @@ DOMCI_CLASS(CSSPageRule)
|
|||
DOMCI_CLASS(MozIccManager)
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G_BT
|
||||
DOMCI_CLASS(BluetoothDevice)
|
||||
#endif
|
||||
|
||||
DOMCI_CLASS(CameraCapabilities)
|
||||
|
||||
DOMCI_CLASS(LockedFile)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -5,17 +5,16 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "GeneratedEvents.h"
|
||||
#include "nsCxPusher.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsIDOMBluetoothDeviceEvent.h"
|
||||
#include "nsIDOMBluetoothStatusChangedEvent.h"
|
||||
#include "nsTArrayHelpers.h"
|
||||
#include "DOMRequest.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/BluetoothAdapterBinding.h"
|
||||
#include "mozilla/dom/BluetoothDeviceEvent.h"
|
||||
#include "mozilla/dom/BluetoothStatusChangedEvent.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/LazyIdleThread.h"
|
||||
|
||||
|
@ -305,12 +304,13 @@ BluetoothAdapter::Notify(const BluetoothSignal& aData)
|
|||
BluetoothValue v = aData.value();
|
||||
if (aData.name().EqualsLiteral("DeviceFound")) {
|
||||
nsRefPtr<BluetoothDevice> device = BluetoothDevice::Create(GetOwner(), mPath, aData.value());
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
NS_NewDOMBluetoothDeviceEvent(getter_AddRefs(event), this, nullptr, nullptr);
|
||||
|
||||
nsCOMPtr<nsIDOMBluetoothDeviceEvent> e = do_QueryInterface(event);
|
||||
e->InitBluetoothDeviceEvent(NS_LITERAL_STRING("devicefound"),
|
||||
false, false, device);
|
||||
BluetoothDeviceEventInit init;
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = false;
|
||||
init.mDevice = device;
|
||||
nsRefPtr<BluetoothDeviceEvent> event =
|
||||
BluetoothDeviceEvent::Constructor(this, NS_LITERAL_STRING("devicefound"), init);
|
||||
DispatchTrustedEvent(event);
|
||||
} else if (aData.name().EqualsLiteral("PropertyChanged")) {
|
||||
MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||
|
@ -335,13 +335,13 @@ BluetoothAdapter::Notify(const BluetoothSignal& aData)
|
|||
nsString address = arr[0].value().get_nsString();
|
||||
bool status = arr[1].value().get_bool();
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
NS_NewDOMBluetoothStatusChangedEvent(
|
||||
getter_AddRefs(event), this, nullptr, nullptr);
|
||||
|
||||
nsCOMPtr<nsIDOMBluetoothStatusChangedEvent> e = do_QueryInterface(event);
|
||||
e->InitBluetoothStatusChangedEvent(aData.name(), false, false,
|
||||
address, status);
|
||||
BluetoothStatusChangedEventInit init;
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = false;
|
||||
init.mAddress = address;
|
||||
init.mStatus = status;
|
||||
nsRefPtr<BluetoothStatusChangedEvent> event =
|
||||
BluetoothStatusChangedEvent::Constructor(this, aData.name(), init);
|
||||
DispatchTrustedEvent(event);
|
||||
} else if (aData.name().EqualsLiteral(REQUEST_MEDIA_PLAYSTATUS_ID)) {
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "BluetoothPropertyContainer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIDOMBluetoothDevice.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
|
|
@ -39,8 +39,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDevice,
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothDevice)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothDevice)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothDevice)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(BluetoothDevice, nsDOMEventTargetHelper)
|
||||
|
|
|
@ -11,11 +11,8 @@
|
|||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothPropertyContainer.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIDOMBluetoothDevice.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIDOMDOMRequest;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothNamedValue;
|
||||
|
@ -24,15 +21,11 @@ class BluetoothSignal;
|
|||
class BluetoothSocket;
|
||||
|
||||
class BluetoothDevice : public nsDOMEventTargetHelper
|
||||
, public nsIDOMBluetoothDevice
|
||||
, public BluetoothSignalObserver
|
||||
, public BluetoothPropertyContainer
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMBLUETOOTHDEVICE
|
||||
|
||||
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(BluetoothDevice,
|
||||
nsDOMEventTargetHelper)
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
if CONFIG['MOZ_B2G_BT']:
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMBluetoothDevice.idl',
|
||||
'nsIDOMBluetoothDeviceEvent.idl',
|
||||
'nsIDOMBluetoothStatusChangedEvent.idl',
|
||||
]
|
||||
XPIDL_MODULE = 'dom_bluetooth'
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
|
||||
// XPIDL interfaces might need this definition; so we keep it in place
|
||||
// until we completely switched to WebIDL. See bug 900904.
|
||||
[scriptable, builtinclass, uuid(291fdda9-4f96-4f2f-857f-900f89fb0412)]
|
||||
interface nsIDOMBluetoothDevice : nsIDOMEventTarget
|
||||
{
|
||||
};
|
|
@ -1,25 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
interface nsIDOMBluetoothDevice;
|
||||
|
||||
[scriptable, builtinclass, uuid(e53dd06e-acd7-444a-914a-5fb60df0ad5b)]
|
||||
interface nsIDOMBluetoothDeviceEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute nsIDOMBluetoothDevice device;
|
||||
|
||||
[noscript] void initBluetoothDeviceEvent(in DOMString aType,
|
||||
in boolean aCanBubble,
|
||||
in boolean aCancelable,
|
||||
in nsIDOMBluetoothDevice aDevice);
|
||||
};
|
||||
|
||||
dictionary BluetoothDeviceEventInit : EventInit
|
||||
{
|
||||
nsIDOMBluetoothDevice device;
|
||||
};
|
|
@ -1,24 +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/. */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(07f6d8d0-d364-4033-92e2-d69de323d7b7)]
|
||||
interface nsIDOMBluetoothStatusChangedEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute DOMString address;
|
||||
readonly attribute boolean status;
|
||||
|
||||
[noscript] void initBluetoothStatusChangedEvent(in DOMString aType,
|
||||
in boolean aCanBubble,
|
||||
in boolean aCancelable,
|
||||
in DOMString aAddress,
|
||||
in boolean aStatus);
|
||||
};
|
||||
|
||||
dictionary BluetoothStatusChangedEventInit : EventInit
|
||||
{
|
||||
DOMString address;
|
||||
bool status;
|
||||
};
|
|
@ -5,8 +5,6 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
if CONFIG['MOZ_B2G_BT']:
|
||||
PARALLEL_DIRS += ['interfaces']
|
||||
|
||||
SOURCES += [
|
||||
'BluetoothAdapter.cpp',
|
||||
'BluetoothDevice.cpp',
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
[Constructor(DOMString type, optional BluetoothDeviceEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
|
||||
[Constructor(DOMString type, optional BluetoothDeviceEventInit eventInitDict)]
|
||||
interface BluetoothDeviceEvent : Event
|
||||
{
|
||||
readonly attribute BluetoothDevice? device;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
[Constructor(DOMString type, optional BluetoothStatusChangedEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
|
||||
[Constructor(DOMString type, optional BluetoothStatusChangedEventInit eventInitDict)]
|
||||
interface BluetoothStatusChangedEvent : Event
|
||||
{
|
||||
readonly attribute DOMString address;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -511,9 +511,7 @@ if CONFIG['MOZ_B2G_BT']:
|
|||
WEBIDL_FILES += [
|
||||
'BluetoothAdapter.webidl',
|
||||
'BluetoothDevice.webidl',
|
||||
'BluetoothDeviceEvent.webidl',
|
||||
'BluetoothManager.webidl',
|
||||
'BluetoothStatusChangedEvent.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
|
@ -583,3 +581,10 @@ if CONFIG['MOZ_GAMEPAD']:
|
|||
'GamepadButtonEvent.webidl',
|
||||
'GamepadEvent.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_BT']:
|
||||
GENERATED_EVENTS_WEBIDL_FILES += [
|
||||
'BluetoothDeviceEvent.webidl',
|
||||
'BluetoothStatusChangedEvent.webidl',
|
||||
]
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -27,10 +27,6 @@ simple_events = [
|
|||
'MozWifiStatusChangeEvent',
|
||||
'MozWifiConnectionInfoEvent',
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT
|
||||
'BluetoothDeviceEvent',
|
||||
'BluetoothStatusChangedEvent',
|
||||
#endif
|
||||
#ifdef MOZ_B2G_RIL
|
||||
'MozCellBroadcastEvent',
|
||||
'MozVoicemailEvent',
|
||||
|
@ -65,7 +61,6 @@ exclude_automatic_type_include = [
|
|||
|
||||
""" Map xpidl interface names to implementation classes. The third column is the canonical interface. """
|
||||
xpidl_to_native = [
|
||||
['nsIDOMBluetoothDevice', 'bluetooth::BluetoothDevice', 'nsIDOMBluetoothDevice'],
|
||||
['nsIDOMDocument', 'nsIDocument', 'nsIDocument'],
|
||||
['nsIDOMElement', 'mozilla::dom::Element', 'mozilla::dom::Element'],
|
||||
['nsIDOMCSSStyleSheet', 'nsCSSStyleSheet', 'nsIStyleSheet'],
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче