зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to fx-team
This commit is contained in:
Коммит
ead717cdd6
|
@ -1199,6 +1199,41 @@ AccessibleWrap::GetNativeInterface(void** aOutAccessible)
|
|||
NS_ADDREF_THIS();
|
||||
}
|
||||
|
||||
void
|
||||
AccessibleWrap::FireWinEvent(Accessible* aTarget, uint32_t aEventType)
|
||||
{
|
||||
static_assert(sizeof(gWinEventMap)/sizeof(gWinEventMap[0]) == nsIAccessibleEvent::EVENT_LAST_ENTRY,
|
||||
"MSAA event map skewed");
|
||||
|
||||
NS_ASSERTION(aEventType > 0 && aEventType < ArrayLength(gWinEventMap), "invalid event type");
|
||||
|
||||
uint32_t winEvent = gWinEventMap[aEventType];
|
||||
if (!winEvent)
|
||||
return;
|
||||
|
||||
int32_t childID = GetChildIDFor(aTarget);
|
||||
if (!childID)
|
||||
return; // Can't fire an event without a child ID
|
||||
|
||||
HWND hwnd = GetHWNDFor(aTarget);
|
||||
if (!hwnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire MSAA event for client area window.
|
||||
::NotifyWinEvent(winEvent, hwnd, OBJID_CLIENT, childID);
|
||||
|
||||
// JAWS announces collapsed combobox navigation based on focus events.
|
||||
if (aEventType == nsIAccessibleEvent::EVENT_SELECTION &&
|
||||
Compatibility::IsJAWS()) {
|
||||
roles::Role role = aTarget->IsProxy() ? aTarget->Proxy()->Role() :
|
||||
aTarget->Role();
|
||||
if (role == roles::COMBOBOX_OPTION) {
|
||||
::NotifyWinEvent(EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, childID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Accessible
|
||||
|
||||
|
@ -1214,15 +1249,6 @@ AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
|||
|
||||
uint32_t eventType = aEvent->GetEventType();
|
||||
|
||||
static_assert(sizeof(gWinEventMap)/sizeof(gWinEventMap[0]) == nsIAccessibleEvent::EVENT_LAST_ENTRY,
|
||||
"MSAA event map skewed");
|
||||
|
||||
NS_ENSURE_TRUE(eventType > 0 && eventType < ArrayLength(gWinEventMap), NS_ERROR_FAILURE);
|
||||
|
||||
uint32_t winEvent = gWinEventMap[eventType];
|
||||
if (!winEvent)
|
||||
return NS_OK;
|
||||
|
||||
// Means we're not active.
|
||||
NS_ENSURE_TRUE(!IsDefunct(), NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -1235,41 +1261,7 @@ AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
|||
UpdateSystemCaretFor(accessible);
|
||||
}
|
||||
|
||||
int32_t childID = GetChildIDFor(accessible); // get the id for the accessible
|
||||
if (!childID)
|
||||
return NS_OK; // Can't fire an event without a child ID
|
||||
|
||||
HWND hWnd = GetHWNDFor(accessible);
|
||||
NS_ENSURE_TRUE(hWnd, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoString tag;
|
||||
nsAutoCString id;
|
||||
nsIContent* cnt = accessible->GetContent();
|
||||
if (cnt) {
|
||||
cnt->NodeInfo()->NameAtom()->ToString(tag);
|
||||
nsIAtom* aid = cnt->GetID();
|
||||
if (aid)
|
||||
aid->ToUTF8String(id);
|
||||
}
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::ePlatforms)) {
|
||||
printf("\n\nMSAA event: event: %d, target: %s@id='%s', childid: %d, hwnd: %p\n\n",
|
||||
eventType, NS_ConvertUTF16toUTF8(tag).get(), id.get(),
|
||||
childID, hWnd);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fire MSAA event for client area window.
|
||||
::NotifyWinEvent(winEvent, hWnd, OBJID_CLIENT, childID);
|
||||
|
||||
// JAWS announces collapsed combobox navigation based on focus events.
|
||||
if (Compatibility::IsJAWS()) {
|
||||
if (eventType == nsIAccessibleEvent::EVENT_SELECTION &&
|
||||
accessible->Role() == roles::COMBOBOX_OPTION) {
|
||||
::NotifyWinEvent(EVENT_OBJECT_FOCUS, hWnd, OBJID_CLIENT, childID);
|
||||
}
|
||||
}
|
||||
FireWinEvent(accessible, eventType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -159,6 +159,8 @@ public: // construction, destruction
|
|||
static int32_t GetChildIDFor(Accessible* aAccessible);
|
||||
static HWND GetHWNDFor(Accessible* aAccessible);
|
||||
|
||||
static void FireWinEvent(Accessible* aTarget, uint32_t aEventType);
|
||||
|
||||
/**
|
||||
* System caret support: update the Windows caret position.
|
||||
* The system caret works more universally than the MSAA caret
|
||||
|
|
|
@ -76,18 +76,23 @@ a11y::ProxyDestroyed(ProxyAccessible* aProxy)
|
|||
}
|
||||
|
||||
void
|
||||
a11y::ProxyEvent(ProxyAccessible*, uint32_t)
|
||||
a11y::ProxyEvent(ProxyAccessible* aTarget, uint32_t aEventType)
|
||||
{
|
||||
AccessibleWrap::FireWinEvent(WrapperFor(aTarget), aEventType);
|
||||
}
|
||||
|
||||
void
|
||||
a11y::ProxyStateChangeEvent(ProxyAccessible*, uint64_t, bool)
|
||||
a11y::ProxyStateChangeEvent(ProxyAccessible* aTarget, uint64_t, bool)
|
||||
{
|
||||
AccessibleWrap::FireWinEvent(WrapperFor(aTarget),
|
||||
nsIAccessibleEvent::EVENT_STATE_CHANGE);
|
||||
}
|
||||
|
||||
void
|
||||
a11y::ProxyCaretMoveEvent(ProxyAccessible* aTarget, int32_t aOffset)
|
||||
{
|
||||
AccessibleWrap::FireWinEvent(WrapperFor(aTarget),
|
||||
nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -104,4 +109,8 @@ a11y::ProxyTextChangeEvent(ProxyAccessible* aText, const nsString& aStr,
|
|||
if (text) {
|
||||
ia2AccessibleText::UpdateTextChangeData(text, aInsert, aStr, aStart, aLen);
|
||||
}
|
||||
|
||||
uint32_t eventType = aInsert ? nsIAccessibleEvent::EVENT_TEXT_INSERTED :
|
||||
nsIAccessibleEvent::EVENT_TEXT_REMOVED;
|
||||
AccessibleWrap::FireWinEvent(wrapper, eventType);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,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="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1f9532e4157df2dc8d3e9c8100120f80117dcd4"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,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="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "2082894c8e974b0c371e4dec298e0ad0f3ac56b1",
|
||||
"git_revision": "4f22dfecdc046fe5223ee858dd06c11b75884740",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "0e712c8d330e10908f99194a9638e62a07c5c483",
|
||||
"revision": "0beec8dba282bfc00590a16ccf180c0988465316",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1f9532e4157df2dc8d3e9c8100120f80117dcd4"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -120,12 +120,31 @@ var gTests = [
|
|||
}
|
||||
];
|
||||
|
||||
function checkState(expectedStates, contentStates) {
|
||||
is(contentStates.inDOMFullscreen, expectedStates.inDOMFullscreen,
|
||||
"The DOM fullscreen state of the content should match");
|
||||
// TODO window.fullScreen is not updated as soon as the fullscreen
|
||||
// state flips in child process, hence checking it could cause
|
||||
// anonying intermittent failure. As we just want to confirm the
|
||||
// fullscreen state of the browser window, we can just check the
|
||||
// that on the chrome window below.
|
||||
// is(contentStates.inFullscreen, expectedStates.inFullscreen,
|
||||
// "The fullscreen state of the content should match");
|
||||
is(document.mozFullScreen, expectedStates.inDOMFullscreen,
|
||||
"The DOM fullscreen state of the chrome should match");
|
||||
is(window.fullScreen, expectedStates.inFullscreen,
|
||||
"The fullscreen state of the chrome should match");
|
||||
}
|
||||
|
||||
const kPage = "http://example.org/browser/browser/" +
|
||||
"base/content/test/general/dummy_page.html";
|
||||
|
||||
add_task(function* () {
|
||||
yield pushPrefs(
|
||||
["full-screen-api.transition-duration.enter", "0 0"],
|
||||
["full-screen-api.transition-duration.leave", "0 0"]);
|
||||
|
||||
let tab = gBrowser.addTab("about:robots");
|
||||
let tab = gBrowser.addTab(kPage);
|
||||
let browser = tab.linkedBrowser;
|
||||
gBrowser.selectedTab = tab;
|
||||
yield waitForDocLoadComplete();
|
||||
|
@ -148,63 +167,53 @@ add_task(function* () {
|
|||
yield new Promise(resolve => listenOneMessage("Test:Activated", resolve));
|
||||
|
||||
for (let test of gTests) {
|
||||
let contentStates;
|
||||
info("Testing exit DOM fullscreen via " + test.desc);
|
||||
|
||||
var { inDOMFullscreen, inFullscreen } = yield queryFullscreenState();
|
||||
ok(!inDOMFullscreen, "Shouldn't have been in DOM fullscreen");
|
||||
ok(!inFullscreen, "Shouldn't have been in fullscreen");
|
||||
contentStates = yield queryFullscreenState();
|
||||
checkState({inDOMFullscreen: false, inFullscreen: false}, contentStates);
|
||||
|
||||
/* DOM fullscreen without fullscreen mode */
|
||||
|
||||
// Enter DOM fullscreen
|
||||
info("> Enter DOM fullscreen");
|
||||
gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
|
||||
var { inDOMFullscreen, inFullscreen } =
|
||||
yield waitForFullscreenChanges(FS_CHANGE_BOTH);
|
||||
ok(inDOMFullscreen, "Should now be in DOM fullscreen");
|
||||
ok(inFullscreen, "Should now be in fullscreen");
|
||||
contentStates = yield waitForFullscreenChanges(FS_CHANGE_BOTH);
|
||||
checkState({inDOMFullscreen: true, inFullscreen: true}, contentStates);
|
||||
|
||||
// Exit DOM fullscreen
|
||||
info("> Exit DOM fullscreen");
|
||||
test.exitFunc();
|
||||
var { inDOMFullscreen, inFullscreen } =
|
||||
yield waitForFullscreenChanges(FS_CHANGE_BOTH);
|
||||
ok(!inDOMFullscreen, "Should no longer be in DOM fullscreen");
|
||||
ok(!inFullscreen, "Should no longer be in fullscreen");
|
||||
contentStates = yield waitForFullscreenChanges(FS_CHANGE_BOTH);
|
||||
checkState({inDOMFullscreen: false, inFullscreen: false}, contentStates);
|
||||
|
||||
/* DOM fullscreen with fullscreen mode */
|
||||
|
||||
// Enter fullscreen mode
|
||||
info("> Enter fullscreen mode");
|
||||
// Need to be asynchronous because sizemodechange event could be
|
||||
// dispatched synchronously, which would cause the event listener
|
||||
// miss that event and wait infinitely.
|
||||
executeSoon(() => BrowserFullScreen());
|
||||
var { inDOMFullscreen, inFullscreen } =
|
||||
yield waitForFullscreenChanges(FS_CHANGE_SIZE);
|
||||
ok(!inDOMFullscreen, "Shouldn't have been in DOM fullscreen");
|
||||
ok(inFullscreen, "Should now be in fullscreen mode");
|
||||
contentStates = yield waitForFullscreenChanges(FS_CHANGE_SIZE);
|
||||
checkState({inDOMFullscreen: false, inFullscreen: true}, contentStates);
|
||||
|
||||
// Enter DOM fullscreen
|
||||
info("> Enter DOM fullscreen in fullscreen mode");
|
||||
gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
|
||||
var { inDOMFullscreen, inFullscreen } =
|
||||
yield waitForFullscreenChanges(FS_CHANGE_DOM);
|
||||
ok(inDOMFullscreen, "Should now be in DOM fullscreen");
|
||||
ok(inFullscreen, "Should still be in fullscreen");
|
||||
contentStates = yield waitForFullscreenChanges(FS_CHANGE_DOM);
|
||||
checkState({inDOMFullscreen: true, inFullscreen: true}, contentStates);
|
||||
|
||||
// Exit DOM fullscreen
|
||||
info("> Exit DOM fullscreen in fullscreen mode");
|
||||
test.exitFunc();
|
||||
var { inDOMFullscreen, inFullscreen } =
|
||||
yield waitForFullscreenChanges(test.affectsFullscreenMode ?
|
||||
FS_CHANGE_BOTH : FS_CHANGE_DOM);
|
||||
ok(!inDOMFullscreen, "Should no longer be in DOM fullscreen");
|
||||
if (test.affectsFullscreenMode) {
|
||||
ok(!inFullscreen, "Should no longer be in fullscreen mode");
|
||||
} else {
|
||||
ok(inFullscreen, "Should still be in fullscreen mode");
|
||||
}
|
||||
contentStates = yield waitForFullscreenChanges(
|
||||
test.affectsFullscreenMode ? FS_CHANGE_BOTH : FS_CHANGE_DOM);
|
||||
checkState({
|
||||
inDOMFullscreen: false,
|
||||
inFullscreen: !test.affectsFullscreenMode
|
||||
}, contentStates);
|
||||
|
||||
/* Cleanup */
|
||||
|
||||
// Exit fullscreen mode if we are still in
|
||||
if (browser.contentWindow.fullScreen) {
|
||||
if (window.fullScreen) {
|
||||
info("> Cleanup");
|
||||
executeSoon(() => BrowserFullScreen());
|
||||
yield waitForFullscreenChanges(FS_CHANGE_SIZE);
|
||||
}
|
||||
|
|
|
@ -145,6 +145,7 @@ MACH_MODULES = [
|
|||
'tools/docs/mach_commands.py',
|
||||
'tools/mercurial/mach_commands.py',
|
||||
'tools/mach_commands.py',
|
||||
'tools/power/mach_commands.py',
|
||||
'mobile/android/mach_commands.py',
|
||||
]
|
||||
|
||||
|
|
|
@ -232,12 +232,11 @@ using namespace mozilla;
|
|||
using namespace mozilla::dom;
|
||||
using mozilla::dom::workers::ServiceWorkerManager;
|
||||
|
||||
// True means sUseErrorPages and sInterceptionEnabled has been added to
|
||||
// True means sUseErrorPages has been added to
|
||||
// preferences var cache.
|
||||
static bool gAddedPreferencesVarCache = false;
|
||||
|
||||
bool nsDocShell::sUseErrorPages = false;
|
||||
bool nsDocShell::sInterceptionEnabled = false;
|
||||
|
||||
// Number of documents currently loading
|
||||
static int32_t gNumberOfDocumentsLoading = 0;
|
||||
|
@ -5536,9 +5535,6 @@ nsDocShell::Create()
|
|||
Preferences::AddBoolVarCache(&sUseErrorPages,
|
||||
"browser.xul.error_pages.enabled",
|
||||
mUseErrorPages);
|
||||
Preferences::AddBoolVarCache(&sInterceptionEnabled,
|
||||
"dom.serviceWorkers.interception.enabled",
|
||||
false);
|
||||
gAddedPreferencesVarCache = true;
|
||||
}
|
||||
|
||||
|
@ -13858,7 +13854,7 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate,
|
|||
{
|
||||
*aShouldIntercept = false;
|
||||
// Preffed off.
|
||||
if (!sInterceptionEnabled) {
|
||||
if (!nsContentUtils::ServiceWorkerInterceptionEnabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -887,9 +887,6 @@ protected:
|
|||
// Cached value of the "browser.xul.error_pages.enabled" preference.
|
||||
static bool sUseErrorPages;
|
||||
|
||||
// Cached value of the "dom.serviceWorkers.interception.enabled" preference.
|
||||
static bool sInterceptionEnabled;
|
||||
|
||||
bool mCreated;
|
||||
bool mAllowSubframes;
|
||||
bool mAllowPlugins;
|
||||
|
|
|
@ -1064,6 +1064,12 @@ nsContentSink::ProcessOfflineManifest(const nsAString& aManifestSpec)
|
|||
return;
|
||||
}
|
||||
|
||||
// If this document has been interecepted, let's skip the processing of the
|
||||
// manifest.
|
||||
if (nsContentUtils::IsControlledByServiceWorker(mDocument)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the docshell's in private browsing mode, we don't want to do any
|
||||
// manifest processing.
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(mDocShell);
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "mozilla/dom/TouchEvent.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/workers/ServiceWorkerManager.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
|
@ -267,6 +268,7 @@ bool nsContentUtils::sEncodeDecodeURLHash = false;
|
|||
bool nsContentUtils::sGettersDecodeURLHash = false;
|
||||
bool nsContentUtils::sPrivacyResistFingerprinting = false;
|
||||
bool nsContentUtils::sSendPerformanceTimingNotifications = false;
|
||||
bool nsContentUtils::sSWInterceptionEnabled = false;
|
||||
|
||||
uint32_t nsContentUtils::sHandlingInputTimeout = 1000;
|
||||
|
||||
|
@ -559,6 +561,10 @@ nsContentUtils::Init()
|
|||
Preferences::AddBoolVarCache(&sPrivacyResistFingerprinting,
|
||||
"privacy.resistFingerprinting", false);
|
||||
|
||||
Preferences::AddBoolVarCache(&sSWInterceptionEnabled,
|
||||
"dom.serviceWorkers.interception.enabled",
|
||||
false);
|
||||
|
||||
Preferences::AddUintVarCache(&sHandlingInputTimeout,
|
||||
"dom.event.handling-user-input-time-limit",
|
||||
1000);
|
||||
|
@ -1736,10 +1742,38 @@ nsContentUtils::ParseLegacyFontSize(const nsAString& aValue)
|
|||
return clamped(value, 1, 7);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsContentUtils::IsControlledByServiceWorker(nsIDocument* aDocument)
|
||||
{
|
||||
if (!ServiceWorkerInterceptionEnabled() ||
|
||||
nsContentUtils::IsInPrivateBrowsing(aDocument)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRefPtr<workers::ServiceWorkerManager> swm =
|
||||
workers::ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
ErrorResult rv;
|
||||
bool controlled = swm->IsControlled(aDocument, rv);
|
||||
NS_WARN_IF(rv.Failed());
|
||||
|
||||
return !rv.Failed() && controlled;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsContentUtils::GetOfflineAppManifest(nsIDocument *aDocument, nsIURI **aURI)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aDocument);
|
||||
*aURI = nullptr;
|
||||
|
||||
if (IsControlledByServiceWorker(aDocument)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Element* docElement = aDocument->GetRootElement();
|
||||
if (!docElement) {
|
||||
return;
|
||||
|
@ -5230,7 +5264,6 @@ nsContentUtils::LeaveMicroTask()
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (--sMicroTaskLevel == 0) {
|
||||
PerformMainThreadMicroTaskCheckpoint();
|
||||
nsDocument::ProcessBaseElementQueue();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1955,6 +1955,14 @@ public:
|
|||
return sSendPerformanceTimingNotifications;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if ServiceWorker Interception is enabled by pref.
|
||||
*/
|
||||
static bool ServiceWorkerInterceptionEnabled()
|
||||
{
|
||||
return sSWInterceptionEnabled;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the frame timing APIs are enabled.
|
||||
*/
|
||||
|
@ -1995,6 +2003,11 @@ public:
|
|||
*/
|
||||
static bool HasPluginWithUncontrolledEventDispatch(nsIDocument* aDoc);
|
||||
|
||||
/**
|
||||
* Return true if this doc is controlled by a ServiceWorker.
|
||||
*/
|
||||
static bool IsControlledByServiceWorker(nsIDocument* aDocument);
|
||||
|
||||
/**
|
||||
* Fire mutation events for changes caused by parsing directly into a
|
||||
* context node.
|
||||
|
@ -2607,6 +2620,7 @@ private:
|
|||
static bool sGettersDecodeURLHash;
|
||||
static bool sPrivacyResistFingerprinting;
|
||||
static bool sSendPerformanceTimingNotifications;
|
||||
static bool sSWInterceptionEnabled;
|
||||
static uint32_t sCookiesLifetimePolicy;
|
||||
static uint32_t sCookiesBehavior;
|
||||
|
||||
|
|
|
@ -5895,29 +5895,6 @@ nsDocument::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ProcessStackRunner final : public nsIRunnable
|
||||
{
|
||||
~ProcessStackRunner() {}
|
||||
public:
|
||||
explicit ProcessStackRunner(bool aIsBaseQueue = false)
|
||||
: mIsBaseQueue(aIsBaseQueue)
|
||||
{
|
||||
}
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
nsDocument::ProcessTopElementQueue(mIsBaseQueue);
|
||||
return NS_OK;
|
||||
}
|
||||
bool mIsBaseQueue;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ProcessStackRunner, nsIRunnable);
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
nsDocument::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
||||
Element* aCustomElement,
|
||||
|
@ -6019,10 +5996,7 @@ nsDocument::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
|||
|
||||
// A new element queue needs to be pushed if the queue at the
|
||||
// top of the stack is associated with another microtask level.
|
||||
// Don't push a queue for the level 0 microtask (base element queue)
|
||||
// because we don't want to process the queue until the
|
||||
// microtask checkpoint.
|
||||
bool shouldPushElementQueue = nsContentUtils::MicroTaskLevel() > 0 &&
|
||||
bool shouldPushElementQueue =
|
||||
(!lastData || lastData->mAssociatedMicroTask <
|
||||
static_cast<int32_t>(nsContentUtils::MicroTaskLevel()));
|
||||
|
||||
|
@ -6045,39 +6019,22 @@ nsDocument::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
|||
// should be invoked prior to returning control back to script.
|
||||
// Create a script runner to process the top of the processing
|
||||
// stack as soon as it is safe to run script.
|
||||
nsContentUtils::AddScriptRunner(new ProcessStackRunner());
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableFunction(&nsDocument::ProcessTopElementQueue);
|
||||
nsContentUtils::AddScriptRunner(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsDocument::ProcessBaseElementQueue()
|
||||
{
|
||||
// Prevent re-entrance. Also, if a microtask checkpoint is reached
|
||||
// and there is no processing stack to process, then we are done.
|
||||
if (sProcessingBaseElementQueue || !sProcessingStack) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(nsContentUtils::MicroTaskLevel() == 0);
|
||||
sProcessingBaseElementQueue = true;
|
||||
nsContentUtils::AddScriptRunner(new ProcessStackRunner(true));
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsDocument::ProcessTopElementQueue(bool aIsBaseQueue)
|
||||
nsDocument::ProcessTopElementQueue()
|
||||
{
|
||||
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
|
||||
|
||||
nsTArray<nsRefPtr<CustomElementData>>& stack = *sProcessingStack;
|
||||
uint32_t firstQueue = stack.LastIndexOf((CustomElementData*) nullptr);
|
||||
|
||||
if (aIsBaseQueue && firstQueue != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = firstQueue + 1; i < stack.Length(); ++i) {
|
||||
// Callback queue may have already been processed in an earlier
|
||||
// element queue or in an element queue that was popped
|
||||
|
@ -6095,7 +6052,6 @@ nsDocument::ProcessTopElementQueue(bool aIsBaseQueue)
|
|||
} else {
|
||||
// Don't pop sentinel for base element queue.
|
||||
stack.SetLength(1);
|
||||
sProcessingBaseElementQueue = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6111,10 +6067,6 @@ nsDocument::RegisterEnabled()
|
|||
Maybe<nsTArray<nsRefPtr<mozilla::dom::CustomElementData>>>
|
||||
nsDocument::sProcessingStack;
|
||||
|
||||
// static
|
||||
bool
|
||||
nsDocument::sProcessingBaseElementQueue;
|
||||
|
||||
void
|
||||
nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
||||
const ElementRegistrationOptions& aOptions,
|
||||
|
@ -11734,6 +11686,41 @@ GetRootWindow(nsIDocument* aDoc)
|
|||
return rootItem ? rootItem->GetWindow() : nullptr;
|
||||
}
|
||||
|
||||
static bool
|
||||
ShouldApplyFullscreenDirectly(nsIDocument* aDoc,
|
||||
nsPIDOMWindow* aRootWin)
|
||||
{
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
// If we are in the content process, we can apply the fullscreen
|
||||
// state directly only if we have been in DOM fullscreen, because
|
||||
// otherwise we always need to notify the chrome.
|
||||
return nsContentUtils::GetRootDocument(aDoc)->IsFullScreenDoc();
|
||||
} else {
|
||||
// If we are in the chrome process, and the window has not been in
|
||||
// fullscreen, we certainly need to make that fullscreen first.
|
||||
bool fullscreen;
|
||||
NS_WARN_IF(NS_FAILED(aRootWin->GetFullScreen(&fullscreen)));
|
||||
if (!fullscreen) {
|
||||
return false;
|
||||
}
|
||||
// The iterator not being at end indicates there is still some
|
||||
// pending fullscreen request relates to this document. We have to
|
||||
// push the request to the pending queue so requests are handled
|
||||
// in the correct order.
|
||||
PendingFullscreenRequestList::Iterator
|
||||
iter(aDoc, PendingFullscreenRequestList::eDocumentsWithSameRoot);
|
||||
if (!iter.AtEnd()) {
|
||||
return false;
|
||||
}
|
||||
// We have to apply the fullscreen state directly in this case,
|
||||
// because nsGlobalWindow::SetFullscreenInternal() will do nothing
|
||||
// if it is already in fullscreen. If we do not apply the state but
|
||||
// instead add it to the queue and wait for the window as normal,
|
||||
// we would get stuck.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
|
||||
{
|
||||
|
@ -11742,19 +11729,7 @@ nsDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
|
|||
return;
|
||||
}
|
||||
|
||||
// If we have been in fullscreen, apply the new state directly.
|
||||
// Note that we should check both condition, because if we are in
|
||||
// child process, our window may not report to be in fullscreen.
|
||||
// Also, it is possible that the root window reports that it is in
|
||||
// fullscreen while there exists pending fullscreen request because
|
||||
// of ongoing fullscreen transition. In that case, we shouldn't
|
||||
// apply the state before any previous request.
|
||||
if ((static_cast<nsGlobalWindow*>(rootWin.get())->FullScreen() &&
|
||||
// The iterator being at end at the beginning indicates there is
|
||||
// no pending fullscreen request which relates to this document.
|
||||
PendingFullscreenRequestList::Iterator(
|
||||
this, PendingFullscreenRequestList::eDocumentsWithSameRoot).AtEnd()) ||
|
||||
nsContentUtils::GetRootDocument(this)->IsFullScreenDoc()) {
|
||||
if (ShouldApplyFullscreenDirectly(this, rootWin)) {
|
||||
ApplyFullscreen(*aRequest);
|
||||
return;
|
||||
}
|
||||
|
@ -13043,6 +13018,24 @@ nsDocument::ReportUseCounters()
|
|||
// that feature were removed. Whereas with a document/top-level
|
||||
// page split, we can see that N documents would be affected, but
|
||||
// only a single web page would be affected.
|
||||
|
||||
// The difference between the values of these two histograms and the
|
||||
// related use counters below tell us how many pages did *not* use
|
||||
// the feature in question. For instance, if we see that a given
|
||||
// session has destroyed 30 content documents, but a particular use
|
||||
// counter shows only a count of 5, we can infer that the use
|
||||
// counter was *not* used in 25 of those 30 documents.
|
||||
//
|
||||
// We do things this way, rather than accumulating a boolean flag
|
||||
// for each use counter, to avoid sending histograms for features
|
||||
// that don't get widely used. Doing things in this fashion means
|
||||
// smaller telemetry payloads and faster processing on the server
|
||||
// side.
|
||||
Telemetry::Accumulate(Telemetry::CONTENT_DOCUMENTS_DESTROYED, 1);
|
||||
if (IsTopLevelContentDocument()) {
|
||||
Telemetry::Accumulate(Telemetry::TOP_LEVEL_CONTENT_DOCUMENTS_DESTROYED, 1);
|
||||
}
|
||||
|
||||
for (int32_t c = 0;
|
||||
c < eUseCounter_Count; ++c) {
|
||||
UseCounter uc = static_cast<UseCounter>(c);
|
||||
|
@ -13051,24 +13044,8 @@ nsDocument::ReportUseCounters()
|
|||
static_cast<Telemetry::ID>(Telemetry::HistogramFirstUseCounter + uc * 2);
|
||||
bool value = GetUseCounter(uc);
|
||||
|
||||
if (sDebugUseCounters && value) {
|
||||
const char* name = Telemetry::GetHistogramName(id);
|
||||
if (name) {
|
||||
printf(" %s", name);
|
||||
} else {
|
||||
printf(" #%d", id);
|
||||
}
|
||||
printf(": %d\n", value);
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(id, value);
|
||||
|
||||
if (IsTopLevelContentDocument()) {
|
||||
id = static_cast<Telemetry::ID>(Telemetry::HistogramFirstUseCounter +
|
||||
uc * 2 + 1);
|
||||
value = GetUseCounter(uc) || GetChildDocumentUseCounter(uc);
|
||||
|
||||
if (sDebugUseCounters && value) {
|
||||
if (value) {
|
||||
if (sDebugUseCounters) {
|
||||
const char* name = Telemetry::GetHistogramName(id);
|
||||
if (name) {
|
||||
printf(" %s", name);
|
||||
|
@ -13078,7 +13055,27 @@ nsDocument::ReportUseCounters()
|
|||
printf(": %d\n", value);
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(id, value);
|
||||
Telemetry::Accumulate(id, 1);
|
||||
}
|
||||
|
||||
if (IsTopLevelContentDocument()) {
|
||||
id = static_cast<Telemetry::ID>(Telemetry::HistogramFirstUseCounter +
|
||||
uc * 2 + 1);
|
||||
value = GetUseCounter(uc) || GetChildDocumentUseCounter(uc);
|
||||
|
||||
if (value) {
|
||||
if (sDebugUseCounters) {
|
||||
const char* name = Telemetry::GetHistogramName(id);
|
||||
if (name) {
|
||||
printf(" %s", name);
|
||||
} else {
|
||||
printf(" #%d", id);
|
||||
}
|
||||
printf(": %d\n", value);
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(id, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1303,7 +1303,7 @@ public:
|
|||
mozilla::dom::LifecycleCallbackArgs* aArgs = nullptr,
|
||||
mozilla::dom::CustomElementDefinition* aDefinition = nullptr) override;
|
||||
|
||||
static void ProcessTopElementQueue(bool aIsBaseQueue = false);
|
||||
static void ProcessTopElementQueue();
|
||||
|
||||
void GetCustomPrototype(int32_t aNamespaceID,
|
||||
nsIAtom* aAtom,
|
||||
|
@ -1600,15 +1600,9 @@ private:
|
|||
// queue in the stack is the base element queue.
|
||||
static mozilla::Maybe<nsTArray<nsRefPtr<mozilla::dom::CustomElementData>>> sProcessingStack;
|
||||
|
||||
// Flag to prevent re-entrance into base element queue as described in the
|
||||
// custom elements speicification.
|
||||
static bool sProcessingBaseElementQueue;
|
||||
|
||||
static bool CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
|
||||
|
||||
public:
|
||||
static void ProcessBaseElementQueue();
|
||||
|
||||
// Enqueue created callback or register upgrade candidate for
|
||||
// newly created custom elements, possibly extending an existing type.
|
||||
// ex. <x-button>, <button is="x-button> (type extension)
|
||||
|
|
|
@ -635,7 +635,7 @@ public:
|
|||
virtual bool has(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id, bool *bp) const override;
|
||||
virtual bool get(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<JSObject*> receiver,
|
||||
JS::Handle<JS::Value> receiver,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JS::Value> vp) const override;
|
||||
virtual bool set(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
|
@ -900,7 +900,7 @@ nsOuterWindowProxy::hasOwn(JSContext *cx, JS::Handle<JSObject*> proxy,
|
|||
|
||||
bool
|
||||
nsOuterWindowProxy::get(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<JSObject*> receiver,
|
||||
JS::Handle<JS::Value> receiver,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JS::Value> vp) const
|
||||
{
|
||||
|
|
|
@ -104,11 +104,14 @@ function grabHistogramsFromContent(browser, use_counter_middlefix) {
|
|||
return telemetry.getHistogramById(name).snapshot();
|
||||
}
|
||||
|
||||
let histogram_page_name = "USE_COUNTER_" + arg.middlefix + "_PAGE";
|
||||
let histogram_document_name = "USE_COUNTER_" + arg.middlefix + "_DOCUMENT";
|
||||
let histogram_page_name = "USE_COUNTER2_" + arg.middlefix + "_PAGE";
|
||||
let histogram_document_name = "USE_COUNTER2_" + arg.middlefix + "_DOCUMENT";
|
||||
let histogram_page = snapshot_histogram(histogram_page_name);
|
||||
let histogram_document = snapshot_histogram(histogram_document_name);
|
||||
return [histogram_page.sum, histogram_document.sum];
|
||||
let histogram_docs = snapshot_histogram("CONTENT_DOCUMENTS_DESTROYED");
|
||||
let histogram_toplevel_docs = snapshot_histogram("TOP_LEVEL_CONTENT_DOCUMENTS_DESTROYED");
|
||||
return [histogram_page.sum, histogram_document.sum,
|
||||
histogram_docs.sum, histogram_toplevel_docs.sum];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -121,7 +124,8 @@ var check_use_counter_iframe = Task.async(function* (file, use_counter_middlefix
|
|||
|
||||
// Hold on to the current values of the telemetry histograms we're
|
||||
// interested in.
|
||||
let [histogram_page_before, histogram_document_before] =
|
||||
let [histogram_page_before, histogram_document_before,
|
||||
histogram_docs_before, histogram_toplevel_docs_before] =
|
||||
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
|
||||
|
||||
gBrowser.selectedBrowser.loadURI(gHttpTestRoot + "file_use_counter_outer.html");
|
||||
|
@ -161,14 +165,17 @@ var check_use_counter_iframe = Task.async(function* (file, use_counter_middlefix
|
|||
yield waitForDestroyedDocuments();
|
||||
|
||||
// Grab histograms again and compare.
|
||||
let [histogram_page_after, histogram_document_after] =
|
||||
let [histogram_page_after, histogram_document_after,
|
||||
histogram_docs_after, histogram_toplevel_docs_after] =
|
||||
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
|
||||
|
||||
is(histogram_page_after, histogram_page_before + 1,
|
||||
"page counts for " + use_counter_middlefix + " after are correct");
|
||||
ok(histogram_toplevel_docs_after >= histogram_toplevel_docs_before + 1,
|
||||
"top level document counts are correct");
|
||||
if (check_documents) {
|
||||
is(histogram_document_after, histogram_document_before + 1,
|
||||
"document counts " + use_counter_middlefix + " after are correct");
|
||||
"document counts for " + use_counter_middlefix + " after are correct");
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -181,7 +188,8 @@ var check_use_counter_img = Task.async(function* (file, use_counter_middlefix) {
|
|||
|
||||
// Hold on to the current values of the telemetry histograms we're
|
||||
// interested in.
|
||||
let [histogram_page_before, histogram_document_before] =
|
||||
let [histogram_page_before, histogram_document_before,
|
||||
histogram_docs_before, histogram_toplevel_docs_before] =
|
||||
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
|
||||
|
||||
gBrowser.selectedBrowser.loadURI(gHttpTestRoot + "file_use_counter_outer.html");
|
||||
|
@ -222,12 +230,19 @@ var check_use_counter_img = Task.async(function* (file, use_counter_middlefix) {
|
|||
yield waitForDestroyedDocuments();
|
||||
|
||||
// Grab histograms again and compare.
|
||||
let [histogram_page_after, histogram_document_after] =
|
||||
let [histogram_page_after, histogram_document_after,
|
||||
histogram_docs_after, histogram_toplevel_docs_after] =
|
||||
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
|
||||
is(histogram_page_after, histogram_page_before + 1,
|
||||
"page counts for " + use_counter_middlefix + " after are correct");
|
||||
is(histogram_document_after, histogram_document_before + 1,
|
||||
"document counts " + use_counter_middlefix + " after are correct");
|
||||
"document counts for " + use_counter_middlefix + " after are correct");
|
||||
ok(histogram_toplevel_docs_after >= histogram_toplevel_docs_before + 1,
|
||||
"top level document counts are correct");
|
||||
// 2 documents: one for the outer html page containing the <img> element, and
|
||||
// one for the SVG image itself.
|
||||
ok(histogram_docs_after >= histogram_docs_before + 2,
|
||||
"document counts are correct");
|
||||
});
|
||||
|
||||
var check_use_counter_direct = Task.async(function* (file, use_counter_middlefix, xfail=false) {
|
||||
|
@ -239,7 +254,8 @@ var check_use_counter_direct = Task.async(function* (file, use_counter_middlefix
|
|||
|
||||
// Hold on to the current values of the telemetry histograms we're
|
||||
// interested in.
|
||||
let [histogram_page_before, histogram_document_before] =
|
||||
let [histogram_page_before, histogram_document_before,
|
||||
histogram_docs_before, histogram_toplevel_docs_before] =
|
||||
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
|
||||
|
||||
gBrowser.selectedBrowser.loadURI(gHttpTestRoot + file);
|
||||
|
@ -267,10 +283,15 @@ var check_use_counter_direct = Task.async(function* (file, use_counter_middlefix
|
|||
yield waitForDestroyedDocuments();
|
||||
|
||||
// Grab histograms again and compare.
|
||||
let [histogram_page_after, histogram_document_after] =
|
||||
let [histogram_page_after, histogram_document_after,
|
||||
histogram_docs_after, histogram_toplevel_docs_after] =
|
||||
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
|
||||
(xfail ? todo_is : is)(histogram_page_after, histogram_page_before + 1,
|
||||
"page counts for " + use_counter_middlefix + " after are correct");
|
||||
(xfail ? todo_is : is)(histogram_document_after, histogram_document_before + 1,
|
||||
"document counts " + use_counter_middlefix + " after are correct");
|
||||
"document counts for " + use_counter_middlefix + " after are correct");
|
||||
ok(histogram_toplevel_docs_after >= histogram_toplevel_docs_before + 1,
|
||||
"top level document counts are correct");
|
||||
ok(histogram_docs_after >= histogram_docs_before + 1,
|
||||
"document counts are correct");
|
||||
});
|
||||
|
|
|
@ -62,8 +62,8 @@ def generate_histograms(filename):
|
|||
'description': desc }
|
||||
|
||||
def append_counters(name, desc):
|
||||
append_counter('USE_COUNTER_%s_DOCUMENT' % name, 'Whether a document %s' % desc)
|
||||
append_counter('USE_COUNTER_%s_PAGE' % name, 'Whether a page %s' % desc)
|
||||
append_counter('USE_COUNTER2_%s_DOCUMENT' % name, 'Whether a document %s' % desc)
|
||||
append_counter('USE_COUNTER2_%s_PAGE' % name, 'Whether a page %s' % desc)
|
||||
|
||||
if counter['type'] == 'method':
|
||||
method = '%s.%s' % (counter['interface_name'], counter['method_name'])
|
||||
|
|
|
@ -1699,8 +1699,8 @@ NativePropertyHooks sEmptyNativePropertyHooks = {
|
|||
|
||||
bool
|
||||
GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id, bool* found,
|
||||
JS::MutableHandle<JS::Value> vp)
|
||||
JS::Handle<JS::Value> receiver, JS::Handle<jsid> id,
|
||||
bool* found, JS::MutableHandle<JS::Value> vp)
|
||||
{
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
if (!js::GetObjectProto(cx, proxy, &proto)) {
|
||||
|
@ -1719,7 +1719,7 @@ GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
|
|||
return true;
|
||||
}
|
||||
|
||||
return JS_ForwardGetPropertyTo(cx, proto, id, proxy, vp);
|
||||
return JS_ForwardGetPropertyTo(cx, proto, id, receiver, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -1847,8 +1847,8 @@ ThrowConstructorWithoutNew(JSContext* cx, const char* name);
|
|||
|
||||
bool
|
||||
GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id, bool* found,
|
||||
JS::MutableHandle<JS::Value> vp);
|
||||
JS::Handle<JS::Value> receiver, JS::Handle<jsid> id,
|
||||
bool* found, JS::MutableHandle<JS::Value> vp);
|
||||
|
||||
//
|
||||
bool
|
||||
|
|
|
@ -11039,7 +11039,7 @@ class CGDOMJSProxyHandler_get(ClassMethod):
|
|||
def __init__(self, descriptor):
|
||||
args = [Argument('JSContext*', 'cx'),
|
||||
Argument('JS::Handle<JSObject*>', 'proxy'),
|
||||
Argument('JS::Handle<JSObject*>', 'receiver'),
|
||||
Argument('JS::Handle<JS::Value>', 'receiver'),
|
||||
Argument('JS::Handle<jsid>', 'id'),
|
||||
Argument('JS::MutableHandle<JS::Value>', 'vp')]
|
||||
ClassMethod.__init__(self, "get", "bool", args,
|
||||
|
@ -11094,7 +11094,7 @@ class CGDOMJSProxyHandler_get(ClassMethod):
|
|||
|
||||
getOnPrototype = dedent("""
|
||||
bool foundOnPrototype;
|
||||
if (!GetPropertyOnPrototype(cx, proxy, id, &foundOnPrototype, vp)) {
|
||||
if (!GetPropertyOnPrototype(cx, proxy, receiver, id, &foundOnPrototype, vp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,6 @@ void
|
|||
TextureClient::RecycleTexture(TextureFlags aFlags)
|
||||
{
|
||||
MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE);
|
||||
MOZ_ASSERT(!HasRecycleCallback());
|
||||
|
||||
mAddedToCompositableClient = false;
|
||||
if (mFlags != aFlags) {
|
||||
|
|
|
@ -53,6 +53,24 @@ TextureClientRecycleAllocator::SetMaxPoolSize(uint32_t aMax)
|
|||
mMaxPooledSize = aMax;
|
||||
}
|
||||
|
||||
class TextureClientRecycleTask : public Task
|
||||
{
|
||||
public:
|
||||
explicit TextureClientRecycleTask(TextureClient* aClient, TextureFlags aFlags)
|
||||
: mTextureClient(aClient)
|
||||
, mFlags(aFlags)
|
||||
{}
|
||||
|
||||
virtual void Run() override
|
||||
{
|
||||
mTextureClient->RecycleTexture(mFlags);
|
||||
}
|
||||
|
||||
private:
|
||||
mozilla::RefPtr<TextureClient> mTextureClient;
|
||||
TextureFlags mFlags;
|
||||
};
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClientRecycleAllocator::CreateOrRecycle(gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
|
@ -74,17 +92,18 @@ TextureClientRecycleAllocator::CreateOrRecycle(gfx::SurfaceFormat aFormat,
|
|||
if (!mPooledClients.empty()) {
|
||||
textureHolder = mPooledClients.top();
|
||||
mPooledClients.pop();
|
||||
Task* task = nullptr;
|
||||
// If a pooled TextureClient is not compatible, release it.
|
||||
if (textureHolder->GetTextureClient()->GetFormat() != aFormat ||
|
||||
textureHolder->GetTextureClient()->GetSize() != aSize) {
|
||||
TextureClientReleaseTask* task = new TextureClientReleaseTask(textureHolder->GetTextureClient());
|
||||
// Release TextureClient.
|
||||
task = new TextureClientReleaseTask(textureHolder->GetTextureClient());
|
||||
textureHolder->ClearTextureClient();
|
||||
textureHolder = nullptr;
|
||||
// Release TextureClient.
|
||||
mSurfaceAllocator->GetMessageLoop()->PostTask(FROM_HERE, task);
|
||||
} else {
|
||||
textureHolder->GetTextureClient()->RecycleTexture(aTextureFlags);
|
||||
task = new TextureClientRecycleTask(textureHolder->GetTextureClient(), aTextureFlags);
|
||||
}
|
||||
mSurfaceAllocator->GetMessageLoop()->PostTask(FROM_HERE, task);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -312,17 +312,17 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
|
|||
sum[2] = rZ + gZ + bZ;
|
||||
|
||||
// Build our target vector (see mozilla bug 460629)
|
||||
target[0] = 0.96420;
|
||||
target[1] = 1.00000;
|
||||
target[2] = 0.82491;
|
||||
target[0] = 0.96420f;
|
||||
target[1] = 1.00000f;
|
||||
target[2] = 0.82491f;
|
||||
|
||||
// Our tolerance vector - Recommended by Chris Murphy based on
|
||||
// conversion from the LAB space criterion of no more than 3 in any one
|
||||
// channel. This is similar to, but slightly more tolerant than Adobe's
|
||||
// criterion.
|
||||
tolerance[0] = 0.02;
|
||||
tolerance[1] = 0.02;
|
||||
tolerance[2] = 0.04;
|
||||
tolerance[0] = 0.02f;
|
||||
tolerance[1] = 0.02f;
|
||||
tolerance[2] = 0.04f;
|
||||
|
||||
// Compare with our tolerance
|
||||
for (i = 0; i < 3; ++i) {
|
||||
|
@ -751,7 +751,7 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index
|
|||
lut->e21 = read_s15Fixed16Number(src, offset+40);
|
||||
lut->e22 = read_s15Fixed16Number(src, offset+44);
|
||||
|
||||
for (i = 0; i < lut->num_input_table_entries * in_chan; i++) {
|
||||
for (i = 0; i < (uint32_t)(lut->num_input_table_entries * in_chan); i++) {
|
||||
if (type == LUT8_TYPE) {
|
||||
lut->input_table[i] = uInt8Number_to_float(read_uInt8Number(src, offset + 52 + i * entry_size));
|
||||
} else {
|
||||
|
@ -773,7 +773,7 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index
|
|||
}
|
||||
|
||||
output_offset = clut_offset + clut_size * out_chan * entry_size;
|
||||
for (i = 0; i < lut->num_output_table_entries * out_chan; i++) {
|
||||
for (i = 0; i < (uint32_t)(lut->num_output_table_entries * out_chan); i++) {
|
||||
if (type == LUT8_TYPE) {
|
||||
lut->output_table[i] = uInt8Number_to_float(read_uInt8Number(src, output_offset + i*entry_size));
|
||||
} else {
|
||||
|
@ -1310,7 +1310,7 @@ void qcms_data_from_unicode_path(const wchar_t *path, void **mem, size_t *size)
|
|||
#define ICC_PROFILE_HEADER_LENGTH 128
|
||||
void qcms_data_create_rgb_with_gamma(qcms_CIE_xyY white_point, qcms_CIE_xyYTRIPLE primaries, float gamma, void **mem, size_t *size)
|
||||
{
|
||||
uint32_t length, offset, index, xyz_count, trc_count;
|
||||
uint32_t length, index, xyz_count, trc_count;
|
||||
size_t tag_table_offset, tag_data_offset;
|
||||
void *data;
|
||||
struct matrix colorants;
|
||||
|
|
|
@ -17,9 +17,6 @@ SOURCES += [
|
|||
'transform_util.c',
|
||||
]
|
||||
|
||||
# XXX: We should fix these warnings.
|
||||
ALLOW_COMPILER_WARNINGS = True
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CC']:
|
||||
|
|
|
@ -259,9 +259,9 @@ static struct matrix
|
|||
adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illumination)
|
||||
{
|
||||
struct matrix lam_rigg = {{ // Bradford matrix
|
||||
{ 0.8951, 0.2664, -0.1614 },
|
||||
{ -0.7502, 1.7135, 0.0367 },
|
||||
{ 0.0389, -0.0685, 1.0296 }
|
||||
{ 0.8951f, 0.2664f, -0.1614f },
|
||||
{ -0.7502f, 1.7135f, 0.0367f },
|
||||
{ 0.0389f, -0.0685f, 1.0296f }
|
||||
}};
|
||||
return compute_chromatic_adaption(source_illumination, target_illumination, lam_rigg);
|
||||
}
|
||||
|
@ -1394,7 +1394,7 @@ qcms_transform* qcms_transform_create(
|
|||
return transform;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
/* we need this to avoid crashes when gcc assumes the stack is 128bit aligned */
|
||||
__attribute__((__force_align_arg_pointer__))
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#define _ISOC99_SOURCE /* for INFINITY */
|
||||
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <string.h> //memcpy
|
||||
|
@ -7,10 +5,6 @@
|
|||
#include "transform_util.h"
|
||||
#include "matrix.h"
|
||||
|
||||
#if !defined(INFINITY)
|
||||
#define INFINITY HUGE_VAL
|
||||
#endif
|
||||
|
||||
#define PARAMETRIC_CURVE_TYPE 0x70617261 //'para'
|
||||
|
||||
/* value must be a value between 0 and 1 */
|
||||
|
@ -131,7 +125,7 @@ void compute_curve_gamma_table_type_parametric(float gamma_table[256], float par
|
|||
c = 0;
|
||||
e = 0;
|
||||
f = 0;
|
||||
interval = -INFINITY;
|
||||
interval = -1;
|
||||
} else if(count == 1) {
|
||||
a = parameter[1];
|
||||
b = parameter[2];
|
||||
|
@ -167,12 +161,12 @@ void compute_curve_gamma_table_type_parametric(float gamma_table[256], float par
|
|||
c = 0;
|
||||
e = 0;
|
||||
f = 0;
|
||||
interval = -INFINITY;
|
||||
}
|
||||
interval = -1;
|
||||
}
|
||||
for (X = 0; X < 256; X++) {
|
||||
if (X >= interval) {
|
||||
// XXX The equations are not exactly as definied in the spec but are
|
||||
// algebraic equivilent.
|
||||
// XXX The equations are not exactly as defined in the spec but are
|
||||
// algebraically equivalent.
|
||||
// TODO Should division by 255 be for the whole expression.
|
||||
gamma_table[X] = clamp_float(pow(a * X / 255. + b, y) + c + e);
|
||||
} else {
|
||||
|
|
|
@ -27,6 +27,7 @@ FONT_PREF_LANG(Gujarati, "x-gujr", x_gujr),
|
|||
FONT_PREF_LANG(Gurmukhi, "x-guru", x_guru),
|
||||
FONT_PREF_LANG(Khmer, "x-khmr", x_khmr),
|
||||
FONT_PREF_LANG(Malayalam, "x-mlym", x_mlym),
|
||||
FONT_PREF_LANG(Mathematics, "x-math", x_math),
|
||||
FONT_PREF_LANG(Oriya, "x-orya", x_orya),
|
||||
FONT_PREF_LANG(Telugu, "x-telu", x_telu),
|
||||
FONT_PREF_LANG(Kannada, "x-knda", x_knda),
|
||||
|
|
|
@ -281,5 +281,36 @@ Downscaler::DownscaleInputLine()
|
|||
}
|
||||
}
|
||||
|
||||
Deinterlacer::Deinterlacer(const nsIntSize& aImageSize)
|
||||
: mImageSize(aImageSize)
|
||||
, mBuffer(MakeUnique<uint8_t[]>(mImageSize.width *
|
||||
mImageSize.height *
|
||||
sizeof(uint32_t)))
|
||||
{ }
|
||||
|
||||
uint32_t
|
||||
Deinterlacer::RowSize() const
|
||||
{
|
||||
return mImageSize.width * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
Deinterlacer::RowBuffer(uint32_t aRow)
|
||||
{
|
||||
uint32_t offset = aRow * RowSize();
|
||||
MOZ_ASSERT(offset < mImageSize.width * mImageSize.height * sizeof(uint32_t),
|
||||
"Row is outside of image");
|
||||
return mBuffer.get() + offset;
|
||||
}
|
||||
|
||||
void
|
||||
Deinterlacer::PropagatePassToDownscaler(Downscaler& aDownscaler)
|
||||
{
|
||||
for (int32_t row = 0 ; row < mImageSize.height ; ++row) {
|
||||
memcpy(aDownscaler.RowBuffer(), RowBuffer(row), RowSize());
|
||||
aDownscaler.CommitRow();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -162,6 +162,34 @@ public:
|
|||
|
||||
#endif // MOZ_ENABLE_SKIA
|
||||
|
||||
/**
|
||||
* Deinterlacer is a utility class to allow Downscaler to work with interlaced
|
||||
* images.
|
||||
|
||||
* Since Downscaler needs to receive rows in top-to-bottom or
|
||||
* bottom-to-top order, it can't natively handle interlaced images, in which the
|
||||
* rows arrive in an interleaved order. Deinterlacer solves this problem by
|
||||
* acting as an intermediate buffer that records decoded rows. Unlike
|
||||
* Downscaler, it allows the rows to be written in arbitrary order. After each
|
||||
* pass, calling PropagatePassToDownscaler() will downscale every buffered row
|
||||
* in a single operation. The rows remain in the buffer, so rows that were
|
||||
* written in one pass will be included in subsequent passes.
|
||||
*/
|
||||
class Deinterlacer
|
||||
{
|
||||
public:
|
||||
explicit Deinterlacer(const nsIntSize& aImageSize);
|
||||
|
||||
uint8_t* RowBuffer(uint32_t aRow);
|
||||
void PropagatePassToDownscaler(Downscaler& aDownscaler);
|
||||
|
||||
private:
|
||||
uint32_t RowSize() const;
|
||||
|
||||
nsIntSize mImageSize;
|
||||
UniquePtr<uint8_t[]> mBuffer;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ ShouldDownscaleDuringDecode(const nsCString& aMimeType)
|
|||
return type == DecoderType::JPEG ||
|
||||
type == DecoderType::ICON ||
|
||||
type == DecoderType::PNG ||
|
||||
type == DecoderType::BMP;
|
||||
type == DecoderType::BMP ||
|
||||
type == DecoderType::GIF;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
|
|
|
@ -99,6 +99,54 @@ nsGIFDecoder2::~nsGIFDecoder2()
|
|||
free(mGIFStruct.hold);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGIFDecoder2::SetTargetSize(const nsIntSize& aSize)
|
||||
{
|
||||
// Make sure the size is reasonable.
|
||||
if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Create a downscaler that we'll filter our output through.
|
||||
mDownscaler.emplace(aSize);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
nsGIFDecoder2::GetCurrentRowBuffer()
|
||||
{
|
||||
if (!mDownscaler) {
|
||||
MOZ_ASSERT(!mDeinterlacer, "Deinterlacer without downscaler?");
|
||||
uint32_t bpp = mGIFStruct.images_decoded == 0 ? sizeof(uint32_t)
|
||||
: sizeof(uint8_t);
|
||||
return mImageData + mGIFStruct.irow * mGIFStruct.width * bpp;
|
||||
}
|
||||
|
||||
if (!mDeinterlacer) {
|
||||
return mDownscaler->RowBuffer();
|
||||
}
|
||||
|
||||
return mDeinterlacer->RowBuffer(mGIFStruct.irow);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
nsGIFDecoder2::GetRowBuffer(uint32_t aRow)
|
||||
{
|
||||
MOZ_ASSERT(mGIFStruct.images_decoded == 0,
|
||||
"Calling GetRowBuffer on a frame other than the first suggests "
|
||||
"we're deinterlacing animated frames");
|
||||
MOZ_ASSERT(!mDownscaler || mDeinterlacer,
|
||||
"Can't get buffer for a specific row if downscaling "
|
||||
"but not deinterlacing");
|
||||
|
||||
if (mDownscaler) {
|
||||
return mDeinterlacer->RowBuffer(aRow);
|
||||
}
|
||||
|
||||
return mImageData + aRow * mGIFStruct.width * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
void
|
||||
nsGIFDecoder2::FinishInternal()
|
||||
{
|
||||
|
@ -128,6 +176,15 @@ nsGIFDecoder2::FlushImageData(uint32_t fromRow, uint32_t rows)
|
|||
void
|
||||
nsGIFDecoder2::FlushImageData()
|
||||
{
|
||||
if (mDownscaler) {
|
||||
if (mDownscaler->HasInvalidation()) {
|
||||
DownscalerInvalidRect invalidRect = mDownscaler->TakeInvalidRect();
|
||||
PostInvalidation(invalidRect.mOriginalSizeRect,
|
||||
Some(invalidRect.mTargetSizeRect));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mCurrentPass - mLastFlushedPass) {
|
||||
case 0: // same pass
|
||||
if (mCurrentRow - mLastFlushedRow) {
|
||||
|
@ -202,21 +259,44 @@ nsGIFDecoder2::BeginImageFrame(uint16_t aDepth)
|
|||
|
||||
CheckForTransparency(frameRect);
|
||||
|
||||
// Make sure there's no animation if we're downscaling.
|
||||
MOZ_ASSERT_IF(mDownscaler, !GetImageMetadata().HasAnimation());
|
||||
|
||||
IntSize targetSize = mDownscaler ? mDownscaler->TargetSize()
|
||||
: GetSize();
|
||||
|
||||
// Rescale the frame rect for the target size.
|
||||
IntRect targetFrameRect = frameRect;
|
||||
if (mDownscaler) {
|
||||
IntSize originalSize = GetSize();
|
||||
targetFrameRect.ScaleRoundOut(double(targetSize.width) / originalSize.width,
|
||||
double(targetSize.height) / originalSize.height);
|
||||
}
|
||||
|
||||
// Use correct format, RGB for first frame, PAL for following frames
|
||||
// and include transparency to allow for optimization of opaque images
|
||||
nsresult rv = NS_OK;
|
||||
if (mGIFStruct.images_decoded) {
|
||||
// Image data is stored with original depth and palette.
|
||||
rv = AllocateFrame(mGIFStruct.images_decoded, GetSize(),
|
||||
frameRect, format, aDepth);
|
||||
rv = AllocateFrame(mGIFStruct.images_decoded, targetSize,
|
||||
targetFrameRect, format, aDepth);
|
||||
} else {
|
||||
// Regardless of depth of input, the first frame is decoded into 24bit RGB.
|
||||
rv = AllocateFrame(mGIFStruct.images_decoded, GetSize(),
|
||||
frameRect, format);
|
||||
rv = AllocateFrame(mGIFStruct.images_decoded, targetSize,
|
||||
targetFrameRect, format);
|
||||
}
|
||||
|
||||
mCurrentFrameIndex = mGIFStruct.images_decoded;
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mDownscaler) {
|
||||
rv = mDownscaler->BeginFrame(frameRect.Size(), mImageData,
|
||||
mGIFStruct.is_transparent);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -237,10 +317,15 @@ nsGIFDecoder2::EndImageFrame()
|
|||
// This will clear the remaining bits of the placeholder. (Bug 37589)
|
||||
const uint32_t realFrameHeight = mGIFStruct.height + mGIFStruct.y_offset;
|
||||
if (realFrameHeight < mGIFStruct.screen_height) {
|
||||
nsIntRect r(0, realFrameHeight,
|
||||
mGIFStruct.screen_width,
|
||||
mGIFStruct.screen_height - realFrameHeight);
|
||||
PostInvalidation(r);
|
||||
if (mDownscaler) {
|
||||
IntRect targetRect = IntRect(IntPoint(), mDownscaler->TargetSize());
|
||||
PostInvalidation(IntRect(IntPoint(), GetSize()), Some(targetRect));
|
||||
} else {
|
||||
nsIntRect r(0, realFrameHeight,
|
||||
mGIFStruct.screen_width,
|
||||
mGIFStruct.screen_height - realFrameHeight);
|
||||
PostInvalidation(r);
|
||||
}
|
||||
}
|
||||
|
||||
// The first frame was preallocated with alpha; if it wasn't transparent, we
|
||||
|
@ -291,8 +376,11 @@ nsGIFDecoder2::EndImageFrame()
|
|||
uint32_t
|
||||
nsGIFDecoder2::OutputRow()
|
||||
{
|
||||
int drow_start, drow_end;
|
||||
drow_start = drow_end = mGIFStruct.irow;
|
||||
// Initialize the region in which we're duplicating rows (for the
|
||||
// Haeberli-inspired hack below) to |irow|, which is the row we're writing to
|
||||
// now.
|
||||
int drow_start = mGIFStruct.irow;
|
||||
int drow_end = mGIFStruct.irow;
|
||||
|
||||
// Protect against too much image data
|
||||
if ((unsigned)drow_start >= mGIFStruct.height) {
|
||||
|
@ -329,8 +417,7 @@ nsGIFDecoder2::OutputRow()
|
|||
}
|
||||
|
||||
// Row to process
|
||||
const uint32_t bpr = sizeof(uint32_t) * mGIFStruct.width;
|
||||
uint8_t* rowp = mImageData + (mGIFStruct.irow * bpr);
|
||||
uint8_t* rowp = GetCurrentRowBuffer();
|
||||
|
||||
// Convert color indices to Cairo pixels
|
||||
uint8_t* from = rowp + mGIFStruct.width;
|
||||
|
@ -351,12 +438,24 @@ nsGIFDecoder2::OutputRow()
|
|||
}
|
||||
}
|
||||
|
||||
// Duplicate rows
|
||||
// If we're downscaling but not deinterlacing, we're done with this row and
|
||||
// can commit it now. Otherwise, we'll let Deinterlacer do the committing
|
||||
// when we call PropagatePassToDownscaler() at the end of this pass.
|
||||
if (mDownscaler && !mDeinterlacer) {
|
||||
mDownscaler->CommitRow();
|
||||
}
|
||||
|
||||
if (drow_end > drow_start) {
|
||||
// irow is the current row filled
|
||||
// Duplicate rows if needed to reduce the "venetian blind" effect mentioned
|
||||
// above. This writes out scanlines of the image in a way that isn't ordered
|
||||
// vertically, which is incompatible with the filter that we use for
|
||||
// downscale-during-decode, so we can't do this if we're downscaling.
|
||||
MOZ_ASSERT_IF(mDownscaler, mDeinterlacer);
|
||||
const uint32_t bpr = sizeof(uint32_t) * mGIFStruct.width;
|
||||
for (int r = drow_start; r <= drow_end; r++) {
|
||||
// Skip the row we wrote to above; that's what we're copying *from*.
|
||||
if (r != int(mGIFStruct.irow)) {
|
||||
memcpy(mImageData + (r * bpr), rowp, bpr);
|
||||
memcpy(GetRowBuffer(r), rowp, bpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -369,9 +468,12 @@ nsGIFDecoder2::OutputRow()
|
|||
}
|
||||
|
||||
if (!mGIFStruct.interlaced) {
|
||||
MOZ_ASSERT(!mDeinterlacer);
|
||||
mGIFStruct.irow++;
|
||||
} else {
|
||||
static const uint8_t kjump[5] = { 1, 8, 8, 4, 2 };
|
||||
int currentPass = mGIFStruct.ipass;
|
||||
|
||||
do {
|
||||
// Row increments resp. per 8,8,4,2 rows
|
||||
mGIFStruct.irow += kjump[mGIFStruct.ipass];
|
||||
|
@ -381,6 +483,15 @@ nsGIFDecoder2::OutputRow()
|
|||
mGIFStruct.ipass++;
|
||||
}
|
||||
} while (mGIFStruct.irow >= mGIFStruct.height);
|
||||
|
||||
// We've finished a pass. If we're downscaling, it's time to propagate the
|
||||
// rows we've decoded so far from our Deinterlacer to our Downscaler.
|
||||
if (mGIFStruct.ipass > currentPass && mDownscaler) {
|
||||
MOZ_ASSERT(mDeinterlacer);
|
||||
mDeinterlacer->PropagatePassToDownscaler(*mDownscaler);
|
||||
FlushImageData();
|
||||
mDownscaler->ResetForNextProgressivePass();
|
||||
}
|
||||
}
|
||||
|
||||
return --mGIFStruct.rows_remaining;
|
||||
|
@ -413,17 +524,13 @@ nsGIFDecoder2::DoLzw(const uint8_t* q)
|
|||
uint8_t* stack = mGIFStruct.stack;
|
||||
uint8_t* rowp = mGIFStruct.rowp;
|
||||
|
||||
uint32_t bpr = mGIFStruct.width;
|
||||
if (!mGIFStruct.images_decoded) {
|
||||
bpr *= sizeof(uint32_t);
|
||||
}
|
||||
uint8_t* rowend = mImageData + (bpr * mGIFStruct.irow) + mGIFStruct.width;
|
||||
uint8_t* rowend = GetCurrentRowBuffer() + mGIFStruct.width;
|
||||
|
||||
#define OUTPUT_ROW() \
|
||||
PR_BEGIN_MACRO \
|
||||
if (!OutputRow()) \
|
||||
goto END; \
|
||||
rowp = mImageData + mGIFStruct.irow * bpr; \
|
||||
rowp = GetCurrentRowBuffer(); \
|
||||
rowend = rowp + mGIFStruct.width; \
|
||||
PR_END_MACRO
|
||||
|
||||
|
@ -934,12 +1041,19 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount)
|
|||
// below, so that RasterImage can detect that this happened.
|
||||
PostIsAnimated(/* aFirstFrameTimeout = */ 0);
|
||||
}
|
||||
|
||||
if (IsFirstFrameDecode()) {
|
||||
// We're about to get a second frame, but we only want the first. Stop
|
||||
// decoding now.
|
||||
mGIFStruct.state = gif_done;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mDownscaler) {
|
||||
MOZ_ASSERT_UNREACHABLE("Doing downscale-during-decode "
|
||||
"for an animated image?");
|
||||
mDownscaler.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Get image offsets, with respect to the screen origin
|
||||
|
@ -1025,14 +1139,22 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount)
|
|||
// offset. Otherwise, the area may never be refreshed and the
|
||||
// placeholder will remain on the screen. (Bug 37589)
|
||||
if (mGIFStruct.y_offset > 0) {
|
||||
nsIntRect r(0, 0, mGIFStruct.screen_width, mGIFStruct.y_offset);
|
||||
PostInvalidation(r);
|
||||
if (mDownscaler) {
|
||||
IntRect targetRect = IntRect(IntPoint(), mDownscaler->TargetSize());
|
||||
PostInvalidation(IntRect(IntPoint(), GetSize()), Some(targetRect));
|
||||
} else {
|
||||
nsIntRect r(0, 0, mGIFStruct.screen_width, mGIFStruct.y_offset);
|
||||
PostInvalidation(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (q[8] & 0x40) {
|
||||
mGIFStruct.interlaced = true;
|
||||
mGIFStruct.ipass = 1;
|
||||
if (mDownscaler) {
|
||||
mDeinterlacer.emplace(mDownscaler->OriginalSize());
|
||||
}
|
||||
} else {
|
||||
mGIFStruct.interlaced = false;
|
||||
mGIFStruct.ipass = 0;
|
||||
|
@ -1044,7 +1166,7 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount)
|
|||
// Clear state from last image
|
||||
mGIFStruct.irow = 0;
|
||||
mGIFStruct.rows_remaining = mGIFStruct.height;
|
||||
mGIFStruct.rowp = mImageData;
|
||||
mGIFStruct.rowp = GetCurrentRowBuffer();
|
||||
|
||||
// Depth of colors is determined by colormap
|
||||
// (q[8] & 0x80) indicates local colormap
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define mozilla_image_decoders_nsGIFDecoder2_h
|
||||
|
||||
#include "Decoder.h"
|
||||
#include "Downscaler.h"
|
||||
|
||||
#include "GIF2.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -24,6 +25,8 @@ class nsGIFDecoder2 : public Decoder
|
|||
public:
|
||||
~nsGIFDecoder2();
|
||||
|
||||
nsresult SetTargetSize(const nsIntSize& aSize) override;
|
||||
|
||||
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
|
||||
virtual void FinishInternal() override;
|
||||
virtual Telemetry::ID SpeedHistogram() override;
|
||||
|
@ -34,6 +37,9 @@ private:
|
|||
// Decoders should only be instantiated via DecoderFactory.
|
||||
explicit nsGIFDecoder2(RasterImage* aImage);
|
||||
|
||||
uint8_t* GetCurrentRowBuffer();
|
||||
uint8_t* GetRowBuffer(uint32_t aRow);
|
||||
|
||||
// These functions will be called when the decoder has a decoded row,
|
||||
// frame size information, etc.
|
||||
void BeginGIF();
|
||||
|
@ -67,6 +73,8 @@ private:
|
|||
bool mSawTransparency;
|
||||
|
||||
gif_struct mGIFStruct;
|
||||
Maybe<Downscaler> mDownscaler;
|
||||
Maybe<Deinterlacer> mDeinterlacer;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include <mach/vm_map.h>
|
||||
#include <mach/mach_port.h>
|
||||
#include <mach/mach_vm.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include "SharedMemoryBasic.h"
|
||||
#include "chrome/common/mach_ipc_mac.h"
|
||||
|
||||
|
|
|
@ -66,9 +66,8 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
|
|||
ReturnStatus* rs, bool* bp) {
|
||||
return Answer::RecvHasOwn(ObjectId::deserialize(objId), id, rs, bp);
|
||||
}
|
||||
bool RecvGet(const uint64_t& objId, const ObjectVariant& receiverVar,
|
||||
const JSIDVariant& id,
|
||||
ReturnStatus* rs, JSVariant* result) {
|
||||
bool RecvGet(const uint64_t& objId, const JSVariant& receiverVar, const JSIDVariant& id,
|
||||
ReturnStatus* rs, JSVariant* result) {
|
||||
return Answer::RecvGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
|
||||
}
|
||||
bool RecvSet(const uint64_t& objId, const JSIDVariant& id, const JSVariant& value,
|
||||
|
@ -155,8 +154,7 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
|
|||
ReturnStatus* rs, bool* bp) {
|
||||
return Base::SendHasOwn(objId.serialize(), id, rs, bp);
|
||||
}
|
||||
bool SendGet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
const JSIDVariant& id,
|
||||
bool SendGet(const ObjectId& objId, const JSVariant& receiverVar, const JSIDVariant& id,
|
||||
ReturnStatus* rs, JSVariant* result) {
|
||||
return Base::SendGet(objId.serialize(), receiverVar, id, rs, result);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ both:
|
|||
|
||||
prio(high) sync Has(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
|
||||
prio(high) sync HasOwn(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
|
||||
prio(high) sync Get(uint64_t objId, ObjectVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
|
||||
prio(high) sync Get(uint64_t objId, JSVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
|
||||
prio(high) sync Set(uint64_t objId, JSIDVariant id, JSVariant value, JSVariant receiver) returns (ReturnStatus rs);
|
||||
|
||||
prio(high) sync IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
|
||||
|
|
|
@ -272,7 +272,7 @@ WrapperAnswer::RecvHasOwn(const ObjectId& objId, const JSIDVariant& idVar, Retur
|
|||
}
|
||||
|
||||
bool
|
||||
WrapperAnswer::RecvGet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
WrapperAnswer::RecvGet(const ObjectId& objId, const JSVariant& receiverVar,
|
||||
const JSIDVariant& idVar, ReturnStatus* rs, JSVariant* result)
|
||||
{
|
||||
// We may run scripted getters.
|
||||
|
@ -289,8 +289,8 @@ WrapperAnswer::RecvGet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
|||
if (!obj)
|
||||
return fail(aes, rs);
|
||||
|
||||
RootedObject receiver(cx, fromObjectVariant(cx, receiverVar));
|
||||
if (!receiver)
|
||||
RootedValue receiver(cx);
|
||||
if (!fromVariant(cx, receiverVar, &receiver))
|
||||
return fail(aes, rs);
|
||||
|
||||
RootedId id(cx);
|
||||
|
|
|
@ -39,7 +39,7 @@ class WrapperAnswer : public virtual JavaScriptShared
|
|||
ReturnStatus* rs, bool* foundp);
|
||||
bool RecvHasOwn(const ObjectId& objId, const JSIDVariant& id,
|
||||
ReturnStatus* rs, bool* foundp);
|
||||
bool RecvGet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
bool RecvGet(const ObjectId& objId, const JSVariant& receiverVar,
|
||||
const JSIDVariant& id,
|
||||
ReturnStatus* rs, JSVariant* result);
|
||||
bool RecvSet(const ObjectId& objId, const JSIDVariant& id, const JSVariant& value,
|
||||
|
|
|
@ -111,7 +111,7 @@ class CPOWProxyHandler : public BaseProxyHandler
|
|||
ObjectOpResult& result) const override;
|
||||
virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
|
||||
virtual bool has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const override;
|
||||
virtual bool set(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
|
||||
JS::HandleValue receiver, JS::ObjectOpResult& result) const override;
|
||||
|
@ -341,7 +341,7 @@ WrapperOwner::hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp)
|
|||
}
|
||||
|
||||
bool
|
||||
CPOWProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
CPOWProxyHandler::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const
|
||||
{
|
||||
FORWARD(get, (cx, proxy, receiver, id, vp));
|
||||
|
@ -458,13 +458,13 @@ WrapperOwner::DOMQI(JSContext* cx, JS::HandleObject proxy, JS::CallArgs& args)
|
|||
}
|
||||
|
||||
bool
|
||||
WrapperOwner::get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
WrapperOwner::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
ObjectId objId = idOf(proxy);
|
||||
|
||||
ObjectVariant receiverVar;
|
||||
if (!toObjectVariant(cx, receiver, &receiverVar))
|
||||
JSVariant receiverVar;
|
||||
if (!toVariant(cx, receiver, &receiverVar))
|
||||
return false;
|
||||
|
||||
JSIDVariant idVar;
|
||||
|
|
|
@ -40,7 +40,7 @@ class WrapperOwner : public virtual JavaScriptShared
|
|||
bool preventExtensions(JSContext* cx, JS::HandleObject proxy, JS::ObjectOpResult& result);
|
||||
bool isExtensible(JSContext* cx, JS::HandleObject proxy, bool* extensible);
|
||||
bool has(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, bool* bp);
|
||||
bool get(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||
bool get(JSContext* cx, JS::HandleObject proxy, JS::HandleValue receiver,
|
||||
JS::HandleId id, JS::MutableHandleValue vp);
|
||||
bool set(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
|
||||
JS::HandleValue receiver, JS::ObjectOpResult& result);
|
||||
|
@ -125,7 +125,7 @@ class WrapperOwner : public virtual JavaScriptShared
|
|||
ReturnStatus* rs, bool* bp) = 0;
|
||||
virtual bool SendHasOwn(const ObjectId& objId, const JSIDVariant& id,
|
||||
ReturnStatus* rs, bool* bp) = 0;
|
||||
virtual bool SendGet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
virtual bool SendGet(const ObjectId& objId, const JSVariant& receiverVar,
|
||||
const JSIDVariant& id,
|
||||
ReturnStatus* rs, JSVariant* result) = 0;
|
||||
virtual bool SendSet(const ObjectId& objId, const JSIDVariant& id, const JSVariant& value,
|
||||
|
|
|
@ -358,7 +358,7 @@ typedef bool
|
|||
typedef bool
|
||||
(* HasPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
|
||||
typedef bool
|
||||
(* GetPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
|
||||
(* GetPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleValue receiver, JS::HandleId id,
|
||||
JS::MutableHandleValue vp);
|
||||
typedef bool
|
||||
(* SetPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
|
||||
|
|
|
@ -293,7 +293,7 @@ class JS_FRIEND_API(BaseProxyHandler)
|
|||
* They do not follow any standard. When in doubt, override them.
|
||||
*/
|
||||
virtual bool has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const;
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const;
|
||||
virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result) const;
|
||||
|
@ -394,7 +394,7 @@ class JS_FRIEND_API(DirectProxyHandler) : public BaseProxyHandler
|
|||
virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
|
||||
virtual bool has(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
bool* bp) const override;
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const override;
|
||||
virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result) const override;
|
||||
|
|
|
@ -1793,7 +1793,7 @@ TypedObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool*
|
|||
}
|
||||
|
||||
bool
|
||||
TypedObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
TypedObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
Rooted<TypedObject*> typedObj(cx, &obj->as<TypedObject>());
|
||||
|
@ -1850,7 +1850,7 @@ TypedObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleObject recei
|
|||
}
|
||||
|
||||
bool
|
||||
TypedObject::obj_getElement(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
TypedObject::obj_getElement(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
uint32_t index, MutableHandleValue vp)
|
||||
{
|
||||
MOZ_ASSERT(obj->is<TypedObject>());
|
||||
|
|
|
@ -529,10 +529,10 @@ class TypedObject : public JSObject
|
|||
|
||||
static bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
|
||||
|
||||
static bool obj_getProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
static bool obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp);
|
||||
|
||||
static bool obj_getElement(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
static bool obj_getElement(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
uint32_t index, MutableHandleValue vp);
|
||||
|
||||
static bool obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
|
|
|
@ -6869,8 +6869,9 @@ ICGetProp_DOMProxyShadowed::Compiler::getStub(ICStubSpace* space)
|
|||
static bool
|
||||
ProxyGet(JSContext* cx, HandleObject proxy, HandlePropertyName name, MutableHandleValue vp)
|
||||
{
|
||||
RootedValue receiver(cx, ObjectValue(*proxy));
|
||||
RootedId id(cx, NameToId(name));
|
||||
return Proxy::get(cx, proxy, proxy, id, vp);
|
||||
return Proxy::get(cx, proxy, receiver, id, vp);
|
||||
}
|
||||
|
||||
typedef bool (*ProxyGetFn)(JSContext* cx, HandleObject proxy, HandlePropertyName name,
|
||||
|
|
|
@ -1539,6 +1539,20 @@ PushObjectOpResult(MacroAssembler& masm)
|
|||
masm.Push(ImmWord(ObjectOpResult::Uninitialized));
|
||||
}
|
||||
|
||||
static bool
|
||||
ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
RootedValue receiver(cx, ObjectValue(*proxy));
|
||||
return Proxy::get(cx, proxy, receiver, id, vp);
|
||||
}
|
||||
|
||||
static bool
|
||||
ProxyCallProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
RootedValue receiver(cx, ObjectValue(*proxy));
|
||||
return Proxy::callProp(cx, proxy, receiver, id, vp);
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
|
||||
PropertyName* name, LiveRegisterSet liveRegs, Register object,
|
||||
|
@ -1552,8 +1566,8 @@ EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
|
|||
AllocatableRegisterSet regSet(RegisterSet::All());
|
||||
regSet.take(AnyRegister(object));
|
||||
|
||||
// Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
// MutableHandleValue vp)
|
||||
// ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
// MutableHandleValue vp)
|
||||
Register argJSContextReg = regSet.takeAnyGeneral();
|
||||
Register argProxyReg = regSet.takeAnyGeneral();
|
||||
Register argIdReg = regSet.takeAnyGeneral();
|
||||
|
@ -1561,9 +1575,9 @@ EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
|
|||
|
||||
Register scratch = regSet.takeAnyGeneral();
|
||||
|
||||
void* getFunction = JSOp(*pc) == JSOP_CALLPROP ?
|
||||
JS_FUNC_TO_DATA_PTR(void*, Proxy::callProp) :
|
||||
JS_FUNC_TO_DATA_PTR(void*, Proxy::get);
|
||||
void* getFunction = JSOp(*pc) == JSOP_CALLPROP ?
|
||||
JS_FUNC_TO_DATA_PTR(void*, ProxyCallProperty) :
|
||||
JS_FUNC_TO_DATA_PTR(void*, ProxyGetProperty);
|
||||
|
||||
// Push stubCode for marking.
|
||||
attacher.pushStubCodePointer(masm);
|
||||
|
@ -1576,9 +1590,7 @@ EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
|
|||
masm.Push(propId, scratch);
|
||||
masm.moveStackPtrTo(argIdReg);
|
||||
|
||||
// Pushing object and receiver. Both are the same, so Handle to one is equivalent to
|
||||
// handle to other.
|
||||
masm.Push(object);
|
||||
// Push the proxy. Also used as receiver.
|
||||
masm.Push(object);
|
||||
masm.moveStackPtrTo(argProxyReg);
|
||||
|
||||
|
@ -1592,7 +1604,6 @@ EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
|
|||
masm.setupUnalignedABICall(scratch);
|
||||
masm.passABIArg(argJSContextReg);
|
||||
masm.passABIArg(argProxyReg);
|
||||
masm.passABIArg(argProxyReg);
|
||||
masm.passABIArg(argIdReg);
|
||||
masm.passABIArg(argVpReg);
|
||||
masm.callWithABI(getFunction);
|
||||
|
@ -2284,9 +2295,7 @@ EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
|
|||
masm.Push(propId, scratch);
|
||||
masm.moveStackPtrTo(argIdReg);
|
||||
|
||||
// Pushing object and receiver. Both are the same, so Handle to one is equivalent to
|
||||
// handle to other.
|
||||
masm.Push(object);
|
||||
// Push object.
|
||||
masm.Push(object);
|
||||
masm.moveStackPtrTo(argProxyReg);
|
||||
|
||||
|
|
|
@ -1401,7 +1401,6 @@ MarkJitExitFrame(JSTracer* trc, const JitFrameIterator& frame)
|
|||
TraceRoot(trc, oolproxy->vp(), "ion-ool-proxy-vp");
|
||||
TraceRoot(trc, oolproxy->id(), "ion-ool-proxy-id");
|
||||
TraceRoot(trc, oolproxy->proxy(), "ion-ool-proxy-proxy");
|
||||
TraceRoot(trc, oolproxy->receiver(), "ion-ool-proxy-receiver");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -699,8 +699,8 @@ class IonOOLSetterOpExitFrameLayout : public IonOOLPropertyOpExitFrameLayout
|
|||
}
|
||||
};
|
||||
|
||||
// Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
// MutableHandleValue vp)
|
||||
// ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp)
|
||||
// ProxyCallProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp)
|
||||
// ProxySetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp,
|
||||
// bool strict)
|
||||
class IonOOLProxyExitFrameLayout
|
||||
|
@ -712,9 +712,6 @@ class IonOOLProxyExitFrameLayout
|
|||
// The proxy object.
|
||||
JSObject* proxy_;
|
||||
|
||||
// Object for HandleObject
|
||||
JSObject* receiver_;
|
||||
|
||||
// id for HandleId
|
||||
jsid id_;
|
||||
|
||||
|
@ -746,9 +743,6 @@ class IonOOLProxyExitFrameLayout
|
|||
inline jsid* id() {
|
||||
return &id_;
|
||||
}
|
||||
inline JSObject** receiver() {
|
||||
return &receiver_;
|
||||
}
|
||||
inline JSObject** proxy() {
|
||||
return &proxy_;
|
||||
}
|
||||
|
|
|
@ -2920,12 +2920,16 @@ JS_GetPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name,
|
|||
JS_PUBLIC_API(bool)
|
||||
JS_GetPropertyById(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
return JS_ForwardGetPropertyTo(cx, obj, id, obj, vp);
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, id);
|
||||
|
||||
return GetProperty(cx, obj, obj, id, vp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ForwardGetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject onBehalfOf,
|
||||
JS::MutableHandleValue vp)
|
||||
JS_ForwardGetPropertyTo(JSContext* cx, HandleObject obj, HandleId id, HandleValue onBehalfOf,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
@ -2935,9 +2939,13 @@ JS_ForwardGetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_GetElement(JSContext* cx, HandleObject objArg, uint32_t index, MutableHandleValue vp)
|
||||
JS_GetElement(JSContext* cx, HandleObject obj, uint32_t index, MutableHandleValue vp)
|
||||
{
|
||||
return JS_ForwardGetElementTo(cx, objArg, index, objArg, vp);
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
|
||||
return GetElement(cx, obj, obj, index, vp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
|
|
@ -2853,7 +2853,7 @@ extern JS_PUBLIC_API(bool)
|
|||
JS_GetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_ForwardGetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject onBehalfOf,
|
||||
JS_ForwardGetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue onBehalfOf,
|
||||
JS::MutableHandleValue vp);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
|
|
|
@ -377,7 +377,7 @@ proxy_DefineProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
|||
extern JS_FRIEND_API(bool)
|
||||
proxy_HasProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
|
||||
extern JS_FRIEND_API(bool)
|
||||
proxy_GetProperty(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
|
||||
proxy_GetProperty(JSContext* cx, JS::HandleObject obj, JS::HandleValue receiver, JS::HandleId id,
|
||||
JS::MutableHandleValue vp);
|
||||
extern JS_FRIEND_API(bool)
|
||||
proxy_SetProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue bp,
|
||||
|
|
|
@ -819,30 +819,65 @@ HasProperty(JSContext* cx, HandleObject obj, PropertyName* name, bool* foundp);
|
|||
* `receiver[id]`, and we've already searched the prototype chain up to `obj`.
|
||||
*/
|
||||
inline bool
|
||||
GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp);
|
||||
|
||||
inline bool
|
||||
GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, PropertyName* name,
|
||||
GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, PropertyName* name,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return GetProperty(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
RootedValue receiverValue(cx, ObjectValue(*receiver));
|
||||
return GetProperty(cx, obj, receiverValue, id, vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, PropertyName* name,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
RootedValue receiverValue(cx, ObjectValue(*receiver));
|
||||
return GetProperty(cx, obj, receiverValue, name, vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetElement(JSContext* cx, HandleObject obj, HandleValue receiver, uint32_t index,
|
||||
MutableHandleValue vp);
|
||||
|
||||
inline bool
|
||||
GetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index,
|
||||
MutableHandleValue vp);
|
||||
|
||||
inline bool
|
||||
GetPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, jsid id, Value* vp);
|
||||
GetPropertyNoGC(JSContext* cx, JSObject* obj, const Value& receiver, jsid id, Value* vp);
|
||||
|
||||
inline bool
|
||||
GetPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, jsid id, Value* vp)
|
||||
{
|
||||
return GetPropertyNoGC(cx, obj, ObjectValue(*receiver), id, vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetPropertyNoGC(JSContext* cx, JSObject* obj, const Value& receiver, PropertyName* name, Value* vp)
|
||||
{
|
||||
return GetPropertyNoGC(cx, obj, receiver, NameToId(name), vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, PropertyName* name, Value* vp)
|
||||
{
|
||||
return GetPropertyNoGC(cx, obj, receiver, NameToId(name), vp);
|
||||
return GetPropertyNoGC(cx, obj, ObjectValue(*receiver), name, vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetElementNoGC(JSContext* cx, JSObject* obj, const Value& receiver, uint32_t index, Value* vp);
|
||||
|
||||
inline bool
|
||||
GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t index, Value* vp);
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ js::HasProperty(JSContext* cx, HandleObject obj, PropertyName* name, bool* found
|
|||
}
|
||||
|
||||
inline bool
|
||||
js::GetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index,
|
||||
js::GetElement(JSContext* cx, HandleObject obj, HandleValue receiver, uint32_t index,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
RootedId id(cx);
|
||||
|
@ -190,7 +190,15 @@ js::GetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t
|
|||
}
|
||||
|
||||
inline bool
|
||||
js::GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t index, Value* vp)
|
||||
js::GetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
RootedValue receiverValue(cx, ObjectValue(*receiver));
|
||||
return GetElement(cx, obj, receiverValue, index, vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::GetElementNoGC(JSContext* cx, JSObject* obj, const Value& receiver, uint32_t index, Value* vp)
|
||||
{
|
||||
if (obj->getOps()->getProperty)
|
||||
return false;
|
||||
|
@ -200,6 +208,12 @@ js::GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t in
|
|||
return GetPropertyNoGC(cx, obj, receiver, INT_TO_JSID(index), vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t index, Value* vp)
|
||||
{
|
||||
return GetElementNoGC(cx, obj, ObjectValue(*receiver), index, vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::DeleteProperty(JSContext* cx, HandleObject obj, HandleId id, ObjectOpResult& result)
|
||||
{
|
||||
|
|
|
@ -133,7 +133,7 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
|
|||
ObjectOpResult& result) const override;
|
||||
virtual bool isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const override;
|
||||
virtual bool has(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
|
||||
virtual bool get(JSContext* cx, HandleObject wrapper, HandleObject receiver,
|
||||
virtual bool get(JSContext* cx, HandleObject wrapper, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const override;
|
||||
virtual bool set(JSContext* cx, HandleObject wrapper, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result) const override;
|
||||
|
@ -191,7 +191,7 @@ class JS_FRIEND_API(OpaqueCrossCompartmentWrapper) : public CrossCompartmentWrap
|
|||
virtual bool isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const override;
|
||||
virtual bool has(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
bool* bp) const override;
|
||||
virtual bool get(JSContext* cx, HandleObject wrapper, HandleObject receiver,
|
||||
virtual bool get(JSContext* cx, HandleObject wrapper, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const override;
|
||||
virtual bool set(JSContext* cx, HandleObject wrapper, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result) const override;
|
||||
|
|
|
@ -65,7 +65,7 @@ BaseProxyHandler::hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* b
|
|||
}
|
||||
|
||||
bool
|
||||
BaseProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
BaseProxyHandler::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id, GET);
|
||||
|
|
|
@ -153,10 +153,10 @@ CrossCompartmentWrapper::hasOwn(JSContext* cx, HandleObject wrapper, HandleId id
|
|||
}
|
||||
|
||||
bool
|
||||
CrossCompartmentWrapper::get(JSContext* cx, HandleObject wrapper, HandleObject receiver,
|
||||
CrossCompartmentWrapper::get(JSContext* cx, HandleObject wrapper, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const
|
||||
{
|
||||
RootedObject receiverCopy(cx, receiver);
|
||||
RootedValue receiverCopy(cx, receiver);
|
||||
{
|
||||
AutoCompartment call(cx, wrappedObject(wrapper));
|
||||
if (!cx->compartment()->wrap(cx, &receiverCopy))
|
||||
|
|
|
@ -217,7 +217,7 @@ DirectProxyHandler::hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool*
|
|||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
DirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id, GET);
|
||||
|
|
|
@ -95,7 +95,7 @@ OpaqueCrossCompartmentWrapper::has(JSContext* cx, HandleObject wrapper, HandleId
|
|||
}
|
||||
|
||||
bool
|
||||
OpaqueCrossCompartmentWrapper::get(JSContext* cx, HandleObject wrapper, HandleObject receiver,
|
||||
OpaqueCrossCompartmentWrapper::get(JSContext* cx, HandleObject wrapper, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const
|
||||
{
|
||||
return BaseProxyHandler::get(cx, wrapper, receiver, id, vp);
|
||||
|
|
|
@ -271,7 +271,7 @@ OuterizeValue(JSContext* cx, HandleValue v)
|
|||
}
|
||||
|
||||
bool
|
||||
Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver_, HandleId id,
|
||||
Proxy::get(JSContext* cx, HandleObject proxy, HandleValue receiver_, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
|
@ -283,7 +283,7 @@ Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver_, HandleId i
|
|||
|
||||
// Outerize the receiver. Proxy handlers shouldn't have to know about
|
||||
// the Window/WindowProxy distinction.
|
||||
RootedObject receiver(cx, GetOuterObject(cx, receiver_));
|
||||
RootedValue receiver(cx, OuterizeValue(cx, receiver_));
|
||||
|
||||
if (handler->hasPrototype()) {
|
||||
bool own;
|
||||
|
@ -303,7 +303,7 @@ Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver_, HandleId i
|
|||
}
|
||||
|
||||
bool
|
||||
Proxy::callProp(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
Proxy::callProp(JSContext* cx, HandleObject proxy, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
// The inline caches need an access point for JSOP_CALLPROP sites that accounts
|
||||
|
@ -594,7 +594,7 @@ js::proxy_HasProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool
|
|||
}
|
||||
|
||||
bool
|
||||
js::proxy_GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
js::proxy_GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
return Proxy::get(cx, obj, receiver, id, vp);
|
||||
|
|
|
@ -40,7 +40,7 @@ class Proxy
|
|||
ObjectOpResult& result);
|
||||
static bool setImmutablePrototype(JSContext* cx, HandleObject proxy, bool* succeeded);
|
||||
static bool has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp);
|
||||
static bool get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
static bool get(JSContext* cx, HandleObject proxy, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp);
|
||||
static bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result);
|
||||
|
@ -72,8 +72,9 @@ class Proxy
|
|||
static void trace(JSTracer* trc, JSObject* obj);
|
||||
|
||||
/* IC entry path for handling __noSuchMethod__ on access. */
|
||||
static bool callProp(JSContext* cx, HandleObject proxy, HandleObject reveiver, HandleId id,
|
||||
static bool callProp(JSContext* cx, HandleObject proxy, HandleValue reveiver, HandleId id,
|
||||
MutableHandleValue vp);
|
||||
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
|
|
@ -846,7 +846,7 @@ ScriptedDirectProxyHandler::has(JSContext* cx, HandleObject proxy, HandleId id,
|
|||
|
||||
// ES6 (22 May, 2014) 9.5.8 Proxy.[[GetP]](P, Receiver)
|
||||
bool
|
||||
ScriptedDirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
ScriptedDirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const
|
||||
{
|
||||
// step 2
|
||||
|
@ -877,7 +877,7 @@ ScriptedDirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject
|
|||
Value argv[] = {
|
||||
ObjectOrNullValue(target),
|
||||
value,
|
||||
ObjectOrNullValue(receiver)
|
||||
receiver
|
||||
};
|
||||
RootedValue trapResult(cx);
|
||||
if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult))
|
||||
|
|
|
@ -44,7 +44,7 @@ class ScriptedDirectProxyHandler : public BaseProxyHandler {
|
|||
virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
|
||||
|
||||
virtual bool has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp) const override;
|
||||
virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result) const override;
|
||||
|
|
|
@ -285,7 +285,7 @@ ScriptedIndirectProxyHandler::hasOwn(JSContext* cx, HandleObject proxy, HandleId
|
|||
}
|
||||
|
||||
bool
|
||||
ScriptedIndirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
ScriptedIndirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp) const
|
||||
{
|
||||
RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
|
||||
|
@ -293,7 +293,7 @@ ScriptedIndirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObjec
|
|||
if (!IdToStringOrSymbol(cx, id, &idv))
|
||||
return false;
|
||||
JS::AutoValueArray<2> argv(cx);
|
||||
argv[0].setObjectOrNull(receiver);
|
||||
argv[0].set(receiver);
|
||||
argv[1].set(idv);
|
||||
RootedValue fval(cx);
|
||||
if (!GetDerivedTrap(cx, handler, cx->names().get, &fval))
|
||||
|
|
|
@ -35,7 +35,7 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
|
|||
ObjectOpResult& result) const override;
|
||||
virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
|
||||
virtual bool has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp) const override;
|
||||
virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result) const override;
|
||||
|
|
|
@ -453,41 +453,42 @@ GetObjectElementOperation(JSContext* cx, JSOp op, JS::HandleObject obj, JS::Hand
|
|||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
GetPrimitiveElementOperation(JSContext* cx, JSOp op, JS::HandleValue receiver,
|
||||
GetPrimitiveElementOperation(JSContext* cx, JSOp op, JS::HandleValue receiver_,
|
||||
HandleValue key, MutableHandleValue res)
|
||||
{
|
||||
MOZ_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM);
|
||||
|
||||
// FIXME: We shouldn't be boxing here or exposing the boxed object as
|
||||
// receiver anywhere below (bug 603201).
|
||||
RootedObject boxed(cx, ToObjectFromStack(cx, receiver));
|
||||
RootedObject boxed(cx, ToObjectFromStack(cx, receiver_));
|
||||
if (!boxed)
|
||||
return false;
|
||||
RootedValue receiver(cx, ObjectValue(*boxed));
|
||||
|
||||
do {
|
||||
uint32_t index;
|
||||
if (IsDefinitelyIndex(key, &index)) {
|
||||
if (GetElementNoGC(cx, boxed, boxed, index, res.address()))
|
||||
if (GetElementNoGC(cx, boxed, receiver, index, res.address()))
|
||||
break;
|
||||
|
||||
if (!GetElement(cx, boxed, boxed, index, res))
|
||||
if (!GetElement(cx, boxed, receiver, index, res))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IsSymbolOrSymbolWrapper(key)) {
|
||||
RootedId id(cx, SYMBOL_TO_JSID(ToSymbolPrimitive(key)));
|
||||
if (!GetProperty(cx, boxed, boxed, id, res))
|
||||
if (!GetProperty(cx, boxed, receiver, id, res))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (JSAtom* name = ToAtom<NoGC>(cx, key)) {
|
||||
if (name->isIndex(&index)) {
|
||||
if (GetElementNoGC(cx, boxed, boxed, index, res.address()))
|
||||
if (GetElementNoGC(cx, boxed, receiver, index, res.address()))
|
||||
break;
|
||||
} else {
|
||||
if (GetPropertyNoGC(cx, boxed, boxed, name->asPropertyName(), res.address()))
|
||||
if (GetPropertyNoGC(cx, boxed, receiver, name->asPropertyName(), res.address()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -497,10 +498,10 @@ GetPrimitiveElementOperation(JSContext* cx, JSOp op, JS::HandleValue receiver,
|
|||
return false;
|
||||
|
||||
if (name->isIndex(&index)) {
|
||||
if (!GetElement(cx, boxed, boxed, index, res))
|
||||
if (!GetElement(cx, boxed, receiver, index, res))
|
||||
return false;
|
||||
} else {
|
||||
if (!GetProperty(cx, boxed, boxed, name->asPropertyName(), res))
|
||||
if (!GetProperty(cx, boxed, receiver, name->asPropertyName(), res))
|
||||
return false;
|
||||
}
|
||||
} while (false);
|
||||
|
@ -555,8 +556,10 @@ GetElementOperation(JSContext* cx, JSOp op, MutableHandleValue lref, HandleValue
|
|||
}
|
||||
}
|
||||
|
||||
if (lref.isPrimitive())
|
||||
return GetPrimitiveElementOperation(cx, op, lref, rref, res);
|
||||
if (lref.isPrimitive()) {
|
||||
RootedValue thisv(cx, lref);
|
||||
return GetPrimitiveElementOperation(cx, op, thisv, rref, res);
|
||||
}
|
||||
|
||||
RootedObject thisv(cx, &lref.toObject());
|
||||
return GetObjectElementOperation(cx, op, thisv, thisv, rref, res);
|
||||
|
|
|
@ -255,7 +255,9 @@ GetPropertyOperation(JSContext* cx, InterpreterFrame* fp, HandleScript script, j
|
|||
}
|
||||
|
||||
MOZ_ASSERT(op == JSOP_GETPROP || op == JSOP_LENGTH);
|
||||
return GetProperty(cx, lval, name, vp);
|
||||
// Copy lval, because it might alias vp.
|
||||
RootedValue v(cx, lval);
|
||||
return GetProperty(cx, v, name, vp);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
@ -916,7 +918,7 @@ js::InternalConstructWithProvidedThis(JSContext* cx, HandleValue fval, HandleVal
|
|||
}
|
||||
|
||||
bool
|
||||
js::InvokeGetter(JSContext* cx, JSObject* obj, Value fval, MutableHandleValue rval)
|
||||
js::InvokeGetter(JSContext* cx, const Value& thisv, Value fval, MutableHandleValue rval)
|
||||
{
|
||||
/*
|
||||
* Invoke could result in another try to get or set the same id again, see
|
||||
|
@ -924,7 +926,7 @@ js::InvokeGetter(JSContext* cx, JSObject* obj, Value fval, MutableHandleValue rv
|
|||
*/
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
|
||||
return Invoke(cx, ObjectValue(*obj), fval, 0, nullptr, rval);
|
||||
return Invoke(cx, thisv, fval, 0, nullptr, rval);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4190,7 +4192,7 @@ js::GetProperty(JSContext* cx, HandleValue v, HandlePropertyName name, MutableHa
|
|||
proto = GlobalObject::getOrCreateSymbolPrototype(cx, cx->global());
|
||||
}
|
||||
if (!proto)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
if (GetPropertyPure(cx, proto, NameToId(name), vp.address()))
|
||||
return true;
|
||||
|
@ -4200,7 +4202,9 @@ js::GetProperty(JSContext* cx, HandleValue v, HandlePropertyName name, MutableHa
|
|||
if (!obj)
|
||||
return false;
|
||||
|
||||
return GetProperty(cx, obj, obj, name, vp);
|
||||
// Bug 603201: Pass primitive receiver here.
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
return GetProperty(cx, obj, receiver, name, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -80,7 +80,7 @@ Invoke(JSContext* cx, const Value& thisv, const Value& fval, unsigned argc, cons
|
|||
* getter/setter calls.
|
||||
*/
|
||||
extern bool
|
||||
InvokeGetter(JSContext* cx, JSObject* obj, Value fval, MutableHandleValue rval);
|
||||
InvokeGetter(JSContext* cx, const Value& thisv, Value fval, MutableHandleValue rval);
|
||||
|
||||
extern bool
|
||||
InvokeSetter(JSContext* cx, const Value& thisv, Value fval, HandleValue v);
|
||||
|
|
|
@ -1194,7 +1194,7 @@ static bool IsDataDescriptor(unsigned attrs) {
|
|||
template <AllowGC allowGC>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
GetExistingProperty(JSContext* cx,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType receiver,
|
||||
typename MaybeRooted<Value, allowGC>::HandleType receiver,
|
||||
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<Shape*, allowGC>::HandleType shape,
|
||||
typename MaybeRooted<Value, allowGC>::MutableHandleType vp);
|
||||
|
@ -1213,7 +1213,8 @@ GetExistingPropertyValue(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
MOZ_ASSERT(shape->propid() == id);
|
||||
MOZ_ASSERT(obj->contains(cx, shape));
|
||||
|
||||
return GetExistingProperty<CanGC>(cx->asJSContext(), obj, obj, shape, vp);
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
return GetExistingProperty<CanGC>(cx->asJSContext(), receiver, obj, shape, vp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1644,7 +1645,7 @@ js::NativeHasProperty(JSContext* cx, HandleNativeObject obj, HandleId id, bool*
|
|||
/*** [[Get]] *************************************************************************************/
|
||||
|
||||
static inline bool
|
||||
CallGetter(JSContext* cx, HandleObject obj, HandleObject receiver, HandleShape shape,
|
||||
CallGetter(JSContext* cx, HandleObject obj, HandleValue receiver, HandleShape shape,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
MOZ_ASSERT(!shape->hasDefaultGetter());
|
||||
|
@ -1662,7 +1663,7 @@ CallGetter(JSContext* cx, HandleObject obj, HandleObject receiver, HandleShape s
|
|||
template <AllowGC allowGC>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
GetExistingProperty(JSContext* cx,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType receiver,
|
||||
typename MaybeRooted<Value, allowGC>::HandleType receiver,
|
||||
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<Shape*, allowGC>::HandleType shape,
|
||||
typename MaybeRooted<Value, allowGC>::MutableHandleType vp)
|
||||
|
@ -1701,7 +1702,7 @@ GetExistingProperty(JSContext* cx,
|
|||
|
||||
if (!CallGetter(cx,
|
||||
MaybeRooted<JSObject*, allowGC>::toHandle(obj),
|
||||
MaybeRooted<JSObject*, allowGC>::toHandle(receiver),
|
||||
MaybeRooted<Value, allowGC>::toHandle(receiver),
|
||||
MaybeRooted<Shape*, allowGC>::toHandle(shape),
|
||||
MaybeRooted<Value, allowGC>::toMutableHandle(vp)))
|
||||
{
|
||||
|
@ -1721,7 +1722,8 @@ bool
|
|||
js::NativeGetExistingProperty(JSContext* cx, HandleObject receiver, HandleNativeObject obj,
|
||||
HandleShape shape, MutableHandleValue vp)
|
||||
{
|
||||
return GetExistingProperty<CanGC>(cx, receiver, obj, shape, vp);
|
||||
RootedValue receiverValue(cx, ObjectValue(*receiver));
|
||||
return GetExistingProperty<CanGC>(cx, receiverValue, obj, shape, vp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1784,7 +1786,7 @@ enum IsNameLookup { NotNameLookup = false, NameLookup = true };
|
|||
*/
|
||||
static bool
|
||||
GetNonexistentProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
HandleObject receiver, IsNameLookup nameLookup, MutableHandleValue vp)
|
||||
HandleValue receiver, IsNameLookup nameLookup, MutableHandleValue vp)
|
||||
{
|
||||
vp.setUndefined();
|
||||
|
||||
|
@ -1849,14 +1851,14 @@ GetNonexistentProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
|
||||
/* The NoGC version of GetNonexistentProperty, present only to make types line up. */
|
||||
bool
|
||||
GetNonexistentProperty(JSContext* cx, NativeObject* obj, jsid id, JSObject* receiver,
|
||||
GetNonexistentProperty(JSContext* cx, NativeObject* obj, jsid id, Value& receiver,
|
||||
IsNameLookup nameLookup, FakeMutableHandle<Value> vp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
GeneralizedGetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleObject receiver,
|
||||
GeneralizedGetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue receiver,
|
||||
IsNameLookup nameLookup, MutableHandleValue vp)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
|
@ -1881,7 +1883,7 @@ GeneralizedGetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleObjec
|
|||
}
|
||||
|
||||
static inline bool
|
||||
GeneralizedGetProperty(JSContext* cx, JSObject* obj, jsid id, JSObject* receiver,
|
||||
GeneralizedGetProperty(JSContext* cx, JSObject* obj, jsid id, const Value& receiver,
|
||||
IsNameLookup nameLookup, FakeMutableHandle<Value> vp)
|
||||
{
|
||||
JS_CHECK_RECURSION_DONT_REPORT(cx, return false);
|
||||
|
@ -1894,7 +1896,7 @@ template <AllowGC allowGC>
|
|||
static MOZ_ALWAYS_INLINE bool
|
||||
NativeGetPropertyInline(JSContext* cx,
|
||||
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType receiver,
|
||||
typename MaybeRooted<Value, allowGC>::HandleType receiver,
|
||||
typename MaybeRooted<jsid, allowGC>::HandleType id,
|
||||
IsNameLookup nameLookup,
|
||||
typename MaybeRooted<Value, allowGC>::MutableHandleType vp)
|
||||
|
@ -1948,14 +1950,14 @@ NativeGetPropertyInline(JSContext* cx,
|
|||
}
|
||||
|
||||
bool
|
||||
js::NativeGetProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
|
||||
js::NativeGetProperty(JSContext* cx, HandleNativeObject obj, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
return NativeGetPropertyInline<CanGC>(cx, obj, receiver, id, NotNameLookup, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::NativeGetPropertyNoGC(JSContext* cx, NativeObject* obj, JSObject* receiver, jsid id, Value* vp)
|
||||
js::NativeGetPropertyNoGC(JSContext* cx, NativeObject* obj, const Value& receiver, jsid id, Value* vp)
|
||||
{
|
||||
AutoAssertNoException noexc(cx);
|
||||
return NativeGetPropertyInline<NoGC>(cx, obj, receiver, id, NotNameLookup, vp);
|
||||
|
@ -1964,9 +1966,10 @@ js::NativeGetPropertyNoGC(JSContext* cx, NativeObject* obj, JSObject* receiver,
|
|||
bool
|
||||
js::GetPropertyForNameLookup(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
if (obj->getOps()->getProperty)
|
||||
return GeneralizedGetProperty(cx, obj, id, obj, NameLookup, vp);
|
||||
return NativeGetPropertyInline<CanGC>(cx, obj.as<NativeObject>(), obj, id, NameLookup, vp);
|
||||
return GeneralizedGetProperty(cx, obj, id, receiver, NameLookup, vp);
|
||||
return NativeGetPropertyInline<CanGC>(cx, obj.as<NativeObject>(), receiver, id, NameLookup, vp);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1288,26 +1288,28 @@ extern bool
|
|||
NativeHasProperty(JSContext* cx, HandleNativeObject obj, HandleId id, bool* foundp);
|
||||
|
||||
extern bool
|
||||
NativeGetProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
|
||||
NativeGetProperty(JSContext* cx, HandleNativeObject obj, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp);
|
||||
|
||||
extern bool
|
||||
NativeGetPropertyNoGC(JSContext* cx, NativeObject* obj, JSObject* receiver, jsid id, Value* vp);
|
||||
NativeGetPropertyNoGC(JSContext* cx, NativeObject* obj, const Value& receiver, jsid id, Value* vp);
|
||||
|
||||
extern bool
|
||||
NativeGetElement(JSContext* cx, HandleNativeObject obj, HandleObject receiver, uint32_t index,
|
||||
NativeGetElement(JSContext* cx, HandleNativeObject obj, HandleValue receiver, uint32_t index,
|
||||
MutableHandleValue vp);
|
||||
|
||||
inline bool
|
||||
NativeGetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
return NativeGetProperty(cx, obj, obj, id, vp);
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
return NativeGetProperty(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
NativeGetElement(JSContext* cx, HandleNativeObject obj, uint32_t index, MutableHandleValue vp)
|
||||
{
|
||||
return NativeGetElement(cx, obj, obj, index, vp);
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
return NativeGetElement(cx, obj, receiver, index, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1409,7 +1411,7 @@ js::HasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
|
|||
}
|
||||
|
||||
inline bool
|
||||
js::GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
js::GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
if (GetPropertyOp op = obj->getOps()->getProperty)
|
||||
|
@ -1418,7 +1420,7 @@ js::GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId
|
|||
}
|
||||
|
||||
inline bool
|
||||
js::GetPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, jsid id, Value* vp)
|
||||
js::GetPropertyNoGC(JSContext* cx, JSObject* obj, const Value& receiver, jsid id, Value* vp)
|
||||
{
|
||||
if (obj->getOps()->getProperty)
|
||||
return false;
|
||||
|
|
|
@ -504,11 +504,14 @@ with_HasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
|
|||
}
|
||||
|
||||
static bool
|
||||
with_GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
with_GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
|
||||
return GetProperty(cx, actual, actual, id, vp);
|
||||
RootedValue actualReceiver(cx, receiver);
|
||||
if (receiver.isObject() && &receiver.toObject() == obj)
|
||||
actualReceiver.setObject(*actual);
|
||||
return GetProperty(cx, actual, actualReceiver, id, vp);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -982,7 +985,7 @@ uninitialized_HasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* fo
|
|||
}
|
||||
|
||||
static bool
|
||||
uninitialized_GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
uninitialized_GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
ReportUninitializedLexicalId(cx, id);
|
||||
|
@ -1624,7 +1627,7 @@ class DebugScopeProxy : public BaseProxyHandler
|
|||
return true;
|
||||
}
|
||||
|
||||
bool get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
bool get(JSContext* cx, HandleObject proxy, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp) const override
|
||||
{
|
||||
Rooted<DebugScopeObject*> debugScope(cx, &proxy->as<DebugScopeObject>());
|
||||
|
|
|
@ -780,7 +780,7 @@ UnboxedPlainObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id
|
|||
}
|
||||
|
||||
/* static */ bool
|
||||
UnboxedPlainObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
UnboxedPlainObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layout();
|
||||
|
@ -793,7 +793,9 @@ UnboxedPlainObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleObjec
|
|||
if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando()) {
|
||||
if (expando->containsShapeOrElement(cx, id)) {
|
||||
RootedObject nexpando(cx, expando);
|
||||
RootedObject nreceiver(cx, (obj == receiver) ? expando : receiver.get());
|
||||
RootedValue nreceiver(cx, receiver);
|
||||
if (receiver.isObject() && &receiver.toObject() == obj)
|
||||
nreceiver.setObject(*expando);
|
||||
return GetProperty(cx, nexpando, nreceiver, id, vp);
|
||||
}
|
||||
}
|
||||
|
@ -1482,7 +1484,7 @@ UnboxedArrayObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id
|
|||
}
|
||||
|
||||
/* static */ bool
|
||||
UnboxedArrayObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
UnboxedArrayObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
|
||||
|
|
|
@ -250,7 +250,7 @@ class UnboxedPlainObject : public JSObject
|
|||
|
||||
static bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
|
||||
|
||||
static bool obj_getProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
static bool obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp);
|
||||
|
||||
static bool obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
|
@ -386,7 +386,7 @@ class UnboxedArrayObject : public JSObject
|
|||
|
||||
static bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
|
||||
|
||||
static bool obj_getProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
static bool obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
HandleId id, MutableHandleValue vp);
|
||||
|
||||
static bool obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
|
|
|
@ -828,7 +828,7 @@ xpc::SandboxProxyHandler::hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy,
|
|||
|
||||
bool
|
||||
xpc::SandboxProxyHandler::get(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<JSObject*> receiver,
|
||||
JS::Handle<JS::Value> receiver,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<Value> vp) const
|
||||
{
|
||||
|
|
|
@ -169,7 +169,7 @@ AddonWrapper<Base>::getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper
|
|||
|
||||
template<typename Base>
|
||||
bool
|
||||
AddonWrapper<Base>::get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
|
||||
AddonWrapper<Base>::get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<Value> receiver,
|
||||
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const
|
||||
{
|
||||
Rooted<JSPropertyDescriptor> desc(cx);
|
||||
|
@ -180,10 +180,7 @@ AddonWrapper<Base>::get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle
|
|||
return Base::get(cx, wrapper, receiver, id, vp);
|
||||
|
||||
if (desc.getter()) {
|
||||
MOZ_ASSERT(desc.hasGetterObject());
|
||||
AutoValueVector args(cx);
|
||||
RootedValue fval(cx, ObjectValue(*desc.getterObject()));
|
||||
return JS_CallFunctionValue(cx, receiver, fval, args, vp);
|
||||
return Call(cx, receiver, desc.getterObject(), HandleValueArray::empty(), vp);
|
||||
} else {
|
||||
vp.set(desc.value());
|
||||
return true;
|
||||
|
|
|
@ -36,7 +36,7 @@ class AddonWrapper : public Base {
|
|||
JS::ObjectOpResult& result) const override;
|
||||
virtual bool delete_(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
|
||||
JS::ObjectOpResult& result) const override;
|
||||
virtual bool get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
|
||||
virtual bool get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JS::Value> receiver,
|
||||
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
|
||||
virtual bool set(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id, JS::HandleValue v,
|
||||
JS::HandleValue receiver, JS::ObjectOpResult& result) const override;
|
||||
|
|
|
@ -50,8 +50,7 @@ WaiveXrayWrapper::getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper,
|
|||
}
|
||||
|
||||
bool
|
||||
WaiveXrayWrapper::get(JSContext* cx, HandleObject wrapper,
|
||||
HandleObject receiver, HandleId id,
|
||||
WaiveXrayWrapper::get(JSContext* cx, HandleObject wrapper, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp) const
|
||||
{
|
||||
return CrossCompartmentWrapper::get(cx, wrapper, receiver, id, vp) &&
|
||||
|
|
|
@ -22,7 +22,7 @@ class WaiveXrayWrapper : public js::CrossCompartmentWrapper {
|
|||
JS::MutableHandle<JSPropertyDescriptor> desc) const override;
|
||||
virtual bool getPrototype(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::MutableHandle<JSObject*> protop) const override;
|
||||
virtual bool get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
|
||||
virtual bool get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JS::Value> receiver,
|
||||
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
|
||||
virtual bool call(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
const JS::CallArgs& args) const override;
|
||||
|
|
|
@ -2092,13 +2092,18 @@ XrayWrapper<Base, Traits>::delete_(JSContext* cx, HandleObject wrapper,
|
|||
template <typename Base, typename Traits>
|
||||
bool
|
||||
XrayWrapper<Base, Traits>::get(JSContext* cx, HandleObject wrapper,
|
||||
HandleObject receiver, HandleId id,
|
||||
HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp) const
|
||||
{
|
||||
// Skip our Base if it isn't already ProxyHandler.
|
||||
// NB: None of the functions we call are prepared for the receiver not
|
||||
// being the wrapper, so ignore the receiver here.
|
||||
return js::BaseProxyHandler::get(cx, wrapper, Traits::HasPrototype ? receiver : wrapper, id, vp);
|
||||
RootedValue thisv(cx);
|
||||
if (Traits::HasPrototype)
|
||||
thisv = receiver;
|
||||
else
|
||||
thisv.setObject(*wrapper);
|
||||
return js::BaseProxyHandler::get(cx, wrapper, thisv, id, vp);
|
||||
}
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
|
|
|
@ -446,7 +446,7 @@ class XrayWrapper : public Base {
|
|||
virtual bool isExtensible(JSContext* cx, JS::Handle<JSObject*> wrapper, bool* extensible) const override;
|
||||
virtual bool has(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
|
||||
bool* bp) const override;
|
||||
virtual bool get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
|
||||
virtual bool get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::HandleValue receiver,
|
||||
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
|
||||
virtual bool set(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
|
||||
JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
|
||||
|
@ -520,7 +520,7 @@ public:
|
|||
// which implement them in terms of lower-level methods.
|
||||
virtual bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||
bool* bp) const override;
|
||||
virtual bool get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
|
||||
virtual bool get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::HandleValue receiver,
|
||||
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
|
||||
virtual bool set(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||
JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
|
||||
|
|
|
@ -3691,7 +3691,11 @@ nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings,
|
|||
if (GetIsPrinting()) {
|
||||
// Let the user know we are not ready to print.
|
||||
rv = NS_ERROR_NOT_AVAILABLE;
|
||||
nsPrintEngine::ShowPrintErrorDialog(rv);
|
||||
|
||||
if (mPrintEngine) {
|
||||
mPrintEngine->FirePrintingErrorEvent(rv);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/dom/CustomEvent.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
@ -121,6 +122,7 @@ static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingpro
|
|||
#include "nsContentList.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "nsVariant.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -414,8 +416,9 @@ nsPrintEngine::CommonPrint(bool aIsPrintPreview,
|
|||
}
|
||||
if (mProgressDialogIsShown)
|
||||
CloseProgressDialog(aWebProgressListener);
|
||||
if (rv != NS_ERROR_ABORT && rv != NS_ERROR_OUT_OF_MEMORY)
|
||||
ShowPrintErrorDialog(rv, !aIsPrintPreview);
|
||||
if (rv != NS_ERROR_ABORT && rv != NS_ERROR_OUT_OF_MEMORY) {
|
||||
FirePrintingErrorEvent(rv);
|
||||
}
|
||||
delete mPrt;
|
||||
mPrt = nullptr;
|
||||
}
|
||||
|
@ -783,7 +786,7 @@ nsPrintEngine::PrintPreview(nsIPrintSettings* aPrintSettings,
|
|||
if (NS_FAILED(docShell->GetBusyFlags(&busyFlags)) ||
|
||||
busyFlags != nsIDocShell::BUSY_FLAGS_NONE) {
|
||||
CloseProgressDialog(aWebProgressListener);
|
||||
ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY, false);
|
||||
FirePrintingErrorEvent(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -1505,7 +1508,7 @@ nsresult nsPrintEngine::CleanupOnFailure(nsresult aResult, bool aIsPrinting)
|
|||
* print job without displaying any error messages
|
||||
*/
|
||||
if (aResult != NS_ERROR_ABORT) {
|
||||
ShowPrintErrorDialog(aResult, aIsPrinting);
|
||||
FirePrintingErrorEvent(aResult);
|
||||
}
|
||||
|
||||
FirePrintCompletionEvent();
|
||||
|
@ -1516,81 +1519,28 @@ nsresult nsPrintEngine::CleanupOnFailure(nsresult aResult, bool aIsPrinting)
|
|||
|
||||
//---------------------------------------------------------------------
|
||||
void
|
||||
nsPrintEngine::ShowPrintErrorDialog(nsresult aPrintError, bool aIsPrinting)
|
||||
nsPrintEngine::FirePrintingErrorEvent(nsresult aPrintError)
|
||||
{
|
||||
nsAutoCString stringName;
|
||||
nsXPIDLString msg, title;
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint);
|
||||
nsCOMPtr<nsIDocument> doc = cv->GetDocument();
|
||||
nsCOMPtr<nsIDOMCustomEvent> event =
|
||||
NS_NewDOMCustomEvent(doc, nullptr, nullptr);
|
||||
|
||||
switch(aPrintError)
|
||||
{
|
||||
#define ENTITY_FOR_ERROR(label) \
|
||||
case NS_ERROR_##label: stringName.AssignLiteral("PERR_" #label); break
|
||||
MOZ_ASSERT(event);
|
||||
nsCOMPtr<nsIWritableVariant> resultVariant = new nsVariant();
|
||||
// nsresults are Uint32_t's, but XPConnect will interpret it as a double
|
||||
// when any JS attempts to access it, and will therefore interpret it
|
||||
// incorrectly. We preempt this by casting and setting as a double.
|
||||
resultVariant->SetAsDouble(static_cast<double>(aPrintError));
|
||||
|
||||
ENTITY_FOR_ERROR(GFX_PRINTER_NO_PRINTER_AVAILABLE);
|
||||
ENTITY_FOR_ERROR(GFX_PRINTER_NAME_NOT_FOUND);
|
||||
ENTITY_FOR_ERROR(GFX_PRINTER_COULD_NOT_OPEN_FILE);
|
||||
ENTITY_FOR_ERROR(GFX_PRINTER_STARTDOC);
|
||||
ENTITY_FOR_ERROR(GFX_PRINTER_ENDDOC);
|
||||
ENTITY_FOR_ERROR(GFX_PRINTER_STARTPAGE);
|
||||
ENTITY_FOR_ERROR(GFX_PRINTER_DOC_IS_BUSY);
|
||||
event->InitCustomEvent(NS_LITERAL_STRING("PrintingError"), false, false,
|
||||
resultVariant);
|
||||
event->SetTrusted(true);
|
||||
|
||||
ENTITY_FOR_ERROR(ABORT);
|
||||
ENTITY_FOR_ERROR(NOT_AVAILABLE);
|
||||
ENTITY_FOR_ERROR(NOT_IMPLEMENTED);
|
||||
ENTITY_FOR_ERROR(OUT_OF_MEMORY);
|
||||
ENTITY_FOR_ERROR(UNEXPECTED);
|
||||
|
||||
default:
|
||||
ENTITY_FOR_ERROR(FAILURE);
|
||||
|
||||
#undef ENTITY_FOR_ERROR
|
||||
}
|
||||
|
||||
if (!aIsPrinting) {
|
||||
// Try first with _PP suffix.
|
||||
stringName.AppendLiteral("_PP");
|
||||
rv = nsContentUtils::GetLocalizedString(
|
||||
nsContentUtils::ePRINTING_PROPERTIES, stringName.get(), msg);
|
||||
if (NS_FAILED(rv)) {
|
||||
stringName.Truncate(stringName.Length() - 3);
|
||||
}
|
||||
}
|
||||
if (aIsPrinting || NS_FAILED(rv)) {
|
||||
rv = nsContentUtils::GetLocalizedString(
|
||||
nsContentUtils::ePRINTING_PROPERTIES, stringName.get(), msg);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = nsContentUtils::GetLocalizedString(
|
||||
nsContentUtils::ePRINTING_PROPERTIES,
|
||||
aIsPrinting ? "print_error_dialog_title"
|
||||
: "printpreview_error_dialog_title",
|
||||
title);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWindowWatcher> wwatch =
|
||||
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> active;
|
||||
wwatch->GetActiveWindow(getter_AddRefs(active));
|
||||
|
||||
nsCOMPtr<nsIPrompt> dialog;
|
||||
/* |GetNewPrompter| allows that |active| is |nullptr|
|
||||
* (see bug 234982 ("nsPrintEngine::ShowPrintErrorDialog() fails in many cases")) */
|
||||
wwatch->GetNewPrompter(active, getter_AddRefs(dialog));
|
||||
if (!dialog) {
|
||||
return;
|
||||
}
|
||||
|
||||
dialog->Alert(title.get(), msg.get());
|
||||
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||
new AsyncEventDispatcher(doc, event);
|
||||
asyncDispatcher->mOnlyChromeDispatch = true;
|
||||
asyncDispatcher->RunDOMEventWhenSafe();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
@ -2696,7 +2646,7 @@ nsPrintEngine::PrePrintPage()
|
|||
// Shouldn't |mPrt->mIsAborted| set to true all the time if something
|
||||
// wents wrong?
|
||||
if (rv != NS_ERROR_ABORT) {
|
||||
ShowPrintErrorDialog(rv);
|
||||
FirePrintingErrorEvent(rv);
|
||||
mPrt->mIsAborted = true;
|
||||
}
|
||||
done = true;
|
||||
|
@ -2715,7 +2665,7 @@ nsPrintEngine::PrintPage(nsPrintObject* aPO,
|
|||
// Although these should NEVER be nullptr
|
||||
// This is added insurance, to make sure we don't crash in optimized builds
|
||||
if (!mPrt || !aPO || !mPageSeqFrame) {
|
||||
ShowPrintErrorDialog(NS_ERROR_FAILURE);
|
||||
FirePrintingErrorEvent(NS_ERROR_FAILURE);
|
||||
return true; // means we are done printing
|
||||
}
|
||||
|
||||
|
@ -2777,7 +2727,7 @@ nsPrintEngine::PrintPage(nsPrintObject* aPO,
|
|||
nsresult rv = mPageSeqFrame->PrintNextPage();
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv != NS_ERROR_ABORT) {
|
||||
ShowPrintErrorDialog(rv);
|
||||
FirePrintingErrorEvent(rv);
|
||||
mPrt->mIsAborted = true;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -137,6 +137,7 @@ public:
|
|||
|
||||
bool IsThereARangeSelection(nsIDOMWindow * aDOMWin);
|
||||
|
||||
void FirePrintingErrorEvent(nsresult aPrintError);
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -165,8 +166,6 @@ public:
|
|||
nsAString& aTitle,
|
||||
nsAString& aURLStr,
|
||||
eDocTitleDefault aDefType);
|
||||
static void ShowPrintErrorDialog(nsresult printerror,
|
||||
bool aIsPrinting = true);
|
||||
|
||||
static bool HasFramesetChild(nsIContent* aContent);
|
||||
|
||||
|
|
|
@ -1965,7 +1965,7 @@ pref("security.mixed_content.block_active_content", false);
|
|||
pref("security.mixed_content.block_display_content", false);
|
||||
|
||||
// Sub-resource integrity
|
||||
pref("security.sri.enable", false);
|
||||
pref("security.sri.enable", true);
|
||||
|
||||
// Disable pinning checks by default.
|
||||
pref("security.cert_pinning.enforcement_level", 0);
|
||||
|
@ -2715,7 +2715,10 @@ pref("font.size.fixed.zh-TW", 16);
|
|||
|
||||
// mathml.css sets font-size to "inherit" and font-family to "serif" so only
|
||||
// font.name.*.x-math and font.minimum-size.x-math are really relevant.
|
||||
pref("font.default.x-math", "serif");
|
||||
pref("font.minimum-size.x-math", 0);
|
||||
pref("font.size.variable.x-math", 16);
|
||||
pref("font.size.fixed.x-math", 13);
|
||||
|
||||
/*
|
||||
* A value greater than zero enables font size inflation for
|
||||
|
@ -3165,11 +3168,11 @@ pref("intl.tsf.hack.easy_changjei.do_not_return_no_layout_error", true);
|
|||
// Whether use previous character rect for the result of
|
||||
// ITfContextView::GetTextExt() if the specified range is the first character
|
||||
// of selected clause of composition string.
|
||||
pref("intl.tsf.hack.google_ja_input.do_not_return_no_layout_error_at_first_char", true);
|
||||
pref("intl.tsf.hack.ms_japanese_ime.do_not_return_no_layout_error_at_first_char", true);
|
||||
// Whether use previous character rect for the result of
|
||||
// ITfContextView::GetTextExt() if the specified range is the caret of
|
||||
// composition string.
|
||||
pref("intl.tsf.hack.google_ja_input.do_not_return_no_layout_error_at_caret", true);
|
||||
pref("intl.tsf.hack.ms_japanese_ime.do_not_return_no_layout_error_at_caret", true);
|
||||
// Whether hack ITextStoreACP::QueryInsert() or not. The method should return
|
||||
// new selection after specified length text is inserted at specified range.
|
||||
// However, Microsoft's some Chinese TIPs expect that the result is same as
|
||||
|
|
|
@ -95,6 +95,7 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t versio
|
|||
, mCleanShutdown(false)
|
||||
, mTLSProfileConfirmed(false)
|
||||
, mGoAwayReason(NO_HTTP_ERROR)
|
||||
, mClientGoAwayReason(UNASSIGNED)
|
||||
, mPeerGoAwayReason(UNASSIGNED)
|
||||
, mGoAwayID(0)
|
||||
, mOutgoingGoAwayID(0)
|
||||
|
@ -195,6 +196,7 @@ Http2Session::~Http2Session()
|
|||
Telemetry::Accumulate(Telemetry::SPDY_REQUEST_PER_CONN, (mNextStreamID - 1) / 2);
|
||||
Telemetry::Accumulate(Telemetry::SPDY_SERVER_INITIATED_STREAMS,
|
||||
mServerPushedResources);
|
||||
Telemetry::Accumulate(Telemetry::SPDY_GOAWAY_LOCAL, mClientGoAwayReason);
|
||||
Telemetry::Accumulate(Telemetry::SPDY_GOAWAY_PEER, mPeerGoAwayReason);
|
||||
}
|
||||
|
||||
|
@ -806,6 +808,7 @@ Http2Session::GenerateGoAway(uint32_t aStatusCode)
|
|||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
LOG3(("Http2Session::GenerateGoAway %p code=%X\n", this, aStatusCode));
|
||||
|
||||
mClientGoAwayReason = aStatusCode;
|
||||
uint32_t frameSize = kFrameHeaderBytes + 8;
|
||||
char *packet = EnsureOutputBuffer(frameSize);
|
||||
mOutputQueueUsed += frameSize;
|
||||
|
|
|
@ -424,8 +424,9 @@ private:
|
|||
// only NO_HTTP_ERROR, PROTOCOL_ERROR, or INTERNAL_ERROR will be sent.
|
||||
errorType mGoAwayReason;
|
||||
|
||||
// The error code received from the peer in a goaway frame. UNASSIGNED/31
|
||||
// if not received.
|
||||
// The error code sent/received on the session goaway frame. UNASSIGNED/31
|
||||
// if not transmitted.
|
||||
int32_t mClientGoAwayReason;
|
||||
int32_t mPeerGoAwayReason;
|
||||
|
||||
// If a GoAway message was received this is the ID of the last valid
|
||||
|
|
|
@ -2896,8 +2896,9 @@ nsHttpChannel::OpenCacheEntry(bool isHttps)
|
|||
return NS_OK;
|
||||
|
||||
// Pick up an application cache from the notification
|
||||
// callbacks if available
|
||||
if (!mApplicationCache && mInheritApplicationCache) {
|
||||
// callbacks if available and if we are not an intercepted channel.
|
||||
if (!PossiblyIntercepted() && !mApplicationCache &&
|
||||
mInheritApplicationCache) {
|
||||
nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer;
|
||||
GetCallback(appCacheContainer);
|
||||
|
||||
|
|
|
@ -169,3 +169,11 @@ class TestElements(MarionetteTestCase):
|
|||
self.assertIsNotNone(re.search(uuid_regex, el.id),
|
||||
'UUID for the WebElement is not valid. ID is {}'\
|
||||
.format(el.id))
|
||||
def test_should_find_elements_by_link_text(self):
|
||||
test_html = self.marionette.absolute_url("nestedElements.html")
|
||||
self.marionette.navigate(test_html)
|
||||
element = self.marionette.find_element(By.NAME, "div1")
|
||||
children = element.find_elements(By.LINK_TEXT, "hello world")
|
||||
self.assertEqual(len(children), 2)
|
||||
self.assertEqual("link1", children[0].get_attribute("name"))
|
||||
self.assertEqual("link2", children[1].get_attribute("name"))
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<a href="1.html">hello world</a>
|
||||
<a href="1.html">hello world</a><a href="1.html">hello world</a>
|
||||
<div name="div1">
|
||||
<a href="2.html" name="link1">hello world</a>
|
||||
<a href="2.html" name="link2">hello world</a>
|
||||
</div>
|
||||
|
||||
<a href="1.html">hello world</a><a href="1.html">hello world</a><a href="1.html">hello world</a>
|
|
@ -681,7 +681,7 @@ ElementManager.prototype = {
|
|||
break;
|
||||
case LINK_TEXT:
|
||||
case PARTIAL_LINK_TEXT:
|
||||
let allLinks = rootNode.getElementsByTagName('A');
|
||||
let allLinks = startNode.getElementsByTagName('A');
|
||||
for (let i = 0; i < allLinks.length; i++) {
|
||||
let text = allLinks[i].text;
|
||||
if (PARTIAL_LINK_TEXT == using) {
|
||||
|
|
|
@ -1,62 +1,5 @@
|
|||
[subresource-integrity.html]
|
||||
type: testharness
|
||||
[Doesn't load scripts with improper integrity URI scheme]
|
||||
expected: FAIL
|
||||
|
||||
[Doesn't load scripts with incorrect content-type]
|
||||
expected: FAIL
|
||||
|
||||
[Doesn't load scripts with non-matching digest]
|
||||
expected: FAIL
|
||||
|
||||
[Doesn't load scripts using weak digest algorithm]
|
||||
expected: FAIL
|
||||
|
||||
[Same-origin script with incorrect hash.]
|
||||
expected: FAIL
|
||||
|
||||
[SHA-512 preferred to SHA-256.]
|
||||
expected: FAIL
|
||||
|
||||
[SHA-512 preferred to SHA-384.]
|
||||
expected: FAIL
|
||||
|
||||
[SHA-384 preferred to SHA-256.]
|
||||
expected: FAIL
|
||||
|
||||
[SHA-256 preferred to MD5.]
|
||||
expected: FAIL
|
||||
|
||||
[getPrioritizedHashFunction('SHA-256', 'SHA-256') returns empty string]
|
||||
expected: FAIL
|
||||
|
||||
[Same-origin script with sha256 match, sha512 mismatch]
|
||||
expected: FAIL
|
||||
|
||||
[<crossorigin='anonymous'> with incorrect hash, ACAO: *]
|
||||
expected: FAIL
|
||||
|
||||
[<crossorigin='use-credentials'> with incorrect hash CORS-eligible]
|
||||
expected: FAIL
|
||||
|
||||
[Resource with Refresh header]
|
||||
expected: FAIL
|
||||
|
||||
[Resource with WWW-Authenticate header]
|
||||
expected: FAIL
|
||||
|
||||
[Script: Same-origin with incorrect hash.]
|
||||
expected: FAIL
|
||||
|
||||
[Script: Same-origin with sha256 match, sha512 mismatch]
|
||||
expected: FAIL
|
||||
|
||||
[Script: <crossorigin='anonymous'> with incorrect hash, ACAO: *]
|
||||
expected: FAIL
|
||||
|
||||
[Script: <crossorigin='use-credentials'> with incorrect hash CORS-eligible]
|
||||
expected: FAIL
|
||||
|
||||
[Style: Same-origin with incorrect hash.]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -71,16 +14,3 @@
|
|||
|
||||
[Style: Same-origin with incorrect sha256 and sha512 hash, rel='alternate stylesheet' enabled]
|
||||
expected: FAIL
|
||||
|
||||
[Script: Cross-origin, not CORS request, with correct hash]
|
||||
expected: FAIL
|
||||
|
||||
[Script: Cross-origin, not CORS request, with hash mismatch]
|
||||
expected: FAIL
|
||||
|
||||
[Style: Cross-origin, not CORS request, with correct hash]
|
||||
expected: FAIL
|
||||
|
||||
[Style: Cross-origin, not CORS request, with hash mismatch]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -65,6 +65,17 @@ var gSavePrintSettings = false;
|
|||
var gFocusedElement = null;
|
||||
|
||||
var PrintUtils = {
|
||||
init() {
|
||||
window.messageManager.addMessageListener("Printing:Error", this);
|
||||
},
|
||||
|
||||
get bundle() {
|
||||
let stringService = Components.classes["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Components.interfaces.nsIStringBundleService);
|
||||
delete this.bundle;
|
||||
return this.bundle = stringService.createBundle("chrome://global/locale/printing.properties");
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the page setup dialog, and saves any settings changed in
|
||||
* that dialog if print.save_print_settings is set to true.
|
||||
|
@ -300,7 +311,77 @@ var PrintUtils = {
|
|||
return this.usingRemoteTabs = usingRemoteTabs;
|
||||
},
|
||||
|
||||
displayPrintingError(nsresult, isPrinting) {
|
||||
// The nsresults from a printing error are mapped to strings that have
|
||||
// similar names to the errors themselves. For example, for error
|
||||
// NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE, the name of the string
|
||||
// for the error message is: PERR_GFX_PRINTER_NO_PRINTER_AVAILABLE. What's
|
||||
// more, if we're in the process of doing a print preview, it's possible
|
||||
// that there are strings specific for print preview for these errors -
|
||||
// if so, the names of those strings have _PP as a suffix. It's possible
|
||||
// that no print preview specific strings exist, in which case it is fine
|
||||
// to fall back to the original string name.
|
||||
const MSG_CODES = [
|
||||
"GFX_PRINTER_NO_PRINTER_AVAILABLE",
|
||||
"GFX_PRINTER_NAME_NOT_FOUND",
|
||||
"GFX_PRINTER_COULD_NOT_OPEN_FILE",
|
||||
"GFX_PRINTER_STARTDOC",
|
||||
"GFX_PRINTER_ENDDOC",
|
||||
"GFX_PRINTER_STARTPAGE",
|
||||
"GFX_PRINTER_DOC_IS_BUSY",
|
||||
"ABORT",
|
||||
"NOT_AVAILABLE",
|
||||
"NOT_IMPLEMENTED",
|
||||
"OUT_OF_MEMORY",
|
||||
"UNEXPECTED",
|
||||
];
|
||||
|
||||
// PERR_FAILURE is the catch-all error message if we've gotten one that
|
||||
// we don't recognize.
|
||||
msgName = "PERR_FAILURE";
|
||||
|
||||
for (let code of MSG_CODES) {
|
||||
let nsErrorResult = "NS_ERROR_" + code;
|
||||
if (Components.results[nsErrorResult] == nsresult) {
|
||||
msgName = "PERR_" + code;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let msg, title;
|
||||
|
||||
if (!isPrinting) {
|
||||
// Try first with _PP suffix.
|
||||
let ppMsgName = msgName + "_PP";
|
||||
try {
|
||||
msg = this.bundle.GetStringFromName(ppMsgName);
|
||||
} catch(e) {
|
||||
// We allow localizers to not have the print preview error string,
|
||||
// and just fall back to the printing error string.
|
||||
}
|
||||
}
|
||||
|
||||
if (!msg) {
|
||||
msg = this.bundle.GetStringFromName(msgName);
|
||||
}
|
||||
|
||||
title = this.bundle.GetStringFromName(isPrinting ? "print_error_dialog_title"
|
||||
: "printpreview_error_dialog_title");
|
||||
|
||||
let promptSvc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
promptSvc.alert(window, title, msg);
|
||||
},
|
||||
|
||||
receiveMessage(aMessage) {
|
||||
if (aMessage.name == "Printing:Error") {
|
||||
this.displayPrintingError(aMessage.data.nsresult,
|
||||
aMessage.data.isPrinting);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we got here, then the message we've received must involve
|
||||
// updating the print progress UI.
|
||||
if (!this._webProgressPP.value) {
|
||||
// We somehow didn't get a nsIWebProgressListener to be updated...
|
||||
// I guess there's nothing to do.
|
||||
|
@ -537,3 +618,5 @@ var PrintUtils = {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
PrintUtils.init();
|
||||
|
|
|
@ -1524,6 +1524,12 @@
|
|||
"extended_statistics_ok": true,
|
||||
"description": "H2: Settings Initial Window (rounded to KB)"
|
||||
},
|
||||
"SPDY_GOAWAY_LOCAL": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "enumerated",
|
||||
"n_values": 32,
|
||||
"description": "H2: goaway reason client sent from rfc 7540. 31 is none sent."
|
||||
},
|
||||
"SPDY_GOAWAY_PEER": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "enumerated",
|
||||
|
@ -9453,5 +9459,15 @@
|
|||
"kind": "count",
|
||||
"releaseChannelCollection": "opt-out",
|
||||
"description": "Sync cryptoKeys collection HMAC mismatches."
|
||||
},
|
||||
"CONTENT_DOCUMENTS_DESTROYED": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "count",
|
||||
"description": "Number of content documents destroyed; used in conjunction with use counter histograms"
|
||||
},
|
||||
"TOP_LEVEL_CONTENT_DOCUMENTS_DESTROYED": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "count",
|
||||
"description": "Number of top-level content documents destroyed; used in conjunction with use counter histograms"
|
||||
}
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче