зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to tabcandy-central.
This commit is contained in:
Коммит
d35d6cdf00
|
@ -713,6 +713,7 @@ nsAttributeCharacteristics nsARIAMap::gWAIUnivAttrMap[] = {
|
|||
{&nsAccessibilityAtoms::aria_grabbed, ATTR_VALTOKEN },
|
||||
{&nsAccessibilityAtoms::aria_haspopup, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
|
||||
{&nsAccessibilityAtoms::aria_invalid, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
|
||||
{&nsAccessibilityAtoms::aria_label, ATTR_BYPASSOBJ },
|
||||
{&nsAccessibilityAtoms::aria_labelledby, ATTR_BYPASSOBJ },
|
||||
{&nsAccessibilityAtoms::aria_level, ATTR_BYPASSOBJ }, /* handled via groupPosition */
|
||||
{&nsAccessibilityAtoms::aria_live, ATTR_VALTOKEN },
|
||||
|
|
|
@ -2694,16 +2694,9 @@ nsAccessible::Shutdown()
|
|||
nsresult
|
||||
nsAccessible::GetARIAName(nsAString& aName)
|
||||
{
|
||||
// First check for label override via aria-label property
|
||||
nsAutoString label;
|
||||
if (mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_label,
|
||||
label)) {
|
||||
label.CompressWhitespace();
|
||||
aName = label;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Second check for label override via aria-labelledby relationship
|
||||
|
||||
// aria-labelledby now takes precedence over aria-label
|
||||
nsresult rv = nsTextEquivUtils::
|
||||
GetTextEquivFromIDRefs(this, nsAccessibilityAtoms::aria_labelledby, label);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
@ -2711,7 +2704,14 @@ nsAccessible::GetARIAName(nsAString& aName)
|
|||
aName = label;
|
||||
}
|
||||
|
||||
return rv;
|
||||
if (label.IsEmpty() &&
|
||||
mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_label,
|
||||
label)) {
|
||||
label.CompressWhitespace();
|
||||
aName = label;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=475006
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=391829
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=581952
|
||||
-->
|
||||
<head>
|
||||
<title>Group attributes tests</title>
|
||||
|
@ -69,6 +70,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391829
|
|||
testAttrs("statusChild", {"container-live-role" : "status"}, true);
|
||||
testAttrs("timerChild", {"container-live-role" : "timer"}, true);
|
||||
|
||||
// absent aria-label and aria-labelledby object attribute
|
||||
testAbsentAttrs("label", {"label" : "foo"});
|
||||
testAbsentAttrs("labelledby", {"labelledby" : "label"});
|
||||
|
||||
// container that has no default live attribute
|
||||
testAttrs("liveGroup", {"live" : "polite"}, true);
|
||||
testAttrs("liveGroupChild", {"container-live" : "polite"}, true);
|
||||
|
@ -93,11 +98,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391829
|
|||
title="Extend nsARIAMap to capture ARIA attribute characteristics">
|
||||
Mozilla Bug 475006
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=391829"
|
||||
title="Add support for container-live-role to object attributes">
|
||||
Mozilla Bug 391829
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=391829"
|
||||
title="Add support for container-live-role to object attributes">
|
||||
Mozilla Bug 391829
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=581952"
|
||||
title="Make explicit that aria-label is not an object attribute">
|
||||
Mozilla Bug 475006
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
@ -129,6 +139,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391829
|
|||
<div id="status" role="status">excuse <div id="statusChild">me</div></div>
|
||||
<div id="timer" role="timer">excuse <div id="timerChild">me</div></div>
|
||||
|
||||
<!-- aria-label[ledby] should not be an object attribute -->
|
||||
<div id="label" role="checkbox" aria-label="foo"></div>
|
||||
<div id="labelledby" role="checkbox" aria-labelledby="label"></div>
|
||||
|
||||
<!-- unusual live case -->
|
||||
<div id="liveGroup" role="group" aria-live="polite">
|
||||
excuse <div id="liveGroupChild">me</div>
|
||||
|
|
|
@ -69,8 +69,8 @@
|
|||
|
||||
<!-- bricks -->
|
||||
<ruleset id="aria">
|
||||
<rule attr="aria-label" type="string"/>
|
||||
<rule attr="aria-labelledby" type="ref"/>
|
||||
<rule attr="aria-label" type="string"/>
|
||||
</ruleset>
|
||||
|
||||
<ruleset id="htmlctrl_start">
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
// Simple label provided via ARIA
|
||||
testName("btn_simple_aria_label", "I am a button");
|
||||
|
||||
// aria-label and aria-labelledby, expect aria-label
|
||||
testName("btn_both_aria_labels", "I am a button, two");
|
||||
// aria-label and aria-labelledby, expect aria-labelledby
|
||||
testName("btn_both_aria_labels", "text I am a button, two");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// aria-labelledby
|
||||
|
@ -207,7 +207,7 @@
|
|||
<br/>
|
||||
<!-- aria-label plus aria-labelledby -->
|
||||
<span id="btn_both_aria_labels" role="button" aria-label="I am a button, two"
|
||||
aria-labelledby="labelledby_text"/>
|
||||
aria-labelledby="labelledby_text btn_both_aria_labels"/>
|
||||
<br/>
|
||||
|
||||
<!-- aria-labelledby, single relation -->
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
// Simple label provided via ARIA
|
||||
testName("btn_simple_aria_label", "I am a button");
|
||||
|
||||
// aria-label and aria-labelledby, expect aria-label
|
||||
testName("btn_both_aria_labels", "I am a button, two");
|
||||
// aria-label and aria-labelledby, expect aria-labelledby
|
||||
testName("btn_both_aria_labels", "text I am a button, two");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// aria-labelledby
|
||||
|
@ -205,9 +205,10 @@
|
|||
|
||||
<!-- aria-label, simple label -->
|
||||
<button id="btn_simple_aria_label" aria-label="I am a button"/>
|
||||
|
||||
<!-- aria-label plus aria-labelledby -->
|
||||
<button id="btn_both_aria_labels" aria-label="I am a button, two"
|
||||
aria-labelledby="labelledby_text"/>
|
||||
aria-labelledby="labelledby_text btn_both_aria_labels"/>
|
||||
|
||||
<!-- aria-labelledby, single relation -->
|
||||
<description id="labelledby_text">text</description>
|
||||
|
|
|
@ -83,10 +83,9 @@
|
|||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<!-- button, aria-label, preferred to aria-labelledby -->
|
||||
<!-- aria-labelledby preferred to aria-label -->
|
||||
<button id="btn_aria_label"
|
||||
aria-label="button label"
|
||||
aria-labelledby="btn_aria_labelledby_text">1</button>
|
||||
aria-label="button label">1</button>
|
||||
<br/>
|
||||
|
||||
<!-- button, aria-labelledby, preferred to html:label -->
|
||||
|
@ -109,10 +108,9 @@
|
|||
<!-- button, no content, name from @title -->
|
||||
<button id="btn_title" title="title"></button>
|
||||
|
||||
<!-- input, aria-label, preferred to aria-labelledby -->
|
||||
<!-- input, aria-label -->
|
||||
<input type="button" id="input_aria_label"
|
||||
aria-label="button label"
|
||||
aria-labelledby="aria_labelledby_text_for_input"
|
||||
value="1"/>
|
||||
<br/>
|
||||
|
||||
|
|
|
@ -61,10 +61,9 @@
|
|||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<!-- aria-label, preferred to aria-labelledby -->
|
||||
<!-- aria-label -->
|
||||
<a id="aria_label" href="mozilla.org"
|
||||
aria-label="anchor label"
|
||||
aria-labelledby="text">1</a>
|
||||
aria-label="anchor label">1</a>
|
||||
<br/>
|
||||
|
||||
<!-- aria-labelledby, preferred to html:label -->
|
||||
|
|
|
@ -343,6 +343,7 @@ pref("browser.tabs.opentabfor.middleclick", true);
|
|||
pref("browser.tabs.loadDivertedInBackground", false);
|
||||
pref("browser.tabs.loadBookmarksInBackground", false);
|
||||
pref("browser.tabs.tabClipWidth", 140);
|
||||
pref("browser.tabs.animate", true);
|
||||
|
||||
// Where to show tab close buttons:
|
||||
// 0 on active tab only
|
||||
|
|
|
@ -29,6 +29,7 @@ tabbrowser {
|
|||
max-width: 250px;
|
||||
min-width: 100px;
|
||||
width: 0;
|
||||
-moz-transition: min-width .2s ease-out, max-width .25s ease-out;
|
||||
}
|
||||
|
||||
.tabbrowser-tab:not([pinned]):not([fadein]) {
|
||||
|
@ -36,19 +37,15 @@ tabbrowser {
|
|||
min-width: 1px;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[fadein]:not([pinned]) {
|
||||
-moz-transition: min-width .2s ease-out, max-width .25s ease-out;
|
||||
}
|
||||
|
||||
.tabbrowser-tab:not([fadein]):not([pinned]) > .tab-text,
|
||||
.tabbrowser-tab:not([fadein]):not([pinned]) > .tab-icon-image,
|
||||
.tabbrowser-tab:not([fadein]):not([pinned]) > .tab-close-button {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[fadein] > .tab-text,
|
||||
.tabbrowser-tab[fadein] > .tab-icon-image,
|
||||
.tabbrowser-tab[fadein] > .tab-close-button {
|
||||
.tabbrowser-tab > .tab-text,
|
||||
.tabbrowser-tab > .tab-icon-image,
|
||||
.tabbrowser-tab > .tab-close-button {
|
||||
-moz-transition: opacity .25s;
|
||||
}
|
||||
|
||||
|
|
|
@ -2051,7 +2051,7 @@ function BrowserCloseTabOrWindow() {
|
|||
#endif
|
||||
|
||||
// If the current tab is the last one, this will close the window.
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.removeCurrentTab({animate: true});
|
||||
}
|
||||
|
||||
function BrowserTryToCloseWindow()
|
||||
|
|
|
@ -457,9 +457,23 @@
|
|||
label="&brandShortName;"
|
||||
style="-moz-user-focus: ignore;">
|
||||
<menupopup id="appmenu-popup">
|
||||
<menuitem id="appmenu_newNavigator"
|
||||
label="&newNavigatorCmd.label;"
|
||||
command="cmd_newNavigator"/>
|
||||
<hbox flex="1" class="split-menuitem">
|
||||
<menuitem id="appmenu_newTab"
|
||||
class="split-menuitem-item"
|
||||
flex="1"
|
||||
label="&tabCmd.label;"
|
||||
command="cmd_newNavigatorTab"/>
|
||||
<menu class="split-menuitem-menu">
|
||||
<menupopup>
|
||||
<menuitem id="appmenu_newTab_sub"
|
||||
label="&tabCmd.label;"
|
||||
command="cmd_newNavigatorTab"/>
|
||||
<menuitem id="appmenu_newNavigator"
|
||||
label="&newNavigatorCmd.label;"
|
||||
command="cmd_newNavigator"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</hbox>
|
||||
<menuseparator/>
|
||||
<menuitem id="appmenu_savePage"
|
||||
label="&savePageCmd.label;"
|
||||
|
|
|
@ -1104,7 +1104,8 @@
|
|||
// doesn't go well together with the width transition. So we skip the
|
||||
// transition in that case.
|
||||
if (aSkipAnimation ||
|
||||
this.tabContainer.getAttribute("overflow") == "true") {
|
||||
this.tabContainer.getAttribute("overflow") == "true" ||
|
||||
!Services.prefs.getBoolPref("browser.tabs.animate")) {
|
||||
t.setAttribute("fadein", "true");
|
||||
setTimeout(function (tabContainer) {
|
||||
tabContainer._handleNewTab(t);
|
||||
|
@ -1154,12 +1155,26 @@
|
|||
notificationbox.setAttribute("flex", "1");
|
||||
notificationbox.appendChild(b);
|
||||
b.setAttribute("flex", "1");
|
||||
|
||||
var position = this.tabs.length - 1;
|
||||
var uniqueId = "panel" + Date.now() + position;
|
||||
notificationbox.id = uniqueId;
|
||||
t.linkedPanel = uniqueId;
|
||||
t.linkedBrowser = b;
|
||||
t._tPos = position;
|
||||
if (t.previousSibling.selected)
|
||||
t.setAttribute("afterselected", true);
|
||||
|
||||
// NB: this appendChild call causes us to run constructors for the
|
||||
// browser element, which fires off a bunch of notifications. Some
|
||||
// of those notifications can cause code to run that inspects our
|
||||
// state, so it is important that the tab element is fully
|
||||
// initialized by this point.
|
||||
this.mPanelContainer.appendChild(notificationbox);
|
||||
|
||||
this.tabContainer.updateVisibility();
|
||||
|
||||
// wire up a progress listener for the new browser object.
|
||||
var position = this.tabs.length - 1;
|
||||
var tabListener = this.mTabProgressListener(t, b, blank);
|
||||
const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
|
||||
.createInstance(Components.interfaces.nsIWebProgress);
|
||||
|
@ -1302,9 +1317,10 @@
|
|||
</method>
|
||||
|
||||
<method name="removeCurrentTab">
|
||||
<parameter name="aParams"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.removeTab(this.mCurrentTab);
|
||||
this.removeTab(this.mCurrentTab, aParams);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -1315,9 +1331,36 @@
|
|||
|
||||
<method name="removeTab">
|
||||
<parameter name="aTab"/>
|
||||
<parameter name="aParams"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._endRemoveTab(this._beginRemoveTab(aTab, false, null, true));
|
||||
var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
|
||||
if (aParams)
|
||||
var animate = aParams.animate;
|
||||
|
||||
if (!this._beginRemoveTab(aTab, false, null, true))
|
||||
return;
|
||||
|
||||
/* Don't animate if:
|
||||
- the caller didn't opt in
|
||||
- this is the last tab in the window
|
||||
- this is a pinned tab
|
||||
- a bunch of other tabs are already closing (arbitrary threshold)
|
||||
- the fadein attribute hasn't been set yet
|
||||
- browser.tabs.animate is false */
|
||||
|
||||
if (!animate ||
|
||||
isLastTab ||
|
||||
aTab.pinned ||
|
||||
this._removingTabs.length > 3 ||
|
||||
aTab.getAttribute("fadein") != "true" ||
|
||||
!Services.prefs.getBoolPref("browser.tabs.animate")) {
|
||||
this._endRemoveTab(aTab);
|
||||
return;
|
||||
}
|
||||
|
||||
this._blurTab(aTab);
|
||||
aTab.removeAttribute("fadein");
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -1328,7 +1371,6 @@
|
|||
false
|
||||
</field>
|
||||
|
||||
<!-- Returns everything that _endRemoveTab needs in an array. -->
|
||||
<method name="_beginRemoveTab">
|
||||
<parameter name="aTab"/>
|
||||
<parameter name="aTabWillBeMoved"/>
|
||||
|
@ -1337,14 +1379,14 @@
|
|||
<body>
|
||||
<![CDATA[
|
||||
if (this._removingTabs.indexOf(aTab) > -1 || this._windowIsClosing)
|
||||
return null;
|
||||
return false;
|
||||
|
||||
var browser = this.getBrowserForTab(aTab);
|
||||
|
||||
if (!aTabWillBeMoved) {
|
||||
let ds = browser.docShell;
|
||||
if (ds && ds.contentViewer && !ds.contentViewer.permitUnload())
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var closeWindow = false;
|
||||
|
@ -1400,18 +1442,26 @@
|
|||
tab.owner = null;
|
||||
});
|
||||
|
||||
return [aTab, closeWindow, newTab];
|
||||
aTab._endRemoveArgs = [closeWindow, newTab];
|
||||
return true;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_endRemoveTab">
|
||||
<parameter name="args"/>
|
||||
<parameter name="aTab"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!args)
|
||||
if (!aTab || !aTab._endRemoveArgs)
|
||||
return;
|
||||
var [aTab, aCloseWindow, aNewTab] = args;
|
||||
|
||||
var [aCloseWindow, aNewTab] = aTab._endRemoveArgs;
|
||||
aTab._endRemoveArgs = null;
|
||||
|
||||
if (this._windowIsClosing) {
|
||||
aCloseWindow = false;
|
||||
aNewTab = false;
|
||||
}
|
||||
|
||||
this._lastRelatedTab = null;
|
||||
|
||||
|
@ -1427,7 +1477,7 @@
|
|||
if (aCloseWindow) {
|
||||
this._windowIsClosing = true;
|
||||
while (this._removingTabs.length)
|
||||
this._endRemoveTab([this._removingTabs[0], false]);
|
||||
this._endRemoveTab(this._removingTabs[0]);
|
||||
} else if (!this._windowIsClosing) {
|
||||
if (aNewTab)
|
||||
focusAndSelectUrlBar();
|
||||
|
@ -1554,13 +1604,13 @@
|
|||
<body>
|
||||
<![CDATA[
|
||||
// That's gBrowser for the other window, not the tab's browser!
|
||||
var remoteBrowser =
|
||||
aOtherTab.ownerDocument.defaultView.getBrowser();
|
||||
var remoteBrowser = aOtherTab.ownerDocument.defaultView.gBrowser;
|
||||
|
||||
// First, start teardown of the other browser. Make sure to not
|
||||
// fire the beforeunload event in the process. Close the other
|
||||
// window if this was its last tab.
|
||||
var endRemoveArgs = remoteBrowser._beginRemoveTab(aOtherTab, true, true);
|
||||
if (!remoteBrowser._beginRemoveTab(aOtherTab, true, true))
|
||||
return;
|
||||
|
||||
// Unhook our progress listener
|
||||
var ourIndex = aOurTab._tPos;
|
||||
|
@ -1587,7 +1637,7 @@
|
|||
ourBrowser.swapDocShells(aOtherTab.linkedBrowser);
|
||||
|
||||
// Finish tearing down the tab that's going away.
|
||||
remoteBrowser._endRemoveTab(endRemoveArgs);
|
||||
remoteBrowser._endRemoveTab(aOtherTab);
|
||||
|
||||
// Restore the progress listener
|
||||
tabListener = this.mTabProgressListener(aOurTab, ourBrowser,
|
||||
|
@ -2181,7 +2231,7 @@
|
|||
if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey &&
|
||||
aEvent.keyCode == KeyEvent.DOM_VK_F4 &&
|
||||
this.mTabBox.handleCtrlPageUpDown) {
|
||||
this.removeCurrentTab();
|
||||
this.removeCurrentTab({animate: true});
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
|
@ -2383,6 +2433,10 @@
|
|||
|
||||
var tabs = document.getBindingParent(this);
|
||||
tabs.removeAttribute("overflow");
|
||||
|
||||
tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser._endRemoveTab,
|
||||
tabs.tabbrowser);
|
||||
|
||||
tabs._positionPinnedTabs();
|
||||
]]></handler>
|
||||
<handler event="overflow"><![CDATA[
|
||||
|
@ -2768,8 +2822,15 @@
|
|||
<handler event="TabSelect" action="this._handleTabSelect();"/>
|
||||
|
||||
<handler event="transitionend"><![CDATA[
|
||||
if (event.propertyName == "max-width")
|
||||
this._handleNewTab(event.target);
|
||||
if (event.propertyName != "max-width")
|
||||
return;
|
||||
|
||||
var tab = event.target;
|
||||
|
||||
if (tab.getAttribute("fadein") == "true")
|
||||
this._handleNewTab(tab);
|
||||
else if (this.tabbrowser._removingTabs.indexOf(tab) > -1)
|
||||
this.tabbrowser._endRemoveTab(tab);
|
||||
]]></handler>
|
||||
|
||||
<handler event="dblclick"><![CDATA[
|
||||
|
@ -2785,7 +2846,7 @@
|
|||
|
||||
if (event.target.localName == "tab") {
|
||||
if (this.childNodes.length > 1 || !this._closeWindowWithLastTab)
|
||||
this.tabbrowser.removeTab(event.target);
|
||||
this.tabbrowser.removeTab(event.target, {animate: true});
|
||||
} else if (event.originalTarget.localName == "box") {
|
||||
BrowserOpenTab();
|
||||
} else {
|
||||
|
@ -3102,7 +3163,7 @@
|
|||
// Reset the "ignored click" flag
|
||||
this._ignoredClick = false;
|
||||
|
||||
tabContainer.tabbrowser.removeTab(bindingParent);
|
||||
tabContainer.tabbrowser.removeTab(bindingParent, {animate: true});
|
||||
tabContainer._blockDblClick = true;
|
||||
|
||||
/* XXXmano hack (see bug 343628):
|
||||
|
|
|
@ -99,6 +99,7 @@ _BROWSER_FILES = \
|
|||
title_test.svg \
|
||||
browser_bug329212.js \
|
||||
browser_bug356571.js \
|
||||
browser_bug380960.js \
|
||||
browser_bug386835.js \
|
||||
browser_bug405137.js \
|
||||
browser_bug406216.js \
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
function test() {
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", tabAdded, false);
|
||||
|
||||
var tab = gBrowser.addTab("about:blank", { skipAnimation: true });
|
||||
gBrowser.removeTab(tab);
|
||||
is(tab.parentNode, null, "tab removed immediately");
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setBoolPref("browser.tabs.animate", true);
|
||||
nextAsyncText();
|
||||
}
|
||||
|
||||
function tabAdded() {
|
||||
info("tab added");
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
if (Services.prefs.prefHasUserValue("browser.tabs.animate"))
|
||||
Services.prefs.clearUserPref("browser.tabs.animate");
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", tabAdded, false);
|
||||
finish();
|
||||
}
|
||||
|
||||
var asyncTests = [
|
||||
function (tab) {
|
||||
info("closing tab with middle click");
|
||||
EventUtils.synthesizeMouse(tab, 2, 2, { button: 1 });
|
||||
},
|
||||
function (tab) {
|
||||
info("closing tab with accel+w");
|
||||
gBrowser.selectedTab = tab;
|
||||
content.focus();
|
||||
EventUtils.synthesizeKey("w", { accelKey: true });
|
||||
},
|
||||
function (tab) {
|
||||
info("closing tab by clicking the tab close button");
|
||||
gBrowser.selectedTab = tab;
|
||||
var button = document.getAnonymousElementByAttribute(tab, "anonid", "close-button");
|
||||
EventUtils.synthesizeMouse(button, 2, 2, {});
|
||||
}
|
||||
];
|
||||
|
||||
function nextAsyncText() {
|
||||
info("tests left: " + asyncTests.length + "; starting next");
|
||||
var tab = gBrowser.addTab("about:blank", { skipAnimation: true });
|
||||
|
||||
var gotCloseEvent = false;
|
||||
|
||||
tab.addEventListener("TabClose", function () {
|
||||
info("got TabClose event");
|
||||
gotCloseEvent = true;
|
||||
|
||||
const DEFAULT_ANIMATION_LENGTH = 250;
|
||||
const MAX_WAIT_TIME = DEFAULT_ANIMATION_LENGTH * 3;
|
||||
const INTERVAL_LENGTH = 100;
|
||||
var polls = Math.ceil(MAX_WAIT_TIME / INTERVAL_LENGTH);
|
||||
var pollTabRemoved = setInterval(function () {
|
||||
--polls;
|
||||
if (tab.parentNode && polls > 0)
|
||||
return;
|
||||
clearInterval(pollTabRemoved);
|
||||
|
||||
is(tab.parentNode, null, "tab removed after at most " + MAX_WAIT_TIME + " ms");
|
||||
|
||||
if (asyncTests.length)
|
||||
nextAsyncText();
|
||||
else
|
||||
cleanup();
|
||||
}, INTERVAL_LENGTH);
|
||||
}, false);
|
||||
|
||||
asyncTests.shift()(tab);
|
||||
|
||||
ok(gotCloseEvent, "got the close event syncronously");
|
||||
|
||||
is(tab.parentNode, gBrowser.tabContainer, "tab still exists when it's about to be removed asynchronously");
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
var expected = ["TabOpen", "onLocationChange", "onStateChange", "onLinkIconAvailable"];
|
||||
var expected = ["TabOpen", "onStateChange", "onLocationChange", "onLinkIconAvailable"];
|
||||
var actual = [];
|
||||
var tabIndex = -1;
|
||||
__defineGetter__("tab", function () gBrowser.tabs[tabIndex]);
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
#
|
||||
|
||||
# Define an include-at-most-once flag
|
||||
#ifdef INCLUDED_CONFIG_MK
|
||||
#$(error Don't include config.mk twice!)
|
||||
#endif
|
||||
INCLUDED_CONFIG_MK = 1
|
||||
|
||||
EXIT_ON_ERROR = set -e; # Shell loops continue past errors without this.
|
||||
|
@ -182,7 +185,7 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
MOZALLOC_LIB = -L$(DIST)/bin $(call EXPAND_MOZLIBNAME,mozalloc)
|
||||
MOZALLOC_LIB = $(call EXPAND_LIBNAME_PATH,mozalloc,$(DIST)/lib)
|
||||
|
||||
OS_CFLAGS += $(_DEBUG_CFLAGS)
|
||||
OS_CXXFLAGS += $(_DEBUG_CFLAGS)
|
||||
|
|
|
@ -5696,12 +5696,6 @@ MOZ_ARG_DISABLE_BOOL(jsd,
|
|||
dnl ========================================================
|
||||
dnl = Disable IPC support for tabs and plugins
|
||||
dnl ========================================================
|
||||
case "${target}" in
|
||||
*-wince*)
|
||||
MOZ_IPC=
|
||||
;;
|
||||
esac
|
||||
|
||||
MOZ_ARG_DISABLE_BOOL(ipc,
|
||||
[ --disable-ipc Disable IPC supports for tabs and plugins],
|
||||
MOZ_IPC=,
|
||||
|
|
|
@ -1014,7 +1014,7 @@ nsContentUtils::ParseIntMarginValue(const nsAString& aString, nsIntMargin& resul
|
|||
|
||||
PRInt32 start = 0, end = 0;
|
||||
for (int count = 0; count < 4; count++) {
|
||||
if (end >= marginStr.Length())
|
||||
if ((PRUint32)end >= marginStr.Length())
|
||||
return PR_FALSE;
|
||||
|
||||
// top, right, bottom, left
|
||||
|
@ -6318,7 +6318,7 @@ nsIContentUtils::FindInternalContentViewer(const char* aType,
|
|||
#ifdef MOZ_MEDIA
|
||||
#ifdef MOZ_OGG
|
||||
if (nsHTMLMediaElement::IsOggEnabled()) {
|
||||
for (int i = 0; i < NS_ARRAY_LENGTH(nsHTMLMediaElement::gOggTypes); ++i) {
|
||||
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(nsHTMLMediaElement::gOggTypes); ++i) {
|
||||
const char* type = nsHTMLMediaElement::gOggTypes[i];
|
||||
if (!strcmp(aType, type)) {
|
||||
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
|
||||
|
@ -6333,7 +6333,7 @@ nsIContentUtils::FindInternalContentViewer(const char* aType,
|
|||
|
||||
#ifdef MOZ_WEBM
|
||||
if (nsHTMLMediaElement::IsWebMEnabled()) {
|
||||
for (int i = 0; i < NS_ARRAY_LENGTH(nsHTMLMediaElement::gWebMTypes); ++i) {
|
||||
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(nsHTMLMediaElement::gWebMTypes); ++i) {
|
||||
const char* type = nsHTMLMediaElement::gWebMTypes[i];
|
||||
if (!strcmp(aType, type)) {
|
||||
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
|
||||
|
|
|
@ -1719,6 +1719,13 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPreloadingImages)
|
||||
|
||||
|
||||
if (tmp->mBoxObjectTable) {
|
||||
tmp->mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nsnull);
|
||||
delete tmp->mBoxObjectTable;
|
||||
tmp->mBoxObjectTable = nsnull;
|
||||
}
|
||||
|
||||
// nsDocument has a pretty complex destructor, so we're going to
|
||||
// assume that *most* cycles you actually want to break somewhere
|
||||
// else, and not unlink an awful lot here.
|
||||
|
|
|
@ -212,7 +212,7 @@ nsICanvasRenderingContextWebGL_BufferSubData(JSContext *cx, uintN argc, jsval *v
|
|||
|
||||
/*
|
||||
* ReadPixels takes:
|
||||
* TexImage2D(int, int, int, int, uint, uint, ArrayBufferView)
|
||||
* ReadPixels(int, int, int, int, uint, uint, ArrayBufferView)
|
||||
*/
|
||||
static JSBool
|
||||
nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
|
||||
|
@ -230,8 +230,7 @@ nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
|
||||
return JS_FALSE;
|
||||
|
||||
// XXX we currently allow passing only 6 args to support the API. Eventually drop that.
|
||||
if (argc < 6)
|
||||
if (argc < 7)
|
||||
return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
|
||||
|
||||
jsval *argv = JS_ARGV(cx, vp);
|
||||
|
@ -244,40 +243,8 @@ nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
|
|||
GET_UINT32_ARG(argv4, 4);
|
||||
GET_UINT32_ARG(argv5, 5);
|
||||
|
||||
if (argc == 6) {
|
||||
/*** BEGIN old API deprecated code. Eventually drop that. ***/
|
||||
// the code here is ugly, but temporary. It comes from the old ReadPixels implementation.
|
||||
// Remove it as soon as it's OK to drop the old API.
|
||||
|
||||
PRInt32 byteLength;
|
||||
rv = self->ReadPixels_byteLength_old_API_deprecated(argv2, argv3, argv4, argv5, &byteLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
xpc_qsThrow(cx, NS_ERROR_FAILURE);
|
||||
return JS_FALSE;
|
||||
}
|
||||
JSObject *abufObject = js_CreateArrayBuffer(cx, byteLength);
|
||||
if (!abufObject) {
|
||||
xpc_qsThrow(cx, NS_ERROR_FAILURE);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
js::ArrayBuffer *abuf = js::ArrayBuffer::fromJSObject(abufObject);
|
||||
|
||||
rv = self->ReadPixels_buf(
|
||||
argv0, argv1, argv2, argv3, argv4, argv5, abuf);
|
||||
if (NS_FAILED(rv)) {
|
||||
xpc_qsThrow(cx, NS_ERROR_FAILURE);
|
||||
return JS_FALSE;
|
||||
}
|
||||
JSObject *retval = js_CreateTypedArrayWithBuffer(cx, js::TypedArray::TYPE_UINT8,
|
||||
abufObject, 0, byteLength);
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(retval);
|
||||
return JS_TRUE; // return here to be unaffected by the *vp = JSVAL_VOID; below
|
||||
|
||||
/*** END old API deprecated code ***/
|
||||
} else if (argc == 7 &&
|
||||
!JSVAL_IS_PRIMITIVE(argv[6]))
|
||||
if (argc == 7 &&
|
||||
!JSVAL_IS_PRIMITIVE(argv[6]))
|
||||
{
|
||||
JSObject *argv6 = JSVAL_TO_OBJECT(argv[6]);
|
||||
if (js_IsArrayBuffer(argv6)) {
|
||||
|
@ -306,7 +273,7 @@ nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
|
|||
|
||||
/*
|
||||
* TexImage2D takes:
|
||||
* TexImage2D(uint, int, uint, int, int, int, uint, uint, ArrayBufferView)\
|
||||
* TexImage2D(uint, int, uint, int, int, int, uint, uint, ArrayBufferView)
|
||||
* TexImage2D(uint, int, uint, uint, uint, nsIDOMElement)
|
||||
* TexImage2D(uint, int, uint, uint, uint, ImageData)
|
||||
*/
|
||||
|
@ -326,9 +293,7 @@ nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
|
||||
return JS_FALSE;
|
||||
|
||||
// XXX we currently allow passing only 3 args to support the API. Eventually drop that.
|
||||
// if (argc < 6 || argc == 7 || argc == 8)
|
||||
if (argc < 3)
|
||||
if (argc < 6 || argc == 7 || argc == 8)
|
||||
return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
|
||||
|
||||
jsval *argv = JS_ARGV(cx, vp);
|
||||
|
@ -337,22 +302,9 @@ nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
|
|||
GET_UINT32_ARG(argv0, 0);
|
||||
GET_INT32_ARG(argv1, 1);
|
||||
|
||||
if (argc > 2 && JSVAL_IS_OBJECT(argv[2])) {
|
||||
// the old API. Eventually drop that.
|
||||
|
||||
nsIDOMElement *elt;
|
||||
xpc_qsSelfRef eltRef;
|
||||
rv = xpc_qsUnwrapArg<nsIDOMElement>(cx, argv[2], &elt, &eltRef.ptr, &argv[2]);
|
||||
if (NS_FAILED(rv)) return JS_FALSE;
|
||||
|
||||
GET_OPTIONAL_UINT32_ARG(argv3, 3);
|
||||
GET_OPTIONAL_UINT32_ARG(argv4, 4);
|
||||
|
||||
rv = self->TexImage2D_dom_old_API_deprecated(argv0, argv1, elt, argv3, argv4);
|
||||
} else if (argc > 5 &&
|
||||
!JSVAL_IS_PRIMITIVE(argv[5]))
|
||||
if (argc > 5 &&
|
||||
!JSVAL_IS_PRIMITIVE(argv[5]))
|
||||
{
|
||||
|
||||
// implement the variants taking a DOMElement as argv[5]
|
||||
GET_UINT32_ARG(argv2, 2);
|
||||
GET_UINT32_ARG(argv3, 3);
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
|
||||
#include "GLContextProvider.h"
|
||||
|
||||
#include "prenv.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
|
@ -275,29 +277,77 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
|||
format.depth = 16;
|
||||
format.minDepth = 1;
|
||||
|
||||
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
|
||||
#ifdef XP_WIN
|
||||
// On Windows, we may have a choice of backends, including straight
|
||||
// OpenGL, D3D through ANGLE via EGL, or straight EGL/GLES2.
|
||||
// We don't differentiate the latter two yet, but we allow for
|
||||
// a env var to try EGL first, instead of last.
|
||||
bool preferEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL") != nsnull;
|
||||
|
||||
// if we want EGL, try it first
|
||||
if (!gl && preferEGL) {
|
||||
gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// if it failed, then try the default provider, whatever that is
|
||||
if (!gl) {
|
||||
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// if that failed, and we weren't already preferring EGL, try it now.
|
||||
if (!gl && !preferEGL) {
|
||||
gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// other platforms just use whatever the default is
|
||||
if (!gl) {
|
||||
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// last chance, try OSMesa
|
||||
if (!gl) {
|
||||
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl) {
|
||||
if (!InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
} else {
|
||||
// make sure we notify always in this case, because it's likely going to be
|
||||
// painfully slow
|
||||
LogMessage("WebGL: Using software rendering via OSMesa");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gl) {
|
||||
LogMessage("WebGL: Can't get a usable OpenGL context.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
printf_stderr ("--- WebGL context created: %p\n", gl.get());
|
||||
|
||||
#ifdef USE_GLES2
|
||||
// On native GLES2, no need to validate, the compiler will do it
|
||||
mShaderValidation = PR_FALSE;
|
||||
#else
|
||||
// Check the shader validator pref
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
if (gl->IsGLES2()) {
|
||||
// On native GLES2, no need to validate, the compiler will do it
|
||||
mShaderValidation = PR_FALSE;
|
||||
} else {
|
||||
// Otherwise, check the shader validator pref
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
|
||||
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
|
||||
#endif
|
||||
|
||||
if (!InitAndValidateGL()) {
|
||||
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (!InitAndValidateGL()) {
|
||||
LogMessage("WebGL: Can't get a usable OpenGL context.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LogMessage("WebGL: Using software rendering via OSMesa");
|
||||
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
|
||||
}
|
||||
|
||||
mWidth = width;
|
||||
|
|
|
@ -2409,58 +2409,6 @@ WebGLContext::ReadPixels_buf(WebGLint x, WebGLint y, WebGLsizei width, WebGLsize
|
|||
pixels ? pixels->byteLength : 0);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::ReadPixels_byteLength_old_API_deprecated(WebGLsizei width, WebGLsizei height,
|
||||
WebGLenum format, WebGLenum type, WebGLsizei *retval)
|
||||
{
|
||||
*retval = 0;
|
||||
if (width < 0 || height < 0)
|
||||
return ErrorInvalidValue("ReadPixels: negative size passed");
|
||||
|
||||
PRUint32 size = 0;
|
||||
switch (format) {
|
||||
case LOCAL_GL_ALPHA:
|
||||
size = 1;
|
||||
break;
|
||||
case LOCAL_GL_RGB:
|
||||
size = 3;
|
||||
break;
|
||||
case LOCAL_GL_RGBA:
|
||||
size = 4;
|
||||
break;
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("ReadPixels: format", format);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
// case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
// case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
||||
// case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
||||
case LOCAL_GL_UNSIGNED_BYTE:
|
||||
break;
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("ReadPixels: type", type);
|
||||
}
|
||||
PRUint32 packAlignment;
|
||||
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*) &packAlignment);
|
||||
|
||||
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * size;
|
||||
|
||||
// alignedRowSize = row size rounded up to next multiple of
|
||||
// packAlignment which is a power of 2
|
||||
CheckedUint32 checked_alignedRowSize
|
||||
= ((checked_plainRowSize + packAlignment-1) / packAlignment) * packAlignment;
|
||||
|
||||
CheckedUint32 checked_neededByteLength = (height-1)*checked_alignedRowSize + checked_plainRowSize;
|
||||
|
||||
if (!checked_neededByteLength.valid())
|
||||
return ErrorInvalidOperation("ReadPixels: integer overflow computing the needed buffer size");
|
||||
|
||||
*retval = checked_neededByteLength.value();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::RenderbufferStorage(WebGLenum target, WebGLenum internalformat, WebGLsizei width, WebGLsizei height)
|
||||
{
|
||||
|
@ -3229,27 +3177,6 @@ WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum interna
|
|||
isurf->Data(), byteLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::TexImage2D_dom_old_API_deprecated(WebGLenum target, WebGLint level, nsIDOMElement *elt,
|
||||
PRBool flipY, PRBool premultiplyAlpha)
|
||||
{
|
||||
nsRefPtr<gfxImageSurface> isurf;
|
||||
|
||||
nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf),
|
||||
flipY, premultiplyAlpha);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
NS_ASSERTION(isurf->Stride() == isurf->Width() * 4, "Bad stride!");
|
||||
|
||||
PRUint32 byteLength = isurf->Stride() * isurf->Height();
|
||||
|
||||
return TexImage2D_base(target, level, LOCAL_GL_RGBA,
|
||||
isurf->Width(), isurf->Height(), 0,
|
||||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
|
||||
isurf->Data(), byteLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::TexSubImage2D(PRInt32 dummy)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
var input = document.getElementById("i");
|
||||
input.setAttribute('type', "image");
|
||||
input.removeAttribute('type');
|
||||
input.placeholder = "Y";
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="boom();"><input id="i" /></body>
|
||||
</html>
|
|
@ -16,3 +16,4 @@ load 515829-1.html
|
|||
load 515829-2.html
|
||||
load 570566-1.html
|
||||
load 571428-1.html
|
||||
load 580507-1.xhtml
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* This interface is used so that the parser can notify the textarea when
|
||||
* it has finished loading content.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(36878df2-1dd2-11b2-99a0-ea9fab347485)]
|
||||
interface nsITextAreaElement : nsISupports
|
||||
{
|
||||
/**
|
||||
* Called when the parser is done adding child content
|
||||
* to the select during document loading.
|
||||
*/
|
||||
void doneAddingChildren();
|
||||
};
|
|
@ -128,7 +128,6 @@ endif
|
|||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
INCLUDES += \
|
||||
|
|
|
@ -66,11 +66,6 @@ public:
|
|||
// nsIDOMHTMLMapElement
|
||||
NS_DECL_NSIDOMHTMLMAPELEMENT
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers);
|
||||
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
||||
PRBool aNullParent = PR_TRUE);
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLMapElement,
|
||||
|
@ -110,38 +105,6 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLMapElement)
|
|||
nsGenericHTMLElement)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMapElement)
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLMapElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers)
|
||||
{
|
||||
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
|
||||
aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aDocument);
|
||||
|
||||
if (htmlDoc) {
|
||||
htmlDoc->AddImageMap(this);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLMapElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
{
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(GetCurrentDoc());
|
||||
|
||||
if (htmlDoc) {
|
||||
htmlDoc->RemoveImageMap(this);
|
||||
}
|
||||
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
}
|
||||
|
||||
NS_IMPL_ELEMENT_CLONE(nsHTMLMapElement)
|
||||
|
||||
|
||||
|
|
|
@ -1835,6 +1835,10 @@ nsTextEditorState::ValueWasChanged(PRBool aNotify)
|
|||
void
|
||||
nsTextEditorState::UpdatePlaceholderText(PRBool aNotify)
|
||||
{
|
||||
// If we don't have a placeholder div, there's nothing to do.
|
||||
if (!mPlaceholderDiv)
|
||||
return;
|
||||
|
||||
nsAutoString placeholderValue;
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
|
||||
|
|
|
@ -179,8 +179,9 @@ _TEST_FILES = \
|
|||
test_bug546995-5.html \
|
||||
file_bug546995.html \
|
||||
test_bug377624.html \
|
||||
test_bug562932.html \
|
||||
test_bug551846.html \
|
||||
test_bug562932.html \
|
||||
test_bug564001.html \
|
||||
test_bug566046.html \
|
||||
test_bug567938-1.html \
|
||||
test_bug567938-2.html \
|
||||
|
|
|
@ -80,6 +80,13 @@ var focusableElements = [
|
|||
"<iframe src=\"about:blank\" tabindex=\"1\"></iframe>",
|
||||
"<iframe src=\"about:blank\" contenteditable=\"true\"></iframe>",
|
||||
|
||||
"<iframe></iframe>",
|
||||
"<iframe tabindex=\"-1\"></iframe>",
|
||||
"<iframe tabindex=\"0\"></iframe>",
|
||||
"<iframe tabindex=\"0\" disabled></iframe>",
|
||||
"<iframe tabindex=\"1\"></iframe>",
|
||||
"<iframe disabled></iframe>",
|
||||
|
||||
"<img tabindex=\"-1\">",
|
||||
"<img tabindex=\"0\">",
|
||||
"<img tabindex=\"0\" disabled>",
|
||||
|
@ -179,13 +186,6 @@ var nonFocusableElements = [
|
|||
"<div tabindex=\"0\" disabled></div>",
|
||||
"<div disabled></div>",
|
||||
|
||||
"<iframe></iframe>",
|
||||
"<iframe tabindex=\"-1\"></iframe>",
|
||||
"<iframe tabindex=\"0\"></iframe>",
|
||||
"<iframe tabindex=\"0\" disabled></iframe>",
|
||||
"<iframe tabindex=\"1\"></iframe>",
|
||||
"<iframe disabled></iframe>",
|
||||
|
||||
"<img>",
|
||||
"<img disabled>",
|
||||
"<img contenteditable=\"true\">",
|
||||
|
@ -280,12 +280,19 @@ var focusableInContentEditable = [
|
|||
"<embed contenteditable=\"true\">",
|
||||
|
||||
"<iframe src=\"about:blank\"></iframe>",
|
||||
"<iframe></iframe>",
|
||||
"<iframe src=\"about:blank\" disabled></iframe>",
|
||||
"<iframe disabled></iframe>",
|
||||
"<iframe src=\"about:blank\" tabindex=\"-1\"></iframe>",
|
||||
"<iframe tabindex=\"-1\"></iframe>",
|
||||
"<iframe src=\"about:blank\" tabindex=\"0\"></iframe>",
|
||||
"<iframe tabindex=\"0\"></iframe>",
|
||||
"<iframe src=\"about:blank\" tabindex=\"0\" disabled></iframe>",
|
||||
"<iframe tabindex=\"0\" disabled></iframe>",
|
||||
"<iframe src=\"about:blank\" tabindex=\"1\"></iframe>",
|
||||
"<iframe tabindex=\"1\"></iframe>",
|
||||
"<iframe src=\"about:blank\" contenteditable=\"true\"></iframe>",
|
||||
"<iframe contenteditable=\"true\"></iframe>",
|
||||
|
||||
"<img tabindex=\"-1\">",
|
||||
"<img tabindex=\"0\">",
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=564001
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 564001</title>
|
||||
<script src="/MochiKit/packed.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=564001">Mozilla Bug 564001</a>
|
||||
<p id="display"><img usemap=#map src=image.png></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script>
|
||||
/** Test for Bug 564001 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var wrongArea = document.createElement("area");
|
||||
wrongArea.shape = "default";
|
||||
wrongArea.href = "#FAIL";
|
||||
var wrongMap = document.createElement("map");
|
||||
wrongMap.name = "map";
|
||||
wrongMap.appendChild(wrongArea);
|
||||
document.body.appendChild(wrongMap);
|
||||
|
||||
var rightArea = document.createElement("area");
|
||||
rightArea.shape = "default";
|
||||
rightArea.href = "#PASS";
|
||||
var rightMap = document.createElement("map");
|
||||
rightMap.name = "map";
|
||||
rightMap.appendChild(rightArea);
|
||||
document.body.insertBefore(rightMap, wrongMap);
|
||||
|
||||
var images = document.getElementsByTagName("img");
|
||||
onhashchange = function() {
|
||||
is(location.hash, "#PASS", "Should get the first map in tree order.");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
SimpleTest.waitForFocus(function() synthesizeMouse(images[0], 50, 50, {}));
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -243,7 +243,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLDocument)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
|
||||
NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
|
||||
"Shouldn't traverse nsHTMLDocument!");
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mImageMaps)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mImages)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplets)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEmbeds)
|
||||
|
@ -252,13 +251,14 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mForms, nsIDOMNodeList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mFormControls,
|
||||
nsIDOMNodeList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mImageMaps,
|
||||
nsIDOMNodeList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mWyciwygChannel)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMidasCommandManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFragmentParser)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mImageMaps)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mImages)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplets)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEmbeds)
|
||||
|
@ -266,6 +266,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAnchors)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mForms)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFormControls)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mImageMaps)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mWyciwygChannel)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMidasCommandManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFragmentParser)
|
||||
|
@ -330,7 +331,6 @@ nsHTMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
|
|||
mLinks = nsnull;
|
||||
mAnchors = nsnull;
|
||||
|
||||
mImageMaps.Clear();
|
||||
mForms = nsnull;
|
||||
|
||||
NS_ASSERTION(!mWyciwygChannel,
|
||||
|
@ -1157,39 +1157,20 @@ nsHTMLDocument::SetTitle(const nsAString& aTitle)
|
|||
return nsDocument::SetTitle(aTitle);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLDocument::AddImageMap(nsIDOMHTMLMapElement* aMap)
|
||||
{
|
||||
// XXX We should order the maps based on their order in the document.
|
||||
// XXX Otherwise scripts that add/remove maps with duplicate names
|
||||
// XXX will cause problems
|
||||
NS_PRECONDITION(nsnull != aMap, "null ptr");
|
||||
if (nsnull == aMap) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (mImageMaps.AppendObject(aMap)) {
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLDocument::RemoveImageMap(nsIDOMHTMLMapElement* aMap)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aMap, "null ptr");
|
||||
mImageMaps.RemoveObject(aMap);
|
||||
}
|
||||
|
||||
nsIDOMHTMLMapElement *
|
||||
nsHTMLDocument::GetImageMap(const nsAString& aMapName)
|
||||
{
|
||||
nsAutoString name;
|
||||
PRUint32 i, n = mImageMaps.Count();
|
||||
nsIDOMHTMLMapElement *firstMatch = nsnull;
|
||||
if (!mImageMaps) {
|
||||
mImageMaps = new nsContentList(this, nsGkAtoms::map, kNameSpaceID_XHTML);
|
||||
}
|
||||
NS_ASSERTION(mImageMaps, "Infallible malloc failed.");
|
||||
|
||||
nsIDOMHTMLMapElement* firstMatch = nsnull;
|
||||
nsAutoString name;
|
||||
PRUint32 i, n = mImageMaps->Length(PR_TRUE);
|
||||
for (i = 0; i < n; ++i) {
|
||||
nsIDOMHTMLMapElement *map = mImageMaps[i];
|
||||
NS_ASSERTION(map, "Null map in map list!");
|
||||
nsCOMPtr<nsIDOMHTMLMapElement> map(
|
||||
do_QueryInterface(mImageMaps->GetNodeAt(i)));
|
||||
|
||||
PRBool match;
|
||||
nsresult rv;
|
||||
|
|
|
@ -105,10 +105,6 @@ public:
|
|||
|
||||
virtual void EndLoad();
|
||||
|
||||
virtual nsresult AddImageMap(nsIDOMHTMLMapElement* aMap);
|
||||
|
||||
virtual void RemoveImageMap(nsIDOMHTMLMapElement* aMap);
|
||||
|
||||
virtual nsIDOMHTMLMapElement *GetImageMap(const nsAString& aMapName);
|
||||
|
||||
virtual void SetCompatibilityMode(nsCompatibility aMode);
|
||||
|
@ -289,8 +285,6 @@ protected:
|
|||
return kNameSpaceID_XHTML;
|
||||
}
|
||||
|
||||
nsCOMArray<nsIDOMHTMLMapElement> mImageMaps;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLCollection> mImages;
|
||||
nsCOMPtr<nsIDOMHTMLCollection> mApplets;
|
||||
nsCOMPtr<nsIDOMHTMLCollection> mEmbeds;
|
||||
|
@ -298,6 +292,7 @@ protected:
|
|||
nsCOMPtr<nsIDOMHTMLCollection> mAnchors;
|
||||
nsRefPtr<nsContentList> mForms;
|
||||
nsRefPtr<nsContentList> mFormControls;
|
||||
nsRefPtr<nsContentList> mImageMaps;
|
||||
|
||||
/** # of forms in the document, synchronously set */
|
||||
PRInt32 mNumForms;
|
||||
|
|
|
@ -54,8 +54,8 @@ class nsIScriptElement;
|
|||
class nsIEditor;
|
||||
|
||||
#define NS_IHTMLDOCUMENT_IID \
|
||||
{ 0x1e1dc0fa, 0xf13e, 0x4abd, \
|
||||
{ 0xa0, 0x95, 0x92, 0xa6, 0x7a, 0x31, 0x3c, 0x50 } }
|
||||
{ 0x840cacc9, 0x1956, 0x4987, \
|
||||
{ 0x80, 0x6e, 0xc6, 0xab, 0x19, 0x1b, 0x92, 0xd2 } }
|
||||
|
||||
|
||||
/**
|
||||
|
@ -66,12 +66,8 @@ class nsIHTMLDocument : public nsISupports
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTMLDOCUMENT_IID)
|
||||
|
||||
virtual nsresult AddImageMap(nsIDOMHTMLMapElement* aMap) = 0;
|
||||
|
||||
virtual nsIDOMHTMLMapElement *GetImageMap(const nsAString& aMapName) = 0;
|
||||
|
||||
virtual void RemoveImageMap(nsIDOMHTMLMapElement* aMap) = 0;
|
||||
|
||||
/**
|
||||
* Set compatibility mode for this document
|
||||
*/
|
||||
|
|
|
@ -41,6 +41,28 @@
|
|||
NS_IMPL_ADDREF(nsXMLBindingSet)
|
||||
NS_IMPL_RELEASE(nsXMLBindingSet)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLBindingSet)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXMLBindingSet)
|
||||
nsXMLBinding* binding = tmp->mFirst;
|
||||
while (binding) {
|
||||
binding->mExpr = nsnull;
|
||||
binding = binding->mNext;
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsXMLBindingSet)
|
||||
nsXMLBinding* binding = tmp->mFirst;
|
||||
while (binding) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "nsXMLBinding::mExpr");
|
||||
cb.NoteXPCOMChild(binding->mExpr);
|
||||
binding = binding->mNext;
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsXMLBindingSet, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsXMLBindingSet, Release)
|
||||
|
||||
nsresult
|
||||
nsXMLBindingSet::AddBinding(nsIAtom* aVar, nsIDOMXPathExpression* aExpr)
|
||||
{
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
class nsXULTemplateResultXML;
|
||||
class nsXMLBindingValues;
|
||||
|
@ -88,6 +89,7 @@ public:
|
|||
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||
NS_IMETHOD_(nsrefcnt) Release();
|
||||
NS_DECL_OWNINGTHREAD
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXMLBindingSet)
|
||||
|
||||
/**
|
||||
* Add a binding to the set
|
||||
|
|
|
@ -145,7 +145,7 @@ nsXULTemplateBuilder::nsXULTemplateBuilder(void)
|
|||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DestroyMatchList(nsISupports* aKey, nsTemplateMatch* aMatch, void* aContext)
|
||||
DestroyMatchList(nsISupports* aKey, nsTemplateMatch*& aMatch, void* aContext)
|
||||
{
|
||||
nsFixedSizeAllocator* pool = static_cast<nsFixedSizeAllocator *>(aContext);
|
||||
|
||||
|
@ -156,7 +156,7 @@ DestroyMatchList(nsISupports* aKey, nsTemplateMatch* aMatch, void* aContext)
|
|||
aMatch = next;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
nsXULTemplateBuilder::~nsXULTemplateBuilder(void)
|
||||
|
@ -235,8 +235,7 @@ nsXULTemplateBuilder::Uninit(PRBool aIsFinal)
|
|||
|
||||
mQuerySets.Clear();
|
||||
|
||||
mMatchMap.EnumerateRead(DestroyMatchList, &mPool);
|
||||
mMatchMap.Clear();
|
||||
mMatchMap.Enumerate(DestroyMatchList, &mPool);
|
||||
|
||||
mRootResult = nsnull;
|
||||
mRefVariable = nsnull;
|
||||
|
@ -267,6 +266,13 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateBuilder)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDataSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDB)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCompDB)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRoot)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRootResult)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mListeners)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mQueryProcessor)
|
||||
if (tmp->mMatchMap.IsInitialized()) {
|
||||
tmp->mMatchMap.Enumerate(DestroyMatchList, &(tmp->mPool));
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateBuilder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDataSource)
|
||||
|
|
|
@ -109,12 +109,34 @@ nsXULTemplateResultSetXML::GetNext(nsISupports **aResult)
|
|||
// nsXULTemplateQueryProcessorXML
|
||||
//
|
||||
|
||||
static PLDHashOperator
|
||||
TraverseRuleToBindingsMap(nsISupports* aKey, nsXMLBindingSet* aMatch, void* aContext)
|
||||
{
|
||||
nsCycleCollectionTraversalCallback *cb =
|
||||
static_cast<nsCycleCollectionTraversalCallback*>(aContext);
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap key");
|
||||
cb->NoteXPCOMChild(aKey);
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap value");
|
||||
cb->NoteNativeChild(aMatch, &NS_CYCLE_COLLECTION_NAME(nsXMLBindingSet));
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML)
|
||||
if (tmp->mRuleToBindingsMap.IsInitialized()) {
|
||||
tmp->mRuleToBindingsMap.Clear();
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRoot)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEvaluator)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTemplateBuilder)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateQueryProcessorXML)
|
||||
if (tmp->mRuleToBindingsMap.IsInitialized()) {
|
||||
tmp->mRuleToBindingsMap.EnumerateRead(TraverseRuleToBindingsMap, &cb);
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEvaluator)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTemplateBuilder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
|
|
@ -107,7 +107,6 @@ var oldtreefirstrow, oldtreecfirstrow;
|
|||
|
||||
function nextDataSource()
|
||||
{
|
||||
document.documentElement.getBoundingClientRect();
|
||||
var tree = document.getElementById('t');
|
||||
var treec = document.getElementById('tc');
|
||||
tree.treeBoxObject.scrollToRow(10);
|
||||
|
|
|
@ -120,6 +120,7 @@
|
|||
"<body>test1</body></html>";
|
||||
|
||||
gExpected = [{type: "pagehide", persisted: true},
|
||||
|
||||
{type: "load", title: "test1"},
|
||||
{type: "pageshow", title: "test1", persisted: false}];
|
||||
gBrowser.loadURI(test1Doc);
|
||||
|
|
|
@ -240,7 +240,7 @@ function pageEventListener(event) {
|
|||
try {
|
||||
dump("TEST: eventListener received a " + event.type + " event for page " +
|
||||
event.originalTarget.title + ", persisted=" + event.persisted + "\n");
|
||||
}catch(e) {
|
||||
} catch(e) {
|
||||
// Ignore any exception.
|
||||
}
|
||||
|
||||
|
@ -293,8 +293,8 @@ function pageEventListener(event) {
|
|||
|
||||
if (typeof(expected.persisted) != "undefined") {
|
||||
is(event.persisted, expected.persisted,
|
||||
"The persisted property of the " + event.type + "event on page " +
|
||||
event.originalTarget.title + " had an unexpected value");
|
||||
"The persisted property of the " + event.type + " event on page " +
|
||||
event.originalTarget.location + " had an unexpected value");
|
||||
}
|
||||
|
||||
// If we're out of expected events, let doPageNavigation() return.
|
||||
|
|
|
@ -43,11 +43,13 @@ function runNextTest() {
|
|||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
utils.sendNativeKeyEvent(0, 13 /* w */, 0x4000 /* cmd */, "w", "w");
|
||||
|
||||
ok(didClose, "Cmd+W should have closed the tab");
|
||||
if (!didClose) {
|
||||
win.close();
|
||||
}
|
||||
SimpleTest.finish();
|
||||
setTimeout(function () {
|
||||
ok(didClose, "Cmd+W should have closed the tab");
|
||||
if (!didClose) {
|
||||
win.close();
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
|
@ -631,12 +631,11 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
// to JS.
|
||||
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(Window, nsWindowSH,
|
||||
NS_DEFINE_CLASSINFO_DATA(Window, nsOuterWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
// XXX Wrong helper!
|
||||
NS_DEFINE_CLASSINFO_DATA(InnerWindow, nsWindowSH,
|
||||
NS_DEFINE_CLASSINFO_DATA(InnerWindow, nsInnerWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
|
@ -927,12 +926,11 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
// DOM Chrome Window class.
|
||||
NS_DEFINE_CLASSINFO_DATA(ChromeWindow, nsWindowSH,
|
||||
NS_DEFINE_CLASSINFO_DATA(ChromeWindow, nsOuterWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
// XXX Wrong helper!
|
||||
NS_DEFINE_CLASSINFO_DATA(InnerChromeWindow, nsWindowSH,
|
||||
NS_DEFINE_CLASSINFO_DATA(InnerChromeWindow, nsInnerWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
|
@ -1315,12 +1313,11 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
NS_DEFINE_CLASSINFO_DATA(FileReader, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH,
|
||||
NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsOuterWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
// XXX Wrong helper!
|
||||
NS_DEFINE_CLASSINFO_DATA(InnerModalContentWindow, nsWindowSH,
|
||||
NS_DEFINE_CLASSINFO_DATA(InnerModalContentWindow, nsInnerWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
|
@ -4827,8 +4824,8 @@ nsDOMClassInfo::ShutDown()
|
|||
// Window helper
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj)
|
||||
nsCommonWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj)
|
||||
{
|
||||
// Normally ::PreCreate() is used to give XPConnect the parent
|
||||
// object for the object that's being wrapped, this parent object is
|
||||
|
@ -4847,6 +4844,10 @@ nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
|||
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromSupports(nativeObj);
|
||||
|
||||
if (win->IsOuterWindow()) {
|
||||
win->EnsureInnerWindow();
|
||||
}
|
||||
|
||||
if (sgo) {
|
||||
*parentObj = sgo->GetGlobalJSObject();
|
||||
|
||||
|
@ -4870,18 +4871,21 @@ nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
|||
static JSClass sGlobalScopePolluterClass = {
|
||||
"Global Scope Polluter",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_NEW_RESOLVE,
|
||||
nsWindowSH::SecurityCheckOnSetProp, nsWindowSH::SecurityCheckOnSetProp,
|
||||
nsWindowSH::GlobalScopePolluterGetProperty,
|
||||
nsWindowSH::SecurityCheckOnSetProp, JS_EnumerateStub,
|
||||
(JSResolveOp)nsWindowSH::GlobalScopePolluterNewResolve, JS_ConvertStub,
|
||||
nsCommonWindowSH::SecurityCheckOnSetProp,
|
||||
nsCommonWindowSH::SecurityCheckOnSetProp,
|
||||
nsCommonWindowSH::GlobalScopePolluterGetProperty,
|
||||
nsCommonWindowSH::SecurityCheckOnSetProp,
|
||||
JS_EnumerateStub,
|
||||
(JSResolveOp)nsCommonWindowSH::GlobalScopePolluterNewResolve,
|
||||
JS_ConvertStub,
|
||||
nsHTMLDocumentSH::ReleaseDocument
|
||||
};
|
||||
|
||||
|
||||
// static
|
||||
JSBool
|
||||
nsWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSObject *obj,
|
||||
jsid id, jsval *vp)
|
||||
nsCommonWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSObject *obj,
|
||||
jsid id, jsval *vp)
|
||||
{
|
||||
// Someone is accessing a element by referencing its name/id in the
|
||||
// global scope, do a security check to make sure that's ok.
|
||||
|
@ -4907,8 +4911,8 @@ nsWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSObject *obj,
|
|||
|
||||
// static
|
||||
JSBool
|
||||
nsWindowSH::SecurityCheckOnSetProp(JSContext *cx, JSObject *obj, jsid id,
|
||||
jsval *vp)
|
||||
nsCommonWindowSH::SecurityCheckOnSetProp(JSContext *cx, JSObject *obj, jsid id,
|
||||
jsval *vp)
|
||||
{
|
||||
// Someone is accessing a element by referencing its name/id in the
|
||||
// global scope, do a security check to make sure that's ok.
|
||||
|
@ -4932,8 +4936,8 @@ GetDocument(JSContext *cx, JSObject *obj)
|
|||
|
||||
// static
|
||||
JSBool
|
||||
nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
|
||||
jsid id, uintN flags,
|
||||
nsCommonWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
|
||||
jsid id, uintN flags,
|
||||
JSObject **objp)
|
||||
{
|
||||
if (flags & (JSRESOLVE_ASSIGNING | JSRESOLVE_DECLARING |
|
||||
|
@ -5002,7 +5006,7 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
|
|||
|
||||
// static
|
||||
void
|
||||
nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
|
||||
nsCommonWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *proto;
|
||||
|
||||
|
@ -5029,8 +5033,8 @@ nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
|
|||
|
||||
// static
|
||||
nsresult
|
||||
nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
|
||||
nsIHTMLDocument *doc)
|
||||
nsCommonWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
|
||||
nsIHTMLDocument *doc)
|
||||
{
|
||||
// If global scope pollution is disabled, or if our document is not
|
||||
// a HTML document, do nothing
|
||||
|
@ -5097,8 +5101,8 @@ GetChildFrame(nsGlobalWindow *win, jsid id)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
|
||||
nsCommonWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
|
||||
{
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
|
||||
|
@ -5171,6 +5175,9 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
// check and return.
|
||||
|
||||
nsGlobalWindow *frameWin = (nsGlobalWindow *)frame.get();
|
||||
NS_ASSERTION(frameWin->IsOuterWindow(), "GetChildFrame gave us an inner?");
|
||||
|
||||
frameWin->EnsureInnerWindow();
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = WrapNative(cx, frameWin->GetGlobalJSObject(), frame,
|
||||
|
@ -5195,7 +5202,7 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
if (JSID_IS_STRING(id) && !JSVAL_IS_PRIMITIVE(*vp) &&
|
||||
::JS_TypeOfValue(cx, *vp) != JSTYPE_FUNCTION) {
|
||||
// A named property accessed which could have been resolved to a
|
||||
// child frame in nsWindowSH::NewResolve() (*vp will tell us if
|
||||
// child frame in nsCommonWindowSH::NewResolve() (*vp will tell us if
|
||||
// that's the case). If *vp is a window object (i.e. a child
|
||||
// frame), return without doing a security check.
|
||||
//
|
||||
|
@ -5233,8 +5240,8 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
|
||||
nsCommonWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
|
||||
{
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
|
||||
|
@ -5310,9 +5317,9 @@ nsWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp,
|
||||
PRBool *_retval)
|
||||
nsCommonWindowSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp,
|
||||
PRBool *_retval)
|
||||
{
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
|
||||
|
@ -5369,9 +5376,9 @@ nsWindowSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp,
|
||||
PRBool *_retval)
|
||||
nsCommonWindowSH::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp,
|
||||
PRBool *_retval)
|
||||
{
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
|
||||
|
@ -6213,8 +6220,8 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
|
|||
|
||||
// static
|
||||
nsresult
|
||||
nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
JSObject *obj, JSString *str, PRBool *did_resolve)
|
||||
nsCommonWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
JSObject *obj, JSString *str, PRBool *did_resolve)
|
||||
{
|
||||
*did_resolve = PR_FALSE;
|
||||
|
||||
|
@ -6454,12 +6461,12 @@ ContentWindowGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsWindowSH::sResolving = PR_FALSE;
|
||||
nsCommonWindowSH::sResolving = PR_FALSE;
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval)
|
||||
nsCommonWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval)
|
||||
{
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
|
||||
|
@ -7003,9 +7010,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
return NS_OK;
|
||||
}
|
||||
}
|
||||
} else if (id == sDialogArguments_id &&
|
||||
(mData == &sClassInfoData[eDOMClassInfo_InnerModalContentWindow_id] ||
|
||||
mData == &sClassInfoData[eDOMClassInfo_ModalContentWindow_id])) {
|
||||
} else if (id == sDialogArguments_id && win->IsModalContentWindow()) {
|
||||
nsCOMPtr<nsIArray> args;
|
||||
((nsGlobalModalWindow *)win)->GetDialogArguments(getter_AddRefs(args));
|
||||
|
||||
|
@ -7092,9 +7097,9 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, PRUint32 enum_op, jsval *statep,
|
||||
jsid *idp, PRBool *_retval)
|
||||
nsCommonWindowSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, PRUint32 enum_op, jsval *statep,
|
||||
jsid *idp, PRBool *_retval)
|
||||
{
|
||||
switch ((JSIterateOp)enum_op) {
|
||||
/* FIXME bug 576449: non-enumerable property support */
|
||||
|
@ -7156,8 +7161,8 @@ nsWindowSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj)
|
||||
nsCommonWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj)
|
||||
{
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
|
||||
NS_ENSURE_TRUE(sgo, NS_ERROR_UNEXPECTED);
|
||||
|
@ -7168,8 +7173,8 @@ nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, const jsval &val, PRBool *bp)
|
||||
nsCommonWindowSH::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, const jsval &val, PRBool *bp)
|
||||
{
|
||||
*bp = PR_FALSE;
|
||||
|
||||
|
@ -7205,8 +7210,8 @@ nsWindowSH::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval)
|
||||
nsCommonWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval)
|
||||
{
|
||||
nsGlobalWindow *origWin = nsGlobalWindow::FromWrapper(wrapper);
|
||||
nsGlobalWindow *win = origWin->GetOuterWindowInternal();
|
||||
|
@ -7233,8 +7238,8 @@ nsWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval)
|
||||
nsCommonWindowSH::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval)
|
||||
{
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
|
||||
|
|
|
@ -478,14 +478,14 @@ public:
|
|||
|
||||
// Window scriptable helper
|
||||
|
||||
class nsWindowSH : public nsEventReceiverSH
|
||||
class nsCommonWindowSH : public nsEventReceiverSH
|
||||
{
|
||||
protected:
|
||||
nsWindowSH(nsDOMClassInfoData* aData) : nsEventReceiverSH(aData)
|
||||
nsCommonWindowSH(nsDOMClassInfoData *aData) : nsEventReceiverSH(aData)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~nsWindowSH()
|
||||
virtual ~nsCommonWindowSH()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -553,10 +553,41 @@ public:
|
|||
static void InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
|
||||
static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
|
||||
nsIHTMLDocument *doc);
|
||||
};
|
||||
|
||||
class nsOuterWindowSH : public nsCommonWindowSH
|
||||
{
|
||||
protected:
|
||||
nsOuterWindowSH(nsDOMClassInfoData* aData) : nsCommonWindowSH(aData)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~nsOuterWindowSH()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
return new nsWindowSH(aData);
|
||||
return new nsOuterWindowSH(aData);
|
||||
}
|
||||
};
|
||||
|
||||
class nsInnerWindowSH : public nsCommonWindowSH
|
||||
{
|
||||
protected:
|
||||
nsInnerWindowSH(nsDOMClassInfoData* aData) : nsCommonWindowSH(aData)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~nsInnerWindowSH()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
return new nsInnerWindowSH(aData);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1304,13 +1304,6 @@ nsGlobalWindow::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aScriptCont
|
|||
|
||||
aScriptContext->SetGCOnDestruction(PR_FALSE);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
|
||||
aScriptContext->CreateOuterObject(this, principal);
|
||||
aScriptContext->DidInitializeContext();
|
||||
mJSObject = (JSObject *)aScriptContext->GetNativeGlobal();
|
||||
}
|
||||
|
||||
mContext = aScriptContext;
|
||||
|
@ -1620,6 +1613,10 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
if (IsFrozen()) {
|
||||
// This outer is now getting its first inner, thaw the outer now
|
||||
// that it's ready and is getting an inner window.
|
||||
mContext->CreateOuterObject(this, aDocument->NodePrincipal());
|
||||
mContext->DidInitializeContext();
|
||||
mJSObject = (JSObject *)mContext->GetNativeGlobal();
|
||||
|
||||
Thaw();
|
||||
}
|
||||
|
||||
|
@ -1745,7 +1742,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
newInnerWindow = currentInner;
|
||||
|
||||
if (aDocument != oldDoc) {
|
||||
nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
|
||||
nsCommonWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
|
||||
}
|
||||
} else {
|
||||
if (aState) {
|
||||
|
@ -1930,8 +1927,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
|
||||
if ((!reUseInnerWindow || aDocument != oldDoc) && !aState) {
|
||||
nsCOMPtr<nsIHTMLDocument> html_doc(do_QueryInterface(mDocument));
|
||||
nsWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject,
|
||||
html_doc);
|
||||
nsCommonWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject,
|
||||
html_doc);
|
||||
}
|
||||
|
||||
// This code should not be called during shutdown any more (now that
|
||||
|
@ -2471,7 +2468,7 @@ nsGlobalWindow::DefineArgumentsProperty(nsIArray *aArguments)
|
|||
if (mIsModalContentWindow) {
|
||||
// Modal content windows don't have an "arguments" property, they
|
||||
// have a "dialogArguments" property which is handled
|
||||
// separately. See nsWindowSH::NewResolve().
|
||||
// separately. See nsCommonWindowSH::NewResolve().
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -3464,7 +3464,7 @@ nsJSContext::ClearScope(void *aGlobalObj, PRBool aClearFromProtoChain)
|
|||
// chain when we're clearing an outer window whose current inner we
|
||||
// still want.
|
||||
if (aClearFromProtoChain) {
|
||||
nsWindowSH::InvalidateGlobalScopePolluter(mContext, obj);
|
||||
nsCommonWindowSH::InvalidateGlobalScopePolluter(mContext, obj);
|
||||
|
||||
// Clear up obj's prototype chain, but not Object.prototype.
|
||||
for (JSObject *o = ::JS_GetPrototype(mContext, obj), *next;
|
||||
|
@ -3980,11 +3980,13 @@ SetMemoryHighWaterMarkPrefChangedCallback(const char* aPrefName, void* aClosure)
|
|||
PRInt32 highwatermark = nsContentUtils::GetIntPref(aPrefName, 32);
|
||||
|
||||
if (highwatermark >= 32) {
|
||||
// There are two options of memory usage in tracemonkey. One is
|
||||
// to use malloc() and the other is to use memory for GC. (E.g.
|
||||
// js_NewGCThing()/RefillDoubleFreeList()).
|
||||
// Let's limit the high water mark for the first one to 32MB,
|
||||
// and second one to 0xffffffff.
|
||||
/*
|
||||
* There are two ways to allocate memory in SpiderMonkey. One is
|
||||
* to use jsmalloc() and the other is to use GC-owned memory
|
||||
* (e.g. js_NewGCThing()).
|
||||
*
|
||||
* In the browser, we don't cap the amount of GC-owned memory.
|
||||
*/
|
||||
JS_SetGCParameter(nsJSRuntime::sRuntime, JSGC_MAX_MALLOC_BYTES,
|
||||
64L * 1024L * 1024L);
|
||||
JS_SetGCParameter(nsJSRuntime::sRuntime, JSGC_MAX_BYTES,
|
||||
|
|
|
@ -404,7 +404,7 @@ nsLocation::GetHost(nsAString& aHost)
|
|||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -443,7 +443,7 @@ nsLocation::GetHostname(nsAString& aHostname)
|
|||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -397,11 +397,6 @@ public:
|
|||
virtual PRBool CanClose() = 0;
|
||||
virtual nsresult ForceClose() = 0;
|
||||
|
||||
void SetModalContentWindow(PRBool aIsModalContentWindow)
|
||||
{
|
||||
mIsModalContentWindow = aIsModalContentWindow;
|
||||
}
|
||||
|
||||
PRBool IsModalContentWindow() const
|
||||
{
|
||||
return mIsModalContentWindow;
|
||||
|
|
|
@ -288,7 +288,7 @@ nsScriptNameSpaceManager::FillHash(nsICategoryManager *aCategoryManager,
|
|||
// count), once such an interface is found the "nsIDOM" prefix is cut
|
||||
// off the name and the rest of the name is added into the hash for
|
||||
// global names. This makes things like 'Node.ELEMENT_NODE' work in
|
||||
// JS. See nsWindowSH::GlobalResolve() for detais on how this is used.
|
||||
// JS. See nsCommonWindowSH::GlobalResolve() for detais on how this is used.
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::FillHashWithDOMInterfaces()
|
||||
|
|
|
@ -128,7 +128,7 @@ interface nsIWebGLUniformLocation : nsISupports
|
|||
};
|
||||
|
||||
|
||||
[scriptable, uuid(f02c85e0-8305-11de-abe2-000c29206271)]
|
||||
[scriptable, uuid(2f21ca21-9720-4eee-ad94-27eefe4f72dc)]
|
||||
interface nsICanvasRenderingContextWebGL : nsISupports
|
||||
{
|
||||
//
|
||||
|
@ -725,8 +725,6 @@ interface nsICanvasRenderingContextWebGL : nsISupports
|
|||
in WebGLenum format, in WebGLenum type, in WebGLArrayPtr pixels);
|
||||
[noscript] void readPixels_buf(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height,
|
||||
in WebGLenum format, in WebGLenum type, in WebGLArrayBufferPtr pixels);
|
||||
[noscript] WebGLsizei readPixels_byteLength_old_API_deprecated(
|
||||
in WebGLsizei width, in WebGLsizei height, in WebGLenum format, in WebGLenum type);
|
||||
|
||||
//void glReleaseShaderCompiler();
|
||||
|
||||
|
@ -754,9 +752,6 @@ interface nsICanvasRenderingContextWebGL : nsISupports
|
|||
// HTMLImageElement, HTMLCanvasElement, HTMLVideoElement
|
||||
[noscript] void texImage2D_dom(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
|
||||
in WebGLenum format, in WebGLenum type, in nsIDOMElement element);
|
||||
// XXX the old API. Eventually drop that.
|
||||
[noscript] void TexImage2D_dom_old_API_deprecated(in WebGLenum target, in WebGLint level,
|
||||
in nsIDOMElement element, in PRBool flipY, in PRBool premultiplyAlpha);
|
||||
|
||||
void texSubImage2D([optional] in long dummy);
|
||||
[noscript] void texSubImage2D_buf(in WebGLenum target, in WebGLint level,
|
||||
|
|
|
@ -116,6 +116,7 @@ _TEST_FILES = \
|
|||
test_bug563487.html \
|
||||
test_bug545314.html \
|
||||
test_bug548828.html \
|
||||
test_bug562433.html \
|
||||
test_DOMWindowCreated_chromeonly.html \
|
||||
test_bug581072.html \
|
||||
test_bug583225.html \
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=562433
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 562433</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562433">Mozilla Bug 562433</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 562433 **/
|
||||
|
||||
var w = window.open("");
|
||||
|
||||
// The new window's location.host and location.hostname must be the empty
|
||||
// string (instead of throwing an exception)
|
||||
|
||||
is(w.location.host, "", 'w.location.host should be ""');
|
||||
is(w.location.hostname, "", 'w.location.hostname should be ""');
|
||||
|
||||
w.close();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsIClipboard.h"
|
||||
|
||||
#include "nsEditorCommands.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
|
||||
#define STATE_ENABLED "state_enabled"
|
||||
|
@ -669,7 +670,6 @@ nsSelectionMoveCommands::IsCommandEnabled(const char * aCommandName,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelectionMoveCommands::DoCommand(const char *aCommandName,
|
||||
nsISupports *aCommandRefCon)
|
||||
|
@ -677,6 +677,15 @@ nsSelectionMoveCommands::DoCommand(const char *aCommandName,
|
|||
nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
|
||||
NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
editor->GetDocument(getter_AddRefs(domDoc));
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
||||
if (doc) {
|
||||
// Most of the commands below (possibly all of them) need layout to
|
||||
// be up to date.
|
||||
doc->FlushPendingNotifications(Flush_Layout);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISelectionController> selCont;
|
||||
nsresult rv = editor->GetSelectionController(getter_AddRefs(selCont));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -223,8 +223,6 @@ nsTransactionItem::UndoTransaction(nsTransactionManager *aTxMgr)
|
|||
return result;
|
||||
}
|
||||
|
||||
// FIXME: bug 583493
|
||||
// NS_ENSURE_TRUE(mTransaction, NS_OK);
|
||||
if (!mTransaction)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -451,7 +449,8 @@ nsTransactionItem::RecoverFromRedoError(nsTransactionManager *aTxMgr)
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(mTransaction, NS_OK);
|
||||
if (!mTransaction)
|
||||
return NS_OK;
|
||||
|
||||
return mTransaction->UndoTransaction();
|
||||
}
|
||||
|
|
|
@ -172,6 +172,13 @@ public:
|
|||
*/
|
||||
virtual gfxIntSize GetCurrentSize() = 0;
|
||||
|
||||
/**
|
||||
* Set a new layer manager for this image container. It must be
|
||||
* either of the same type as the container's current layer manager,
|
||||
* or null. TRUE is returned on success.
|
||||
*/
|
||||
virtual PRBool SetLayerManager(LayerManager *aManager) = 0;
|
||||
|
||||
protected:
|
||||
LayerManager* mManager;
|
||||
|
||||
|
|
|
@ -142,12 +142,21 @@ public:
|
|||
LAYERS_D3D9
|
||||
};
|
||||
|
||||
LayerManager() : mUserData(nsnull)
|
||||
LayerManager() : mUserData(nsnull), mDestroyed(PR_FALSE)
|
||||
{
|
||||
InitLog();
|
||||
}
|
||||
virtual ~LayerManager() {}
|
||||
|
||||
/**
|
||||
* Release layers and resources held by this layer manager, and mark
|
||||
* it as destroyed. Should do any cleanup necessary in preparation
|
||||
* for its widget going away. After this call, only user data calls
|
||||
* are valid on the layer manager.
|
||||
*/
|
||||
virtual void Destroy() { mDestroyed = PR_TRUE; }
|
||||
PRBool IsDestroyed() { return mDestroyed; }
|
||||
|
||||
/**
|
||||
* Start a new transaction. Nested transactions are not allowed so
|
||||
* there must be no transaction currently in progress.
|
||||
|
@ -297,6 +306,7 @@ public:
|
|||
protected:
|
||||
nsRefPtr<Layer> mRoot;
|
||||
void* mUserData;
|
||||
PRPackedBool mDestroyed;
|
||||
|
||||
// Print interesting information about this into aTo. Internally
|
||||
// used to implement Dump*() and Log*().
|
||||
|
@ -328,7 +338,9 @@ public:
|
|||
virtual ~Layer() {}
|
||||
|
||||
/**
|
||||
* Returns the LayoutManager this Layer belongs to. Cannot be null.
|
||||
* Returns the LayerManager this Layer belongs to. Note that the layer
|
||||
* manager might be in a destroyed state, at which point it's only
|
||||
* valid to set/get user data from it.
|
||||
*/
|
||||
LayerManager* Manager() { return mManager; }
|
||||
|
||||
|
@ -387,6 +399,7 @@ public:
|
|||
}
|
||||
Mutated();
|
||||
}
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* Set a clip rect which will be applied to this layer as it is
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -226,6 +226,7 @@ public:
|
|||
virtual already_AddRefed<Image> GetCurrentImage();
|
||||
virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
|
||||
virtual gfxIntSize GetCurrentSize();
|
||||
virtual PRBool SetLayerManager(LayerManager *aManager);
|
||||
|
||||
protected:
|
||||
Monitor mMonitor;
|
||||
|
@ -302,6 +303,20 @@ BasicImageContainer::GetCurrentSize()
|
|||
return !mImage ? gfxIntSize(0,0) : ToImageData(mImage)->GetSize();
|
||||
}
|
||||
|
||||
PRBool
|
||||
BasicImageContainer::SetLayerManager(LayerManager *aManager)
|
||||
{
|
||||
if (aManager &&
|
||||
aManager->GetBackendType() != LayerManager::LAYERS_BASIC)
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// for basic layers, we can just swap; no magic needed.
|
||||
mManager = aManager;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
already_AddRefed<ImageContainer>
|
||||
BasicLayerManager::CreateImageContainer()
|
||||
{
|
||||
|
|
|
@ -701,15 +701,9 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect)
|
|||
// For simplicity, we read the entire framebuffer for now -- in
|
||||
// the future we should use mUpdatedRect, though with WebGL we don't
|
||||
// have an easy way to generate one.
|
||||
if (mGLContext->IsGLES2()) {
|
||||
mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
|
||||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
|
||||
isurf->Data());
|
||||
} else {
|
||||
mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
|
||||
LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
isurf->Data());
|
||||
}
|
||||
mGLContext->ReadPixelsIntoImageSurface(0, 0,
|
||||
mBounds.width, mBounds.height,
|
||||
isurf);
|
||||
|
||||
// Put back the previous framebuffer binding.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
|
|
|
@ -111,9 +111,15 @@ CanvasLayerD3D9::Updated(const nsIntRect& aRect)
|
|||
// For simplicity, we read the entire framebuffer for now -- in
|
||||
// the future we should use aRect, though with WebGL we don't
|
||||
// have an easy way to generate one.
|
||||
mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
|
||||
LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
destination);
|
||||
nsRefPtr<gfxImageSurface> tmpSurface =
|
||||
new gfxImageSurface(destination,
|
||||
gfxIntSize(mBounds.width, mBounds.height),
|
||||
mBounds.width * 4,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
mGLContext->ReadPixelsIntoImageSurface(0, 0,
|
||||
mBounds.width, mBounds.height,
|
||||
tmpSurface);
|
||||
tmpSurface = nsnull;
|
||||
|
||||
// Put back the previous framebuffer binding.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -130,6 +130,13 @@ ImageContainerD3D9::GetCurrentSize()
|
|||
return gfxIntSize(0,0);
|
||||
}
|
||||
|
||||
PRBool
|
||||
ImageContainerD3D9::SetLayerManager(LayerManager *aManager)
|
||||
{
|
||||
// we can't do anything here for now
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
Layer*
|
||||
ImageLayerD3D9::GetLayer()
|
||||
{
|
||||
|
|
|
@ -62,6 +62,8 @@ public:
|
|||
|
||||
virtual gfxIntSize GetCurrentSize();
|
||||
|
||||
virtual PRBool SetLayerManager(LayerManager *aManager);
|
||||
|
||||
private:
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
|
|
|
@ -54,12 +54,17 @@ using namespace mozilla;
|
|||
using namespace mozilla::layers;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
CanvasLayerOGL::~CanvasLayerOGL()
|
||||
void
|
||||
CanvasLayerOGL::Destroy()
|
||||
{
|
||||
mOGLManager->MakeCurrent();
|
||||
if (!mDestroyed) {
|
||||
if (mTexture) {
|
||||
GLContext *cx = mOGLManager->glForResources();
|
||||
cx->MakeCurrent();
|
||||
cx->fDeleteTextures(1, &mTexture);
|
||||
}
|
||||
|
||||
if (mTexture) {
|
||||
gl()->fDeleteTextures(1, &mTexture);
|
||||
mDestroyed = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,6 +121,10 @@ CanvasLayerOGL::MakeTexture()
|
|||
void
|
||||
CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
||||
{
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mUpdatedRect.IsEmpty(),
|
||||
"CanvasLayer::Updated called more than once during a transaction!");
|
||||
|
||||
|
@ -123,13 +132,15 @@ CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
|||
|
||||
mUpdatedRect.UnionRect(mUpdatedRect, aRect);
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
if (mCanvasGLContext &&
|
||||
mCanvasGLContext->GetContextType() == gl()->GetContextType())
|
||||
{
|
||||
if (gl()->BindOffscreenNeedsTexture(mCanvasGLContext) &&
|
||||
mTexture == 0)
|
||||
{
|
||||
MakeTexture();
|
||||
}
|
||||
} else if (mCanvasSurface) {
|
||||
} else {
|
||||
PRBool newTexture = mTexture == 0;
|
||||
if (newTexture) {
|
||||
MakeTexture();
|
||||
|
@ -140,40 +151,50 @@ CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
|||
}
|
||||
|
||||
nsRefPtr<gfxImageSurface> updatedAreaImageSurface;
|
||||
nsRefPtr<gfxASurface> sourceSurface = mCanvasSurface;
|
||||
if (mCanvasSurface) {
|
||||
nsRefPtr<gfxASurface> sourceSurface = mCanvasSurface;
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (sourceSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
|
||||
sourceSurface = static_cast<gfxWindowsSurface*>(sourceSurface.get())->GetImageSurface();
|
||||
if (!sourceSurface)
|
||||
sourceSurface = mCanvasSurface;
|
||||
}
|
||||
if (sourceSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
|
||||
sourceSurface = static_cast<gfxWindowsSurface*>(sourceSurface.get())->GetImageSurface();
|
||||
if (!sourceSurface)
|
||||
sourceSurface = mCanvasSurface;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// XXX don't copy, blah.
|
||||
// but need to deal with stride on the gl side; do this later.
|
||||
if (mCanvasSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
gfxImageSurface *s = static_cast<gfxImageSurface*>(mCanvasSurface.get());
|
||||
if (s->Format() == gfxASurface::ImageFormatARGB32 ||
|
||||
s->Format() == gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
updatedAreaImageSurface = ...;
|
||||
} else {
|
||||
NS_WARNING("surface with format that we can't handle");
|
||||
return;
|
||||
}
|
||||
} else
|
||||
// XXX don't copy, blah.
|
||||
// but need to deal with stride on the gl side; do this later.
|
||||
if (mCanvasSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
gfxImageSurface *s = static_cast<gfxImageSurface*>(mCanvasSurface.get());
|
||||
if (s->Format() == gfxASurface::ImageFormatARGB32 ||
|
||||
s->Format() == gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
updatedAreaImageSurface = ...;
|
||||
} else {
|
||||
NS_WARNING("surface with format that we can't handle");
|
||||
return;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
{
|
||||
updatedAreaImageSurface =
|
||||
new gfxImageSurface(gfxIntSize(mUpdatedRect.width, mUpdatedRect.height),
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(updatedAreaImageSurface);
|
||||
ctx->Translate(gfxPoint(-mUpdatedRect.x, -mUpdatedRect.y));
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(sourceSurface);
|
||||
ctx->Paint();
|
||||
}
|
||||
} else if (mCanvasGLContext) {
|
||||
updatedAreaImageSurface =
|
||||
new gfxImageSurface(gfxIntSize(mUpdatedRect.width, mUpdatedRect.height),
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(updatedAreaImageSurface);
|
||||
ctx->Translate(gfxPoint(-mUpdatedRect.x, -mUpdatedRect.y));
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(sourceSurface);
|
||||
ctx->Paint();
|
||||
mCanvasGLContext->ReadPixelsIntoImageSurface(mUpdatedRect.x, mUpdatedRect.y,
|
||||
mUpdatedRect.width,
|
||||
mUpdatedRect.height,
|
||||
updatedAreaImageSurface);
|
||||
}
|
||||
|
||||
if (newTexture) {
|
||||
|
@ -222,12 +243,12 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
|||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
}
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
bool useGLContext = mCanvasGLContext &&
|
||||
mCanvasGLContext->GetContextType() == gl()->GetContextType();
|
||||
|
||||
if (useGLContext) {
|
||||
gl()->BindTex2DOffscreen(mCanvasGLContext);
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
program = mOGLManager->GetRGBALayerProgram();
|
||||
} else {
|
||||
program = mOGLManager->GetBGRALayerProgram();
|
||||
|
@ -244,7 +265,7 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
|||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
if (useGLContext) {
|
||||
gl()->UnbindTex2DOffscreen(mCanvasGLContext);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,14 +56,14 @@ public:
|
|||
{
|
||||
mImplData = static_cast<LayerOGL*>(this);
|
||||
}
|
||||
|
||||
~CanvasLayerOGL();
|
||||
~CanvasLayerOGL() { Destroy(); }
|
||||
|
||||
// CanvasLayer implementation
|
||||
virtual void Initialize(const Data& aData);
|
||||
virtual void Updated(const nsIntRect& aRect);
|
||||
|
||||
// LayerOGL implementation
|
||||
virtual void Destroy();
|
||||
virtual Layer* GetLayer() { return this; }
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
|
|
|
@ -53,10 +53,13 @@ public:
|
|||
{
|
||||
mImplData = static_cast<LayerOGL*>(this);
|
||||
}
|
||||
~ColorLayerOGL() { Destroy(); }
|
||||
|
||||
// LayerOGL Implementation
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual void Destroy() { mDestroyed = PR_TRUE; }
|
||||
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
};
|
||||
|
|
|
@ -49,8 +49,18 @@ ContainerLayerOGL::ContainerLayerOGL(LayerManagerOGL *aManager)
|
|||
|
||||
ContainerLayerOGL::~ContainerLayerOGL()
|
||||
{
|
||||
while (mFirstChild) {
|
||||
RemoveChild(mFirstChild);
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerOGL::Destroy()
|
||||
{
|
||||
if (!mDestroyed) {
|
||||
while (mFirstChild) {
|
||||
GetFirstChildOGL()->Destroy();
|
||||
RemoveChild(mFirstChild);
|
||||
}
|
||||
mDestroyed = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -60,6 +60,8 @@ public:
|
|||
/** LayerOGL implementation */
|
||||
Layer* GetLayer();
|
||||
|
||||
void Destroy();
|
||||
|
||||
LayerOGL* GetFirstChildOGL();
|
||||
|
||||
PRBool IsEmpty();
|
||||
|
|
|
@ -57,11 +57,13 @@ public:
|
|||
GLuint aTexture)
|
||||
: mContext(aContext), mTexture(aTexture)
|
||||
{
|
||||
NS_ASSERTION(aTexture, "TextureDeleter instantiated with nothing to do");
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (mTexture) {
|
||||
mContext->DestroyTexture(mTexture);
|
||||
}
|
||||
mContext->MakeCurrent();
|
||||
mContext->fDeleteTextures(1, &mTexture);
|
||||
|
||||
// Ensure context is released on the main thread
|
||||
mContext = nsnull;
|
||||
return NS_OK;
|
||||
|
@ -74,12 +76,15 @@ public:
|
|||
void
|
||||
GLTexture::Allocate(GLContext *aContext)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Can only allocate texture on main thread");
|
||||
NS_ASSERTION(aContext->IsGlobalSharedContext() ||
|
||||
NS_IsMainThread(), "Can only allocate texture on main thread or with cx sharing");
|
||||
|
||||
Release();
|
||||
|
||||
mContext = aContext;
|
||||
mTexture = mContext->CreateTexture();
|
||||
|
||||
mContext->MakeCurrent();
|
||||
mContext->fGenTextures(1, &mTexture);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -100,19 +105,20 @@ GLTexture::Release()
|
|||
return;
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
if (mTexture) {
|
||||
mContext->DestroyTexture(mTexture);
|
||||
mTexture = 0;
|
||||
if (mTexture) {
|
||||
if (NS_IsMainThread() || mContext->IsGlobalSharedContext()) {
|
||||
mContext->MakeCurrent();
|
||||
mContext->fDeleteTextures(1, &mTexture);
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
new TextureDeleter(mContext.forget(), mTexture);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
mContext = nsnull;
|
||||
return;
|
||||
|
||||
mTexture = 0;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
new TextureDeleter(mContext.forget(), mTexture);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
mTexture = 0;
|
||||
mContext = nsnull;
|
||||
}
|
||||
|
||||
RecycleBin::RecycleBin()
|
||||
|
@ -133,7 +139,7 @@ RecycleBin::RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize)
|
|||
}
|
||||
|
||||
PRUint8*
|
||||
RecycleBin::TakeBuffer(PRUint32 aSize)
|
||||
RecycleBin::GetBuffer(PRUint32 aSize)
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
|
@ -163,8 +169,8 @@ RecycleBin::RecycleTexture(GLTexture *aTexture, TextureType aType,
|
|||
}
|
||||
|
||||
void
|
||||
RecycleBin::TakeTexture(TextureType aType, const gfxIntSize& aSize,
|
||||
GLContext *aContext, GLTexture *aOutTexture)
|
||||
RecycleBin::GetTexture(TextureType aType, const gfxIntSize& aSize,
|
||||
GLContext *aContext, GLTexture *aOutTexture)
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
|
@ -184,6 +190,15 @@ ImageContainerOGL::ImageContainerOGL(LayerManagerOGL *aManager)
|
|||
{
|
||||
}
|
||||
|
||||
ImageContainerOGL::~ImageContainerOGL()
|
||||
{
|
||||
if (mManager) {
|
||||
NS_ASSERTION(mManager->GetBackendType() == LayerManager::LAYERS_OPENGL, "Wrong layer manager got assigned to ImageContainerOGL!");
|
||||
|
||||
static_cast<LayerManagerOGL*>(mManager)->ForgetImageContainer(this);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<Image>
|
||||
ImageContainerOGL::CreateImage(const Image::Format *aFormats,
|
||||
PRUint32 aNumFormats)
|
||||
|
@ -193,7 +208,8 @@ ImageContainerOGL::CreateImage(const Image::Format *aFormats,
|
|||
}
|
||||
nsRefPtr<Image> img;
|
||||
if (aFormats[0] == Image::PLANAR_YCBCR) {
|
||||
img = new PlanarYCbCrImageOGL(mRecycleBin);
|
||||
img = new PlanarYCbCrImageOGL(static_cast<LayerManagerOGL*>(mManager),
|
||||
mRecycleBin);
|
||||
} else if (aFormats[0] == Image::CAIRO_SURFACE) {
|
||||
img = new CairoImageOGL(static_cast<LayerManagerOGL*>(mManager));
|
||||
}
|
||||
|
@ -228,7 +244,47 @@ ImageContainerOGL::GetCurrentImage()
|
|||
already_AddRefed<gfxASurface>
|
||||
ImageContainerOGL::GetCurrentAsSurface(gfxIntSize *aSize)
|
||||
{
|
||||
return nsnull;
|
||||
MutexAutoLock lock(mActiveImageLock);
|
||||
|
||||
if (!mActiveImage) {
|
||||
*aSize = gfxIntSize(0,0);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
GLContext *gl = nsnull;
|
||||
// tex1 will be RGBA or Y, tex2 will Cb, tex3 will be Cr
|
||||
GLuint tex1 = 0, tex2 = 0, tex3 = 0;
|
||||
gfxIntSize size;
|
||||
|
||||
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImageOGL *yuvImage =
|
||||
static_cast<PlanarYCbCrImageOGL*>(mActiveImage.get());
|
||||
if (!yuvImage->HasData() || !yuvImage->HasTextures()) {
|
||||
*aSize = gfxIntSize(0, 0);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
size = yuvImage->mSize;
|
||||
gl = yuvImage->mTextures[0].GetGLContext();
|
||||
tex1 = yuvImage->mTextures[0].GetTextureID();
|
||||
tex2 = yuvImage->mTextures[1].GetTextureID();
|
||||
tex3 = yuvImage->mTextures[2].GetTextureID();
|
||||
}
|
||||
|
||||
if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
CairoImageOGL *cairoImage =
|
||||
static_cast<CairoImageOGL*>(mActiveImage.get());
|
||||
size = cairoImage->mSize;
|
||||
gl = cairoImage->mTexture.GetGLContext();
|
||||
tex1 = cairoImage->mTexture.GetTextureID();
|
||||
}
|
||||
|
||||
// XXX TODO: read all textures in YCbCr case and convert to RGB
|
||||
// XXX Or maybe add a ReadYCbCrTextureImage that will take 3 textures
|
||||
// and return RGB, since we can render YCbCr to the temporary framebuffer.
|
||||
nsRefPtr<gfxImageSurface> s = gl->ReadTextureImage(tex1, size, LOCAL_GL_RGBA);
|
||||
*aSize = size;
|
||||
return s.forget();
|
||||
}
|
||||
|
||||
gfxIntSize
|
||||
|
@ -238,6 +294,7 @@ ImageContainerOGL::GetCurrentSize()
|
|||
if (!mActiveImage) {
|
||||
return gfxIntSize(0,0);
|
||||
}
|
||||
|
||||
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImageOGL *yuvImage =
|
||||
static_cast<PlanarYCbCrImageOGL*>(mActiveImage.get());
|
||||
|
@ -246,7 +303,9 @@ ImageContainerOGL::GetCurrentSize()
|
|||
}
|
||||
return yuvImage->mSize;
|
||||
|
||||
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
}
|
||||
|
||||
if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
CairoImageOGL *cairoImage =
|
||||
static_cast<CairoImageOGL*>(mActiveImage.get());
|
||||
return cairoImage->mSize;
|
||||
|
@ -255,6 +314,38 @@ ImageContainerOGL::GetCurrentSize()
|
|||
return gfxIntSize(0,0);
|
||||
}
|
||||
|
||||
PRBool
|
||||
ImageContainerOGL::SetLayerManager(LayerManager *aManager)
|
||||
{
|
||||
if (!aManager) {
|
||||
// the layer manager just entirely went away
|
||||
|
||||
// XXX if we don't have context sharing, we should tell our images
|
||||
// that their textures are no longer valid.
|
||||
mManager = nsnull;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (aManager->GetBackendType() != LayerManager::LAYERS_OPENGL) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
LayerManagerOGL* lmOld = static_cast<LayerManagerOGL*>(mManager);
|
||||
LayerManagerOGL* lmNew = static_cast<LayerManagerOGL*>(aManager);
|
||||
|
||||
if (lmOld) {
|
||||
NS_ASSERTION(lmNew->glForResources() == lmOld->glForResources(),
|
||||
"We require GL context sharing here!");
|
||||
lmOld->ForgetImageContainer(this);
|
||||
}
|
||||
|
||||
mManager = aManager;
|
||||
|
||||
lmNew->RememberImageContainer(this);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
Layer*
|
||||
ImageLayerOGL::GetLayer()
|
||||
{
|
||||
|
@ -276,11 +367,15 @@ ImageLayerOGL::RenderLayer(int,
|
|||
PlanarYCbCrImageOGL *yuvImage =
|
||||
static_cast<PlanarYCbCrImageOGL*>(image.get());
|
||||
|
||||
if (!yuvImage->HasData())
|
||||
if (!yuvImage->HasData()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!yuvImage->HasTextures()) {
|
||||
yuvImage->AllocateTextures(gl());
|
||||
}
|
||||
|
||||
if (!yuvImage->HasTextures())
|
||||
yuvImage->AllocateTextures(mOGLManager);
|
||||
yuvImage->UpdateTextures(gl());
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[0].GetTextureID());
|
||||
|
@ -335,9 +430,39 @@ ImageLayerOGL::RenderLayer(int,
|
|||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
PlanarYCbCrImageOGL::PlanarYCbCrImageOGL(RecycleBin *aRecycleBin)
|
||||
static void
|
||||
InitTexture(GLContext* aGL, GLuint aTexture, GLenum aFormat, const gfxIntSize& aSize)
|
||||
{
|
||||
aGL->fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
aFormat,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
0,
|
||||
aFormat,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
PlanarYCbCrImageOGL::PlanarYCbCrImageOGL(LayerManagerOGL *aManager,
|
||||
RecycleBin *aRecycleBin)
|
||||
: PlanarYCbCrImage(nsnull), mRecycleBin(aRecycleBin), mHasData(PR_FALSE)
|
||||
{
|
||||
#if 0
|
||||
// We really want to allocate this on the decode thread -- but to do that,
|
||||
// we need to create a per-thread shared GL context, and it will only work
|
||||
// if we have context sharing. For now, create the textures on the main
|
||||
// thread the first time we render.
|
||||
if (aManager) {
|
||||
AllocateTextures(aManager->glForResources());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PlanarYCbCrImageOGL::~PlanarYCbCrImageOGL()
|
||||
|
@ -346,9 +471,11 @@ PlanarYCbCrImageOGL::~PlanarYCbCrImageOGL()
|
|||
mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
|
||||
}
|
||||
|
||||
mRecycleBin->RecycleTexture(&mTextures[0], RecycleBin::TEXTURE_Y, mData.mYSize);
|
||||
mRecycleBin->RecycleTexture(&mTextures[1], RecycleBin::TEXTURE_C, mData.mCbCrSize);
|
||||
mRecycleBin->RecycleTexture(&mTextures[2], RecycleBin::TEXTURE_C, mData.mCbCrSize);
|
||||
if (HasTextures()) {
|
||||
mRecycleBin->RecycleTexture(&mTextures[0], RecycleBin::TEXTURE_Y, mData.mYSize);
|
||||
mRecycleBin->RecycleTexture(&mTextures[1], RecycleBin::TEXTURE_C, mData.mCbCrSize);
|
||||
mRecycleBin->RecycleTexture(&mTextures[2], RecycleBin::TEXTURE_C, mData.mCbCrSize);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -384,7 +511,7 @@ PlanarYCbCrImageOGL::SetData(const PlanarYCbCrImage::Data &aData)
|
|||
|
||||
mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
|
||||
mData.mYStride * mData.mYSize.height;
|
||||
mBuffer = mRecycleBin->TakeBuffer(mBufferSize);
|
||||
mBuffer = mRecycleBin->GetBuffer(mBufferSize);
|
||||
if (!mBuffer)
|
||||
return;
|
||||
|
||||
|
@ -417,54 +544,24 @@ PlanarYCbCrImageOGL::SetData(const PlanarYCbCrImage::Data &aData)
|
|||
mHasData = PR_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
SetupPlaneTexture(GLContext* aGL, const gfxIntSize& aSize, PRUint8* aData, PRBool aIsNew)
|
||||
void
|
||||
PlanarYCbCrImageOGL::AllocateTextures(mozilla::gl::GLContext *gl)
|
||||
{
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl->MakeCurrent();
|
||||
|
||||
if (aIsNew) {
|
||||
aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
0,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
aData);
|
||||
} else {
|
||||
aGL->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
0, 0,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
aData);
|
||||
}
|
||||
mRecycleBin->GetTexture(RecycleBin::TEXTURE_Y, mData.mYSize, gl, &mTextures[0]);
|
||||
InitTexture(gl, mTextures[0].GetTextureID(), LOCAL_GL_LUMINANCE, mData.mYSize);
|
||||
|
||||
mRecycleBin->GetTexture(RecycleBin::TEXTURE_C, mData.mCbCrSize, gl, &mTextures[1]);
|
||||
InitTexture(gl, mTextures[1].GetTextureID(), LOCAL_GL_LUMINANCE, mData.mCbCrSize);
|
||||
|
||||
mRecycleBin->GetTexture(RecycleBin::TEXTURE_C, mData.mCbCrSize, gl, &mTextures[2]);
|
||||
InitTexture(gl, mTextures[2].GetTextureID(), LOCAL_GL_LUMINANCE, mData.mCbCrSize);
|
||||
}
|
||||
|
||||
void
|
||||
PlanarYCbCrImageOGL::AllocateTextures(LayerManagerOGL *aManager)
|
||||
PlanarYCbCrImageOGL::UpdateTextures(GLContext *gl)
|
||||
{
|
||||
aManager->MakeCurrent();
|
||||
|
||||
mozilla::gl::GLContext *gl = aManager->gl();
|
||||
|
||||
PRPackedBool isNewTexture[3];
|
||||
for (PRUint32 i = 0; i < 3; ++i) {
|
||||
isNewTexture[i] = !mTextures[i].IsAllocated();
|
||||
}
|
||||
|
||||
mRecycleBin->TakeTexture(RecycleBin::TEXTURE_Y, mData.mYSize, gl, &mTextures[0]);
|
||||
mRecycleBin->TakeTexture(RecycleBin::TEXTURE_C, mData.mCbCrSize, gl, &mTextures[1]);
|
||||
mRecycleBin->TakeTexture(RecycleBin::TEXTURE_C, mData.mCbCrSize, gl, &mTextures[2]);
|
||||
if (!HasTextures())
|
||||
return;
|
||||
|
||||
GLint alignment;
|
||||
|
||||
if (!((ptrdiff_t)mData.mYStride & 0x7) && !((ptrdiff_t)mData.mYChannel & 0x7)) {
|
||||
|
@ -481,12 +578,16 @@ PlanarYCbCrImageOGL::AllocateTextures(LayerManagerOGL *aManager)
|
|||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment);
|
||||
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextures[0].GetTextureID());
|
||||
|
||||
SetupPlaneTexture(gl, mData.mYSize, mData.mYChannel, isNewTexture[0]);
|
||||
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
|
||||
0, 0, mData.mYSize.width, mData.mYSize.height,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
mData.mYChannel);
|
||||
|
||||
if (!((ptrdiff_t)mData.mCbCrStride & 0x7) &&
|
||||
!((ptrdiff_t)mData.mCbChannel & 0x7) &&
|
||||
!((ptrdiff_t)mData.mCrChannel & 0x7)) {
|
||||
!((ptrdiff_t)mData.mCrChannel & 0x7))
|
||||
{
|
||||
alignment = 8;
|
||||
} else if (!((ptrdiff_t)mData.mCbCrStride & 0x3)) {
|
||||
alignment = 4;
|
||||
|
@ -500,12 +601,18 @@ PlanarYCbCrImageOGL::AllocateTextures(LayerManagerOGL *aManager)
|
|||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment);
|
||||
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextures[1].GetTextureID());
|
||||
|
||||
SetupPlaneTexture(gl, mData.mCbCrSize, mData.mCbChannel, isNewTexture[1]);
|
||||
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
|
||||
0, 0, mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
mData.mCbChannel);
|
||||
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextures[2].GetTextureID());
|
||||
|
||||
SetupPlaneTexture(gl, mData.mCbCrSize, mData.mCrChannel, isNewTexture[2]);
|
||||
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
|
||||
0, 0, mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
mData.mCrChannel);
|
||||
|
||||
// Reset alignment to default
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
|
||||
|
@ -516,12 +623,15 @@ PlanarYCbCrImageOGL::AllocateTextures(LayerManagerOGL *aManager)
|
|||
}
|
||||
}
|
||||
|
||||
CairoImageOGL::CairoImageOGL(LayerManagerOGL *aManager) : CairoImage(nsnull)
|
||||
CairoImageOGL::CairoImageOGL(LayerManagerOGL *aManager)
|
||||
: CairoImage(nsnull)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread to create a cairo image");
|
||||
|
||||
// Allocate texture now to grab a reference to the GLContext
|
||||
mTexture.Allocate(aManager->gl());
|
||||
if (aManager) {
|
||||
// Allocate texture now to grab a reference to the GLContext
|
||||
mTexture.Allocate(aManager->glForResources());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -533,20 +643,20 @@ CairoImageOGL::SetData(const CairoImage::Data &aData)
|
|||
mozilla::gl::GLContext *gl = mTexture.GetGLContext();
|
||||
gl->MakeCurrent();
|
||||
|
||||
mSize = aData.mSize;
|
||||
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture.GetTextureID());
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
if (mSize != aData.mSize) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
InitTexture(gl, mTexture.GetTextureID(), LOCAL_GL_RGBA, aData.mSize);
|
||||
mSize = aData.mSize;
|
||||
} else {
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture.GetTextureID());
|
||||
}
|
||||
|
||||
if (!mASurfaceAsGLContext) {
|
||||
mASurfaceAsGLContext = GLContextProvider::CreateForNativePixmapSurface(aData.mSurface);
|
||||
if (mASurfaceAsGLContext)
|
||||
mASurfaceAsGLContext->BindTexImage();
|
||||
}
|
||||
|
||||
if (mASurfaceAsGLContext)
|
||||
return;
|
||||
|
||||
|
@ -561,15 +671,11 @@ CairoImageOGL::SetData(const CairoImage::Data &aData)
|
|||
context->SetSource(aData.mSurface);
|
||||
context->Paint();
|
||||
|
||||
gl->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
mSize.width,
|
||||
mSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
imageSurface->Data());
|
||||
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
|
||||
0, 0, mSize.width, mSize.height,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
imageSurface->Data());
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -102,7 +102,7 @@ public:
|
|||
|
||||
void RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize);
|
||||
// Returns a recycled buffer of the right size, or allocates a new buffer.
|
||||
PRUint8* TakeBuffer(PRUint32 aSize);
|
||||
PRUint8* GetBuffer(PRUint32 aSize);
|
||||
|
||||
enum TextureType {
|
||||
TEXTURE_Y,
|
||||
|
@ -111,8 +111,8 @@ public:
|
|||
|
||||
void RecycleTexture(GLTexture *aTexture, TextureType aType,
|
||||
const gfxIntSize& aSize);
|
||||
void TakeTexture(TextureType aType, const gfxIntSize& aSize,
|
||||
GLContext *aContext, GLTexture *aOutTexture);
|
||||
void GetTexture(TextureType aType, const gfxIntSize& aSize,
|
||||
GLContext *aContext, GLTexture *aOutTexture);
|
||||
|
||||
private:
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
@ -135,7 +135,7 @@ class THEBES_API ImageContainerOGL : public ImageContainer
|
|||
{
|
||||
public:
|
||||
ImageContainerOGL(LayerManagerOGL *aManager);
|
||||
virtual ~ImageContainerOGL() {}
|
||||
virtual ~ImageContainerOGL();
|
||||
|
||||
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
|
||||
PRUint32 aNumFormats);
|
||||
|
@ -148,6 +148,8 @@ public:
|
|||
|
||||
virtual gfxIntSize GetCurrentSize();
|
||||
|
||||
virtual PRBool SetLayerManager(LayerManager *aManager);
|
||||
|
||||
private:
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
|
@ -169,8 +171,10 @@ public:
|
|||
{
|
||||
mImplData = static_cast<LayerOGL*>(this);
|
||||
}
|
||||
~ImageLayerOGL() { Destroy(); }
|
||||
|
||||
// LayerOGL Implementation
|
||||
virtual void Destroy() { mDestroyed = PR_TRUE; }
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
|
@ -182,7 +186,8 @@ class THEBES_API PlanarYCbCrImageOGL : public PlanarYCbCrImage
|
|||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
public:
|
||||
PlanarYCbCrImageOGL(RecycleBin *aRecycleBin);
|
||||
PlanarYCbCrImageOGL(LayerManagerOGL *aManager,
|
||||
RecycleBin *aRecycleBin);
|
||||
~PlanarYCbCrImageOGL();
|
||||
|
||||
virtual void SetData(const Data &aData);
|
||||
|
@ -191,7 +196,9 @@ public:
|
|||
* Upload the data from out mData into our textures. For now we use this to
|
||||
* make sure the textures are created and filled on the main thread.
|
||||
*/
|
||||
void AllocateTextures(LayerManagerOGL *aManager);
|
||||
void AllocateTextures(GLContext *gl);
|
||||
void UpdateTextures(GLContext *gl);
|
||||
|
||||
PRBool HasData() { return mHasData; }
|
||||
PRBool HasTextures()
|
||||
{
|
||||
|
|
|
@ -76,8 +76,30 @@ LayerManagerOGL::LayerManagerOGL(nsIWidget *aWidget)
|
|||
|
||||
LayerManagerOGL::~LayerManagerOGL()
|
||||
{
|
||||
mRoot = nsnull;
|
||||
CleanupResources();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::Destroy()
|
||||
{
|
||||
if (!mDestroyed) {
|
||||
if (mRoot) {
|
||||
RootLayer()->Destroy();
|
||||
}
|
||||
mRoot = nsnull;
|
||||
|
||||
// Make a copy, since SetLayerManager will cause mImageContainers
|
||||
// to get mutated.
|
||||
nsTArray<ImageContainer*> imageContainers(mImageContainers);
|
||||
for (PRUint32 i = 0; i < imageContainers.Length(); ++i) {
|
||||
ImageContainer *c = imageContainers[i];
|
||||
c->SetLayerManager(nsnull);
|
||||
}
|
||||
|
||||
CleanupResources();
|
||||
|
||||
mDestroyed = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -90,7 +112,7 @@ LayerManagerOGL::CleanupResources()
|
|||
if (!ctx) {
|
||||
ctx = mGLContext;
|
||||
}
|
||||
|
||||
|
||||
ctx->MakeCurrent();
|
||||
|
||||
for (unsigned int i = 0; i < mPrograms.Length(); ++i)
|
||||
|
@ -125,6 +147,7 @@ LayerManagerOGL::Initialize(GLContext *aExistingContext)
|
|||
} else {
|
||||
if (mGLContext)
|
||||
CleanupResources();
|
||||
|
||||
mGLContext = gl::GLContextProvider::CreateForWindow(mWidget);
|
||||
|
||||
if (!mGLContext) {
|
||||
|
@ -137,10 +160,9 @@ LayerManagerOGL::Initialize(GLContext *aExistingContext)
|
|||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
const char *extensionStr =
|
||||
(const char*) mGLContext->fGetString(LOCAL_GL_EXTENSIONS);
|
||||
|
||||
mHasBGRA = (strstr(extensionStr, "EXT_bgra") != nsnull);
|
||||
mHasBGRA =
|
||||
mGLContext->IsExtensionSupported(gl::GLContext::EXT_texture_format_BGRA8888) ||
|
||||
mGLContext->IsExtensionSupported(gl::GLContext::EXT_bgra);
|
||||
|
||||
mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
|
||||
LOCAL_GL_ONE, LOCAL_GL_ONE);
|
||||
|
@ -259,7 +281,7 @@ LayerManagerOGL::Initialize(GLContext *aExistingContext)
|
|||
* texture rectangle access inside GLSL (sampler2DRect,
|
||||
* texture2DRect).
|
||||
*/
|
||||
if (strstr(extensionStr, "ARB_texture_rectangle") == NULL)
|
||||
if (!mGLContext->IsExtensionSupported(gl::GLContext::ARB_texture_rectangle))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -327,6 +349,11 @@ LayerManagerOGL::BeginTransaction()
|
|||
void
|
||||
LayerManagerOGL::BeginTransactionWithTarget(gfxContext *aTarget)
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return;
|
||||
}
|
||||
|
||||
mTarget = aTarget;
|
||||
}
|
||||
|
||||
|
@ -334,6 +361,11 @@ void
|
|||
LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return;
|
||||
}
|
||||
|
||||
mThebesLayerCallback = aCallback;
|
||||
mThebesLayerCallbackData = aCallbackData;
|
||||
|
||||
|
@ -348,6 +380,11 @@ LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback,
|
|||
already_AddRefed<ThebesLayer>
|
||||
LayerManagerOGL::CreateThebesLayer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ThebesLayer> layer = new ThebesLayerOGL(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
@ -355,6 +392,11 @@ LayerManagerOGL::CreateThebesLayer()
|
|||
already_AddRefed<ContainerLayer>
|
||||
LayerManagerOGL::CreateContainerLayer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ContainerLayer> layer = new ContainerLayerOGL(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
@ -362,13 +404,24 @@ LayerManagerOGL::CreateContainerLayer()
|
|||
already_AddRefed<ImageContainer>
|
||||
LayerManagerOGL::CreateImageContainer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ImageContainer> container = new ImageContainerOGL(this);
|
||||
RememberImageContainer(container);
|
||||
return container.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ImageLayer>
|
||||
LayerManagerOGL::CreateImageLayer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ImageLayer> layer = new ImageLayerOGL(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
@ -376,6 +429,11 @@ LayerManagerOGL::CreateImageLayer()
|
|||
already_AddRefed<ColorLayer>
|
||||
LayerManagerOGL::CreateColorLayer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ColorLayer> layer = new ColorLayerOGL(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
@ -383,25 +441,65 @@ LayerManagerOGL::CreateColorLayer()
|
|||
already_AddRefed<CanvasLayer>
|
||||
LayerManagerOGL::CreateCanvasLayer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<CanvasLayer> layer = new CanvasLayerOGL(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::ForgetImageContainer(ImageContainer *aContainer)
|
||||
{
|
||||
NS_ASSERTION(aContainer->Manager() == this,
|
||||
"ForgetImageContainer called on non-owned container!");
|
||||
|
||||
if (!mImageContainers.RemoveElement(aContainer)) {
|
||||
NS_WARNING("ForgetImageContainer couldn't find container it was supposed to forget!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::RememberImageContainer(ImageContainer *aContainer)
|
||||
{
|
||||
NS_ASSERTION(aContainer->Manager() == this,
|
||||
"RememberImageContainer called on non-owned container!");
|
||||
mImageContainers.AppendElement(aContainer);
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::MakeCurrent()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return;
|
||||
}
|
||||
|
||||
mGLContext->MakeCurrent();
|
||||
}
|
||||
|
||||
LayerOGL*
|
||||
LayerManagerOGL::RootLayer() const
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return static_cast<LayerOGL*>(mRoot->ImplData());
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::Render()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect rect;
|
||||
mWidget->GetBounds(rect);
|
||||
GLint width = rect.width;
|
||||
|
@ -645,12 +743,22 @@ LayerManagerOGL::CopyToTarget()
|
|||
NS_ASSERTION(imageSurface->Stride() == width * 4,
|
||||
"Image Surfaces being created with weird stride!");
|
||||
|
||||
PRUint32 currentPackAlignment = 0;
|
||||
mGLContext->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)¤tPackAlignment);
|
||||
if (currentPackAlignment != 4) {
|
||||
mGLContext->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
|
||||
}
|
||||
|
||||
mGLContext->fReadPixels(0, 0,
|
||||
width, height,
|
||||
format,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
imageSurface->Data());
|
||||
|
||||
if (currentPackAlignment != 4) {
|
||||
mGLContext->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
|
||||
}
|
||||
|
||||
if (!mHasBGRA) {
|
||||
// need to swap B and R bytes
|
||||
for (int j = 0; j < height; ++j) {
|
||||
|
@ -739,6 +847,5 @@ LayerManagerOGL::CreateFBOWithTexture(int aWidth, int aHeight,
|
|||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
|
|
|
@ -83,6 +83,8 @@ public:
|
|||
|
||||
void CleanupResources();
|
||||
|
||||
void Destroy();
|
||||
|
||||
/**
|
||||
* Initializes the layer manager, this is when the layer manager will
|
||||
* actually access the device and attempt to create the swap chain used
|
||||
|
@ -135,6 +137,16 @@ public:
|
|||
|
||||
virtual LayersBackend GetBackendType() { return LAYERS_OPENGL; }
|
||||
|
||||
/**
|
||||
* Image Container management.
|
||||
*/
|
||||
|
||||
/* Forget this image container. Should be called by ImageContainerOGL
|
||||
* on its current layer manager before switching to a new one.
|
||||
*/
|
||||
void ForgetImageContainer(ImageContainer* aContainer);
|
||||
void RememberImageContainer(ImageContainer* aContainer);
|
||||
|
||||
/**
|
||||
* Helper methods.
|
||||
*/
|
||||
|
@ -182,6 +194,16 @@ public:
|
|||
void* GetThebesLayerCallbackData() const
|
||||
{ return mThebesLayerCallbackData; }
|
||||
|
||||
// This is a GLContext that can be used for resource
|
||||
// management (creation, destruction). It is guaranteed
|
||||
// to be either the same as the gl() context, or a context
|
||||
// that is in the same share pool.
|
||||
GLContext *glForResources() const {
|
||||
if (mGLContext->GetSharedContext())
|
||||
return mGLContext->GetSharedContext();
|
||||
return mGLContext;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper functions for our layers
|
||||
*/
|
||||
|
@ -281,6 +303,11 @@ private:
|
|||
|
||||
nsRefPtr<GLContext> mGLContext;
|
||||
|
||||
// The image containers that this layer manager has created.
|
||||
// The destructor will tell the layer manager to remove
|
||||
// it from the list.
|
||||
nsTArray<ImageContainer*> mImageContainers;
|
||||
|
||||
enum ProgramType {
|
||||
RGBALayerProgramType,
|
||||
BGRALayerProgramType,
|
||||
|
@ -364,13 +391,20 @@ class LayerOGL
|
|||
{
|
||||
public:
|
||||
LayerOGL(LayerManagerOGL *aManager)
|
||||
: mOGLManager(aManager)
|
||||
: mOGLManager(aManager), mDestroyed(PR_FALSE)
|
||||
{ }
|
||||
|
||||
virtual ~LayerOGL() { }
|
||||
|
||||
virtual LayerOGL *GetFirstChildOGL() {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/* Do NOT call this from the generic LayerOGL destructor. Only from the
|
||||
* concrete class destructor
|
||||
*/
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
virtual Layer* GetLayer() = 0;
|
||||
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
|
@ -381,6 +415,7 @@ public:
|
|||
GLContext *gl() const { return mOGLManager->gl(); }
|
||||
protected:
|
||||
LayerManagerOGL *mOGLManager;
|
||||
PRPackedBool mDestroyed;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
|
|
@ -300,19 +300,17 @@ protected:
|
|||
}
|
||||
fprintf (stderr, "=== Log:\n%s\n", nsPromiseFlatCString(log).get());
|
||||
fprintf (stderr, "============\n");
|
||||
}
|
||||
|
||||
// We can mark the shaders for deletion; they're attached to the program
|
||||
// and will remain attached.
|
||||
mGL->fDeleteShader(vertexShader);
|
||||
mGL->fDeleteShader(fragmentShader);
|
||||
// We can mark the shaders for deletion; they're attached to the program
|
||||
// and will remain attached.
|
||||
mGL->fDeleteShader(vertexShader);
|
||||
mGL->fDeleteShader(fragmentShader);
|
||||
|
||||
if (!success) {
|
||||
mGL->fDeleteProgram(mProgram);
|
||||
|
||||
mProgram = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!success) {
|
||||
mGL->fDeleteProgram(mProgram);
|
||||
mProgram = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now query uniforms, so that we can initialize mUniformValues
|
||||
|
|
|
@ -331,8 +331,18 @@ ThebesLayerOGL::ThebesLayerOGL(LayerManagerOGL *aManager)
|
|||
|
||||
ThebesLayerOGL::~ThebesLayerOGL()
|
||||
{
|
||||
mBuffer = nsnull;
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerOGL::Destroy()
|
||||
{
|
||||
if (!mDestroyed) {
|
||||
mBuffer = nsnull;
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
|
||||
mDestroyed = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace layers {
|
|||
class ThebesLayerBufferOGL;
|
||||
|
||||
class ThebesLayerOGL : public ThebesLayer,
|
||||
public LayerOGL
|
||||
public LayerOGL
|
||||
{
|
||||
typedef ThebesLayerBufferOGL Buffer;
|
||||
|
||||
|
@ -65,6 +65,7 @@ public:
|
|||
void InvalidateRegion(const nsIntRegion& aRegion);
|
||||
|
||||
/** LayerOGL implementation */
|
||||
void Destroy();
|
||||
Layer* GetLayer();
|
||||
virtual PRBool IsEmpty();
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
|
|
|
@ -309,9 +309,64 @@ GLContext::InitWithPrefix(const char *prefix, PRBool trygl)
|
|||
};
|
||||
|
||||
mInitialized = LoadSymbols(&symbols[0], trygl, prefix);
|
||||
|
||||
if (mInitialized) {
|
||||
InitExtensions();
|
||||
}
|
||||
|
||||
return mInitialized;
|
||||
}
|
||||
|
||||
// should match the order of GLExtensions
|
||||
static const char *sExtensionNames[] = {
|
||||
"GL_EXT_framebuffer_object",
|
||||
"GL_ARB_framebuffer_object",
|
||||
"GL_ARB_texture_rectangle",
|
||||
"GL_EXT_bgra",
|
||||
"GL_EXT_texture_format_BGRA8888",
|
||||
"GL_OES_depth24",
|
||||
"GL_OES_depth32",
|
||||
"GL_OES_stencil8",
|
||||
"GL_OES_texture_npot",
|
||||
"GL_OES_depth_texture",
|
||||
"GL_OES_packed_depth_stencil",
|
||||
"GL_IMG_read_format",
|
||||
"GL_EXT_read_format_bgra",
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
GLContext::InitExtensions()
|
||||
{
|
||||
MakeCurrent();
|
||||
const GLubyte *extensions = fGetString(LOCAL_GL_EXTENSIONS);
|
||||
char *exts = strdup((char *)extensions);
|
||||
|
||||
printf_stderr("GL extensions: %s\n", exts);
|
||||
|
||||
char *s = exts;
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
char *space = strchr(s, ' ');
|
||||
if (space) {
|
||||
*space = '\0';
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
|
||||
for (int i = 0; sExtensionNames[i]; ++i) {
|
||||
if (strcmp(s, sExtensionNames[i]) == 0) {
|
||||
printf_stderr("Found extension %s\n", s);
|
||||
mAvailableExtensions[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
s = space+1;
|
||||
}
|
||||
|
||||
free(exts);
|
||||
}
|
||||
|
||||
PRBool
|
||||
GLContext::IsExtensionSupported(const char *extension)
|
||||
{
|
||||
|
@ -479,6 +534,9 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
|||
|
||||
GLint viewport[4];
|
||||
|
||||
bool useDepthStencil =
|
||||
!mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil);
|
||||
|
||||
// save a few things for later restoring
|
||||
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &curBoundTexture);
|
||||
fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*) &curBoundFramebuffer);
|
||||
|
@ -496,7 +554,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
|||
fGenFramebuffers(1, &mOffscreenFBO);
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mOffscreenFBO);
|
||||
|
||||
if (depth && stencil && !mIsGLES2) {
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fGenRenderbuffers(1, &mOffscreenDepthRB);
|
||||
} else {
|
||||
if (depth) {
|
||||
|
@ -529,18 +587,35 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
|||
aSize.width, aSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGB,
|
||||
#ifdef XP_WIN
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
#else
|
||||
mIsGLES2 ? LOCAL_GL_UNSIGNED_SHORT_5_6_5
|
||||
: LOCAL_GL_UNSIGNED_BYTE,
|
||||
#endif
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (depth && stencil && !mIsGLES2) {
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenDepthRB);
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
LOCAL_GL_DEPTH24_STENCIL8,
|
||||
aSize.width, aSize.height);
|
||||
} else {
|
||||
if (depth) {
|
||||
GLenum depthType;
|
||||
if (mIsGLES2) {
|
||||
if (IsExtensionSupported(OES_depth32)) {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT32;
|
||||
} else if (IsExtensionSupported(OES_depth24)) {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
} else {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
} else {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
}
|
||||
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenDepthRB);
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
mIsGLES2 ? LOCAL_GL_DEPTH_COMPONENT16
|
||||
|
@ -565,7 +640,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
|||
mOffscreenTexture,
|
||||
0);
|
||||
|
||||
if (depth && stencil && !mIsGLES2) {
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
|
@ -603,6 +678,10 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
|||
|
||||
if (firstTime) {
|
||||
UpdateActualFormat();
|
||||
|
||||
printf_stderr("Created offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d\n",
|
||||
mActualFormat.red, mActualFormat.green, mActualFormat.blue, mActualFormat.alpha,
|
||||
mActualFormat.depth, mActualFormat.stencil);
|
||||
}
|
||||
|
||||
// We're good, and the framebuffer is already attached, so let's
|
||||
|
@ -665,7 +744,216 @@ GLContext::ClearSafely()
|
|||
void
|
||||
GLContext::UpdateActualFormat()
|
||||
{
|
||||
// TODO
|
||||
ContextFormat nf;
|
||||
|
||||
fGetIntegerv(LOCAL_GL_RED_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_GREEN_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_BLUE_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_ALPHA_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_DEPTH_BITS, (GLint*) &nf.depth);
|
||||
fGetIntegerv(LOCAL_GL_STENCIL_BITS, (GLint*) &nf.depth);
|
||||
|
||||
mActualFormat = nf;
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::MarkDestroyed()
|
||||
{
|
||||
MakeCurrent();
|
||||
DeleteOffscreenFBO();
|
||||
memset(&mFunctionListStartSentinel, 0, &mFunctionListEndSentinel - &mFunctionListStartSentinel);
|
||||
}
|
||||
|
||||
already_AddRefed<gfxImageSurface>
|
||||
GLContext::ReadTextureImage(GLuint aTexture,
|
||||
const gfxIntSize& aSize,
|
||||
GLenum aTextureFormat)
|
||||
{
|
||||
MakeCurrent();
|
||||
|
||||
nsRefPtr<gfxImageSurface> isurf;
|
||||
|
||||
GLint oldrb, oldfb, oldprog, oldvp[4], oldPackAlignment;
|
||||
GLint success;
|
||||
|
||||
GLuint rb = 0, fb = 0;
|
||||
GLuint vs = 0, fs = 0, prog = 0;
|
||||
|
||||
const char *vShader =
|
||||
"attribute vec4 aVertex;\n"
|
||||
"attribute vec2 aTexCoord;\n"
|
||||
"varying vec2 vTexCoord;\n"
|
||||
"void main() { gl_Position = aVertex; vTexCoord = aTexCoord; }";
|
||||
const char *fShader =
|
||||
"#ifdef GL_ES\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"varying vec2 vTexCoord;\n"
|
||||
"uniform sampler2D uTexture;\n"
|
||||
"void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }";
|
||||
|
||||
float verts[4*4] = {
|
||||
-1.0f, -1.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f,
|
||||
-1.0f, 1.0f, 0.0f, 1.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
float texcoords[2*4] = {
|
||||
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f
|
||||
};
|
||||
|
||||
fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &oldrb);
|
||||
fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &oldfb);
|
||||
fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &oldprog);
|
||||
fGetIntegerv(LOCAL_GL_VIEWPORT, oldvp);
|
||||
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &oldPackAlignment);
|
||||
|
||||
fGenRenderbuffers(1, &rb);
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, rb);
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, LOCAL_GL_RGBA,
|
||||
aSize.width, aSize.height);
|
||||
|
||||
fGenFramebuffers(1, &fb);
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_RENDERBUFFER, rb);
|
||||
|
||||
if (fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) !=
|
||||
LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
vs = fCreateShader(LOCAL_GL_VERTEX_SHADER);
|
||||
fs = fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
|
||||
fShaderSource(vs, 1, (const GLchar**) &vShader, NULL);
|
||||
fShaderSource(fs, 1, (const GLchar**) &fShader, NULL);
|
||||
prog = fCreateProgram();
|
||||
fAttachShader(prog, vs);
|
||||
fAttachShader(prog, fs);
|
||||
fBindAttribLocation(prog, 0, "aVertex");
|
||||
fBindAttribLocation(prog, 1, "aTexCoord");
|
||||
fLinkProgram(prog);
|
||||
|
||||
fGetProgramiv(prog, LOCAL_GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
fUseProgram(prog);
|
||||
|
||||
fEnableVertexAttribArray(0);
|
||||
fEnableVertexAttribArray(1);
|
||||
|
||||
fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, verts);
|
||||
fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, texcoords);
|
||||
|
||||
fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
|
||||
|
||||
fUniform1i(fGetUniformLocation(prog, "uTexture"), 0);
|
||||
|
||||
fViewport(0, 0, aSize.width, aSize.height);
|
||||
|
||||
fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
fDisableVertexAttribArray(1);
|
||||
fDisableVertexAttribArray(0);
|
||||
|
||||
isurf = new gfxImageSurface(aSize, gfxASurface::ImageFormatARGB32);
|
||||
if (!isurf || isurf->CairoStatus()) {
|
||||
isurf = nsnull;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (oldPackAlignment != 4)
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
fReadPixels(0, 0, aSize.width, aSize.height,
|
||||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
|
||||
isurf->Data());
|
||||
|
||||
if (oldPackAlignment != 4)
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, oldPackAlignment);
|
||||
|
||||
cleanup:
|
||||
// note that deleting 0 has no effect in any of these calls
|
||||
fDeleteRenderbuffers(1, &rb);
|
||||
fDeleteFramebuffers(1, &fb);
|
||||
fDeleteShader(vs);
|
||||
fDeleteShader(fs);
|
||||
fDeleteProgram(prog);
|
||||
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, oldrb);
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, oldfb);
|
||||
fUseProgram(oldprog);
|
||||
fViewport(oldvp[0], oldvp[1], oldvp[2], oldvp[3]);
|
||||
|
||||
return isurf.forget();
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::ReadPixelsIntoImageSurface(GLint aX, GLint aY,
|
||||
GLsizei aWidth, GLsizei aHeight,
|
||||
gfxImageSurface *aDest)
|
||||
{
|
||||
MakeCurrent();
|
||||
|
||||
if (aDest->Format() != gfxASurface::ImageFormatARGB32 &&
|
||||
aDest->Format() != gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
NS_WARNING("ReadPixelsIntoImageSurface called with invalid image format");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aDest->Width() != aWidth ||
|
||||
aDest->Height() != aHeight ||
|
||||
aDest->Stride() != aWidth * 4)
|
||||
{
|
||||
NS_WARNING("ReadPixelsIntoImageSurface called with wrong size or stride surface");
|
||||
return;
|
||||
}
|
||||
|
||||
GLint currentPackAlignment = 0;
|
||||
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, ¤tPackAlignment);
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
// defaults for desktop
|
||||
GLenum format = LOCAL_GL_BGRA;
|
||||
GLenum datatype = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
bool swap = false;
|
||||
|
||||
if (IsGLES2()) {
|
||||
datatype = LOCAL_GL_UNSIGNED_BYTE;
|
||||
|
||||
if (IsExtensionSupported(gl::GLContext::EXT_read_format_bgra) ||
|
||||
IsExtensionSupported(gl::GLContext::IMG_read_format) ||
|
||||
IsExtensionSupported(gl::GLContext::EXT_bgra))
|
||||
{
|
||||
format = LOCAL_GL_BGRA;
|
||||
} else {
|
||||
format = LOCAL_GL_RGBA;
|
||||
swap = true;
|
||||
}
|
||||
}
|
||||
|
||||
fReadPixels(0, 0, aWidth, aHeight,
|
||||
format, datatype,
|
||||
aDest->Data());
|
||||
|
||||
if (swap) {
|
||||
// swap B and R bytes
|
||||
for (int j = 0; j < aHeight; ++j) {
|
||||
PRUint32 *row = (PRUint32*) (aDest->Data() + aDest->Stride() * j);
|
||||
for (int i = 0; i < aWidth; ++i) {
|
||||
*row = (*row & 0xff00ff00) | ((*row & 0xff) << 16) | ((*row & 0xff0000) >> 16);
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -385,6 +385,10 @@ public:
|
|||
mUserData.Put(aKey, aValue);
|
||||
}
|
||||
|
||||
// Mark this context as destroyed. This will NULL out all
|
||||
// the GL function pointers!
|
||||
void THEBES_API MarkDestroyed();
|
||||
|
||||
enum NativeDataType {
|
||||
NativeGLContext,
|
||||
NativeImageSurface,
|
||||
|
@ -395,6 +399,9 @@ public:
|
|||
virtual void *GetNativeData(NativeDataType aType) { return NULL; }
|
||||
GLContext *GetSharedContext() { return mSharedContext; }
|
||||
|
||||
PRBool IsGlobalSharedContext() { return mIsGlobalSharedContext; }
|
||||
void SetIsGlobalSharedContext(PRBool aIsOne) { mIsGlobalSharedContext = aIsOne; }
|
||||
|
||||
const ContextFormat& CreationFormat() { return mCreationFormat; }
|
||||
const ContextFormat& ActualFormat() { return mActualFormat; }
|
||||
|
||||
|
@ -428,20 +435,6 @@ public:
|
|||
*/
|
||||
virtual PRBool ReleaseTexImage() { return PR_FALSE; }
|
||||
|
||||
virtual GLuint CreateTexture()
|
||||
{
|
||||
GLuint tex;
|
||||
MakeCurrent();
|
||||
fGenTextures(1, &tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
virtual void DestroyTexture(GLuint tex)
|
||||
{
|
||||
MakeCurrent();
|
||||
fDeleteTextures(1, &tex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Offscreen support API
|
||||
*/
|
||||
|
@ -554,10 +547,61 @@ public:
|
|||
GLint aWrapMode,
|
||||
PRBool aUseNearestFilter=PR_FALSE);
|
||||
|
||||
/**
|
||||
* Read the image data contained in aTexture, and return it as an ImageSurface.
|
||||
* If GL_RGBA is given as the format, a ImageFormatARGB32 surface is returned.
|
||||
* Not implemented yet:
|
||||
* If GL_RGB is given as the format, a ImageFormatRGB24 surface is returned.
|
||||
* If GL_LUMINANCE is given as the format, a ImageFormatA8 surface is returned.
|
||||
*
|
||||
* THIS IS EXPENSIVE. It is ridiculously expensive. Only do this
|
||||
* if you absolutely positively must, and never in any performance
|
||||
* critical path.
|
||||
*/
|
||||
already_AddRefed<gfxImageSurface> ReadTextureImage(GLuint aTexture,
|
||||
const gfxIntSize& aSize,
|
||||
GLenum aTextureFormat);
|
||||
|
||||
/**
|
||||
* Call ReadPixels into an existing gfxImageSurface for the given bounds.
|
||||
* The image surface must be using image format RGBA32 or RGB24.
|
||||
*/
|
||||
void ReadPixelsIntoImageSurface(GLint aX, GLint aY, GLsizei aWidth, GLsizei aHeight,
|
||||
gfxImageSurface *aDest);
|
||||
|
||||
/**
|
||||
* Known GL extensions that can be queried by
|
||||
* IsExtensionSupported. The results of this are cached, and as
|
||||
* such it's safe to use this even in performance critical code.
|
||||
* If you add to this array, remember to add to the string names
|
||||
* in GLContext.cpp.
|
||||
*/
|
||||
enum GLExtensions {
|
||||
EXT_framebuffer_object,
|
||||
ARB_framebuffer_object,
|
||||
ARB_texture_rectangle,
|
||||
EXT_bgra,
|
||||
EXT_texture_format_BGRA8888,
|
||||
OES_depth24,
|
||||
OES_depth32,
|
||||
OES_stencil8,
|
||||
OES_texture_npot,
|
||||
OES_depth_texture,
|
||||
OES_packed_depth_stencil,
|
||||
IMG_read_format,
|
||||
EXT_read_format_bgra,
|
||||
Extensions_Max
|
||||
};
|
||||
|
||||
PRBool IsExtensionSupported(GLExtensions aKnownExtension) {
|
||||
return mAvailableExtensions[aKnownExtension];
|
||||
}
|
||||
|
||||
protected:
|
||||
PRPackedBool mInitialized;
|
||||
PRPackedBool mIsOffscreen;
|
||||
PRPackedBool mIsGLES2;
|
||||
PRPackedBool mIsGlobalSharedContext;
|
||||
ContextFormat mCreationFormat;
|
||||
nsRefPtr<GLContext> mSharedContext;
|
||||
|
||||
|
@ -576,6 +620,25 @@ protected:
|
|||
GLuint mOffscreenDepthRB;
|
||||
GLuint mOffscreenStencilRB;
|
||||
|
||||
// this should just be a std::bitset, but that ended up breaking
|
||||
// MacOS X builds; see bug 584919. We can replace this with one
|
||||
// later on.
|
||||
template<size_t setlen>
|
||||
struct ExtensionBitset {
|
||||
ExtensionBitset() {
|
||||
for (int i = 0; i < setlen; ++i)
|
||||
values[i] = false;
|
||||
}
|
||||
|
||||
bool& operator[](const int index) {
|
||||
NS_ASSERTION(index >= 0 && index < setlen, "out of range");
|
||||
return values[index];
|
||||
}
|
||||
|
||||
bool values[setlen];
|
||||
};
|
||||
ExtensionBitset<Extensions_Max> mAvailableExtensions;
|
||||
|
||||
// Clear to transparent black, with 0 depth and stencil,
|
||||
// while preserving current ClearColor etc. values.
|
||||
// Useful for resizing offscreen buffers.
|
||||
|
@ -590,6 +653,7 @@ protected:
|
|||
|
||||
PRBool InitWithPrefix(const char *prefix, PRBool trygl);
|
||||
|
||||
void InitExtensions();
|
||||
PRBool IsExtensionSupported(const char *extension);
|
||||
|
||||
virtual already_AddRefed<TextureImage>
|
||||
|
@ -607,6 +671,9 @@ public:
|
|||
* perl-or-python-or-js script somewhere and would be
|
||||
* autogenerated; one would be wrong.
|
||||
*/
|
||||
// Keep this at the start of the function pointers
|
||||
void *mFunctionListStartSentinel;
|
||||
|
||||
typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
PFNGLACTIVETEXTUREPROC fActiveTexture;
|
||||
typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
|
@ -851,6 +918,9 @@ public:
|
|||
typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGE) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
|
||||
PFNGLRENDERBUFFERSTORAGE fRenderbufferStorage;
|
||||
|
||||
// keep this at the end of the function pointers
|
||||
void *mFunctionListEndSentinel;
|
||||
|
||||
void fDepthRange(GLclampf a, GLclampf b) {
|
||||
if (mIsGLES2) {
|
||||
priv_fDepthRangef(a, b);
|
||||
|
@ -963,127 +1033,73 @@ public:
|
|||
priv_fDeleteRenderbuffers(n, names);
|
||||
}
|
||||
#else
|
||||
GLContext *TrackingContext() {
|
||||
GLContext *tip = this;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
return tip;
|
||||
}
|
||||
|
||||
GLuint GLAPIENTRY fCreateProgram() {
|
||||
GLuint ret = priv_fCreateProgram();
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedProgram(this, ret);
|
||||
}
|
||||
TrackingContext()->CreatedProgram(this, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GLuint GLAPIENTRY fCreateShader(GLenum t) {
|
||||
GLuint ret = priv_fCreateShader(t);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedShader(this, ret);
|
||||
}
|
||||
TrackingContext()->CreatedShader(this, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenBuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenBuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedBuffers(this, n, names);
|
||||
}
|
||||
TrackingContext()->CreatedBuffers(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenTextures(GLsizei n, GLuint* names) {
|
||||
priv_fGenTextures(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedTextures(this, n, names);
|
||||
}
|
||||
TrackingContext()->CreatedTextures(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenFramebuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenFramebuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedFramebuffers(this, n, names);
|
||||
}
|
||||
TrackingContext()->CreatedFramebuffers(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenRenderbuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenRenderbuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedRenderbuffers(this, n, names);
|
||||
}
|
||||
TrackingContext()->CreatedRenderbuffers(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteProgram(GLuint program) {
|
||||
priv_fDeleteProgram(program);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedProgram(this, program);
|
||||
}
|
||||
TrackingContext()->DeletedProgram(this, program);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteShader(GLuint shader) {
|
||||
priv_fDeleteShader(shader);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedShader(this, shader);
|
||||
}
|
||||
TrackingContext()->DeletedShader(this, shader);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteBuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteBuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedBuffers(this, n, names);
|
||||
}
|
||||
TrackingContext()->DeletedBuffers(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteTextures(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteTextures(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedTextures(this, n, names);
|
||||
}
|
||||
TrackingContext()->DeletedTextures(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteFramebuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteFramebuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedFramebuffers(this, n, names);
|
||||
}
|
||||
|
||||
TrackingContext()->DeletedFramebuffers(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteRenderbuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteRenderbuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedRenderbuffers(this, n, names);
|
||||
}
|
||||
TrackingContext()->DeletedRenderbuffers(this, n, names);
|
||||
}
|
||||
|
||||
void THEBES_API CreatedProgram(GLContext *aOrigin, GLuint aName);
|
||||
|
|
|
@ -74,12 +74,15 @@ namespace gl {
|
|||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO)
|
||||
#if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO) || defined(XP_WIN)
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
|
||||
#ifndef GL_CONTEXT_PROVIDER_DEFAULT
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// X11, but only if we didn't use EGL above
|
||||
#if defined(MOZ_X11) && !defined(GL_CONTEXT_PROVIDER_DEFAULT)
|
||||
|
|
|
@ -520,6 +520,8 @@ GLContextProviderCGL::GetGlobalContext()
|
|||
gGlobalContext = nsnull;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
|
|
|
@ -76,6 +76,62 @@ typedef void *EGLNativeWindowType;
|
|||
#define EGL_LIB "/system/lib/libEGL.so"
|
||||
#define GLES2_LIB "/system/lib/libGLESv2.so"
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
|
||||
#include <nsServiceManagerUtils.h>
|
||||
#include <nsIPrefBranch.h>
|
||||
#include <nsILocalFile.h>
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
typedef HDC EGLNativeDisplayType;
|
||||
typedef HBITMAP EGLNativePixmapType;
|
||||
typedef HWND EGLNativeWindowType;
|
||||
|
||||
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
|
||||
|
||||
#define EGL_LIB "libEGL.dll"
|
||||
#define GLES2_LIB "libGLESv2.dll"
|
||||
|
||||
// a little helper
|
||||
class AutoDestroyHWND {
|
||||
public:
|
||||
AutoDestroyHWND(HWND aWnd = NULL)
|
||||
: mWnd(aWnd)
|
||||
{
|
||||
}
|
||||
|
||||
~AutoDestroyHWND() {
|
||||
if (mWnd) {
|
||||
::DestroyWindow(mWnd);
|
||||
}
|
||||
}
|
||||
|
||||
operator HWND() {
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
HWND forget() {
|
||||
HWND w = mWnd;
|
||||
mWnd = NULL;
|
||||
return w;
|
||||
}
|
||||
|
||||
HWND operator=(HWND aWnd) {
|
||||
if (mWnd && mWnd != aWnd) {
|
||||
::DestroyWindow(mWnd);
|
||||
}
|
||||
mWnd = aWnd;
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
HWND mWnd;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#error "Platform not recognized"
|
||||
|
@ -147,58 +203,58 @@ public:
|
|||
mHave_EGL_KHR_gl_texture_2D_image = PR_FALSE;
|
||||
}
|
||||
|
||||
typedef EGLDisplay (*pfnGetDisplay)(void *display_id);
|
||||
typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void *display_id);
|
||||
pfnGetDisplay fGetDisplay;
|
||||
typedef EGLContext (*pfnGetCurrentContext)(void);
|
||||
typedef EGLContext (GLAPIENTRY * pfnGetCurrentContext)(void);
|
||||
pfnGetCurrentContext fGetCurrentContext;
|
||||
typedef EGLBoolean (*pfnMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
pfnMakeCurrent fMakeCurrent;
|
||||
typedef EGLBoolean (*pfnDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
||||
pfnDestroyContext fDestroyContext;
|
||||
typedef EGLContext (*pfnCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
|
||||
typedef EGLContext (GLAPIENTRY * pfnCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
|
||||
pfnCreateContext fCreateContext;
|
||||
typedef EGLBoolean (*pfnDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||
pfnDestroySurface fDestroySurface;
|
||||
typedef EGLSurface (*pfnCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
|
||||
typedef EGLSurface (GLAPIENTRY * pfnCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
|
||||
pfnCreateWindowSurface fCreateWindowSurface;
|
||||
typedef EGLSurface (*pfnCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
typedef EGLSurface (GLAPIENTRY * pfnCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
pfnCreatePbufferSurface fCreatePbufferSurface;
|
||||
typedef EGLSurface (*pfnCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
|
||||
typedef EGLSurface (GLAPIENTRY * pfnCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
|
||||
pfnCreatePixmapSurface fCreatePixmapSurface;
|
||||
typedef EGLBoolean (*pfnBindAPI)(EGLenum api);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnBindAPI)(EGLenum api);
|
||||
pfnBindAPI fBindAPI;
|
||||
typedef EGLBoolean (*pfnInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
pfnInitialize fInitialize;
|
||||
typedef EGLBoolean (*pfnChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
pfnChooseConfig fChooseConfig;
|
||||
typedef EGLint (*pfnGetError)(void);
|
||||
typedef EGLint (GLAPIENTRY * pfnGetError)(void);
|
||||
pfnGetError fGetError;
|
||||
typedef EGLBoolean (*pfnGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
pfnGetConfigAttrib fGetConfigAttrib;
|
||||
typedef EGLBoolean (*pfnGetConfigs)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnGetConfigs)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
pfnGetConfigs fGetConfigs;
|
||||
typedef EGLBoolean (*pfnWaitNative)(EGLint engine);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnWaitNative)(EGLint engine);
|
||||
pfnWaitNative fWaitNative;
|
||||
typedef EGLCastToRelevantPtr (*pfnGetProcAddress)(const char *procname);
|
||||
typedef EGLCastToRelevantPtr (GLAPIENTRY * pfnGetProcAddress)(const char *procname);
|
||||
pfnGetProcAddress fGetProcAddress;
|
||||
typedef EGLBoolean (*pfnSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||
pfnSwapBuffers fSwapBuffers;
|
||||
typedef EGLBoolean (*pfnCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLNativePixmapType target);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLNativePixmapType target);
|
||||
pfnCopyBuffers fCopyBuffers;
|
||||
typedef const GLubyte* (*pfnQueryString)(EGLDisplay, EGLint name);
|
||||
typedef const GLubyte* (GLAPIENTRY * pfnQueryString)(EGLDisplay, EGLint name);
|
||||
pfnQueryString fQueryString;
|
||||
typedef EGLBoolean (*pfnBindTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnBindTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
pfnBindTexImage fBindTexImage;
|
||||
typedef EGLBoolean (*pfnReleaseTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnReleaseTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
pfnReleaseTexImage fReleaseTexImage;
|
||||
typedef EGLImageKHR (*pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
typedef EGLImageKHR (GLAPIENTRY * pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
pfnCreateImageKHR fCreateImageKHR;
|
||||
typedef EGLBoolean (*pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image);
|
||||
pfnDestroyImageKHR fDestroyImageKHR;
|
||||
// This is EGL specific GL ext symbol "glEGLImageTargetTexture2DOES"
|
||||
// Lets keep it here for now.
|
||||
typedef void (*pfnImageTargetTexture2DOES)(GLenum target, GLeglImageOES image);
|
||||
typedef void (GLAPIENTRY * pfnImageTargetTexture2DOES)(GLenum target, GLeglImageOES image);
|
||||
pfnImageTargetTexture2DOES fImageTargetTexture2DOES;
|
||||
|
||||
PRBool EnsureInitialized()
|
||||
|
@ -207,6 +263,43 @@ public:
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
// ANGLE is an addon currently, so we have to do a bit of work
|
||||
// to find the directory; the addon sets this on startup/shutdown.
|
||||
do {
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService("@mozilla.org/preferences-service;1");
|
||||
nsCOMPtr<nsILocalFile> angleFile, glesv2File;
|
||||
if (!prefs)
|
||||
break;
|
||||
|
||||
nsresult rv = prefs->GetComplexValue("gfx.angle.egl.path",
|
||||
NS_GET_IID(nsILocalFile),
|
||||
getter_AddRefs(angleFile));
|
||||
if (NS_FAILED(rv) || !angleFile)
|
||||
break;
|
||||
|
||||
nsCAutoString s;
|
||||
|
||||
// note that we have to load the libs in this order, because libEGL.dll
|
||||
// depends on libGLESv2.dll, but is not in our search path.
|
||||
nsCOMPtr<nsIFile> f;
|
||||
angleFile->Clone(getter_AddRefs(f));
|
||||
glesv2File = do_QueryInterface(f);
|
||||
if (!glesv2File)
|
||||
break;
|
||||
|
||||
glesv2File->Append(NS_LITERAL_STRING("libGLESv2.dll"));
|
||||
|
||||
PRLibrary *glesv2lib = nsnull; // this will be leaked on purpose
|
||||
glesv2File->Load(&glesv2lib);
|
||||
if (!glesv2lib)
|
||||
break;
|
||||
|
||||
angleFile->Append(NS_LITERAL_STRING("libEGL.dll"));
|
||||
angleFile->Load(&mEGLLibrary);
|
||||
} while (false);
|
||||
#endif
|
||||
|
||||
if (!mEGLLibrary) {
|
||||
mEGLLibrary = PR_LoadLibrary(EGL_LIB);
|
||||
if (!mEGLLibrary) {
|
||||
|
@ -253,6 +346,11 @@ public:
|
|||
return PR_FALSE;
|
||||
|
||||
const char *extensions = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
|
||||
if (!extensions)
|
||||
extensions = "";
|
||||
|
||||
printf_stderr("Extensions: %s 0x%02x\n", extensions, extensions[0]);
|
||||
printf_stderr("Extensions length: %d\n", strlen(extensions));
|
||||
|
||||
// note the extra space -- this ugliness tries to match
|
||||
// EGL_KHR_image in the middle of the string, or right at the
|
||||
|
@ -406,10 +504,21 @@ public:
|
|||
, mThebesSurface(nsnull)
|
||||
, mBound(PR_FALSE)
|
||||
, mIsPBuffer(PR_FALSE)
|
||||
{}
|
||||
#ifdef XP_WIN
|
||||
, mWnd(0)
|
||||
#endif
|
||||
{
|
||||
// any EGL contexts will always be GLESv2
|
||||
SetIsGLES2(PR_TRUE);
|
||||
}
|
||||
|
||||
~GLContextEGL()
|
||||
{
|
||||
if (mOffscreenFBO) {
|
||||
MakeCurrent();
|
||||
DeleteOffscreenFBO();
|
||||
}
|
||||
|
||||
// If mGLWidget is non-null, then we've been given it by the GL context provider,
|
||||
// and it's managed by the widget implementation. In this case, We can't destroy
|
||||
// our contexts.
|
||||
|
@ -559,6 +668,15 @@ public:
|
|||
CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat);
|
||||
|
||||
#ifdef XP_WIN
|
||||
static already_AddRefed<GLContextEGL>
|
||||
CreateEGLWin32OffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat);
|
||||
|
||||
void HoldWin32Window(HWND aWnd) { mWnd = aWnd; }
|
||||
HWND GetWin32Window() { return mWnd; }
|
||||
#endif
|
||||
|
||||
void SetOffscreenSize(const gfxIntSize &aRequestedSize,
|
||||
const gfxIntSize &aActualSize)
|
||||
{
|
||||
|
@ -577,6 +695,10 @@ protected:
|
|||
PRBool mBound;
|
||||
|
||||
PRPackedBool mIsPBuffer;
|
||||
|
||||
#ifdef XP_WIN
|
||||
AutoDestroyHWND mWnd;
|
||||
#endif
|
||||
};
|
||||
|
||||
PRBool
|
||||
|
@ -1167,6 +1289,95 @@ GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& aSize,
|
|||
return glContext.forget();
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
already_AddRefed<GLContextEGL>
|
||||
GLContextEGL::CreateEGLWin32OffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
if (!sEGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
WNDCLASSW wc;
|
||||
if (!GetClassInfoW(GetModuleHandle(NULL), L"ANGLEContextClass", &wc)) {
|
||||
ZeroMemory(&wc, sizeof(WNDCLASSW));
|
||||
wc.style = CS_OWNDC;
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.lpszClassName = L"ANGLEContextClass";
|
||||
if (!RegisterClassW(&wc)) {
|
||||
NS_WARNING("Failed to register ANGLEContextClass?!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
AutoDestroyHWND wnd = CreateWindowW(L"ANGLEContextClass", L"ANGLEContext", 0,
|
||||
0, 0, 16, 16,
|
||||
NULL, NULL, GetModuleHandle(NULL), NULL);
|
||||
NS_ENSURE_TRUE(HWND(wnd), NULL);
|
||||
|
||||
EGLConfig config;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
|
||||
// We don't really care, we're going to use a FBO anyway
|
||||
EGLint attribs[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
|
||||
EGLint ncfg = 1;
|
||||
if (!sEGLLibrary.fChooseConfig(sEGLLibrary.Display(), attribs, &config, ncfg, &ncfg) ||
|
||||
ncfg < 1)
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
surface = sEGLLibrary.fCreateWindowSurface(sEGLLibrary.Display(),
|
||||
config,
|
||||
HWND(wnd),
|
||||
0);
|
||||
if (!surface) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API)) {
|
||||
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
EGLint cxattribs[] = {
|
||||
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
context = sEGLLibrary.fCreateContext(sEGLLibrary.Display(),
|
||||
config,
|
||||
EGL_NO_CONTEXT,
|
||||
cxattribs);
|
||||
if (!context) {
|
||||
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextEGL> glContext = new GLContextEGL(aFormat, nsnull,
|
||||
config, surface, context,
|
||||
PR_TRUE);
|
||||
|
||||
// hold this even before we initialize, because we need to make
|
||||
// sure it gets destroyed after the surface etc. in case of error.
|
||||
glContext->HoldWin32Window(wnd.forget());
|
||||
|
||||
if (!glContext->Init() ||
|
||||
!glContext->ResizeOffscreenFBO(aSize))
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Under EGL, if we're under X11, then we have to create a Pixmap
|
||||
// because Maemo's EGL implementation doesn't support pbuffers at all
|
||||
// for some reason. On Android, pbuffers are supported fine, though
|
||||
|
@ -1183,6 +1394,8 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
return GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, aFormat);
|
||||
#elif defined(MOZ_X11)
|
||||
return GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, aFormat);
|
||||
#elif defined(XP_WIN)
|
||||
return GLContextEGL::CreateEGLWin32OffscreenContext(aSize, aFormat);
|
||||
#else
|
||||
return nsnull;
|
||||
#endif
|
||||
|
@ -1291,6 +1504,8 @@ GLContextProviderEGL::GetGlobalContext()
|
|||
if (!triedToCreateContext && !gGlobalContext) {
|
||||
triedToCreateContext = true;
|
||||
gGlobalContext = CreateOffscreen(gfxIntSize(16, 16));
|
||||
if (gGlobalContext)
|
||||
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
|
|
|
@ -225,6 +225,11 @@ TRY_AGAIN_NO_SHARING:
|
|||
|
||||
~GLContextGLX()
|
||||
{
|
||||
if (mOffscreenFBO) {
|
||||
MakeCurrent();
|
||||
DeleteOffscreenFBO();
|
||||
}
|
||||
|
||||
sGLXLibrary.xDeleteContext(mDisplay, mContext);
|
||||
|
||||
if (mDeleteDrawable) {
|
||||
|
@ -287,34 +292,6 @@ TRY_AGAIN_NO_SHARING:
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void WindowDestroyed()
|
||||
{
|
||||
for (unsigned int i=0; i<textures.Length(); i++) {
|
||||
GLContext::DestroyTexture(textures.ElementAt(i));
|
||||
}
|
||||
textures.Clear();
|
||||
}
|
||||
|
||||
// NB: we could set a flag upon WindowDestroyed() to dictate an
|
||||
// early-return from CreateTexture(), but then we would need the
|
||||
// same check before all GL calls, and that heads down a rabbit
|
||||
// hole.
|
||||
virtual GLuint CreateTexture()
|
||||
{
|
||||
GLuint tex = GLContext::CreateTexture();
|
||||
NS_ASSERTION(!textures.Contains(tex), "");
|
||||
textures.AppendElement(tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
virtual void DestroyTexture(GLuint texture)
|
||||
{
|
||||
if (textures.Contains(texture)) {
|
||||
textures.RemoveElement(texture);
|
||||
GLContext::DestroyTexture(texture);
|
||||
}
|
||||
}
|
||||
|
||||
virtual already_AddRefed<TextureImage>
|
||||
CreateBasicTextureImage(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
|
@ -347,7 +324,6 @@ private:
|
|||
PRPackedBool mDeleteDrawable;
|
||||
PRPackedBool mDoubleBuffered;
|
||||
|
||||
nsTArray<GLuint> textures;
|
||||
nsRefPtr<gfxXlibSurface> mPixmap;
|
||||
};
|
||||
|
||||
|
@ -740,6 +716,8 @@ GLContextProviderGLX::GetGlobalContext()
|
|||
gGlobalContext = CreateOffscreenPixmapContext(gfxIntSize(1, 1),
|
||||
ContextFormat(ContextFormat::BasicRGB24),
|
||||
PR_FALSE);
|
||||
if (gGlobalContext)
|
||||
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
|
|
|
@ -87,6 +87,10 @@ CreateDummyWindow(HDC *aWindowDC = nsnull)
|
|||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 24;
|
||||
pfd.cRedBits = 8;
|
||||
pfd.cGreenBits = 8;
|
||||
pfd.cBlueBits = 8;
|
||||
pfd.cAlphaBits = 8;
|
||||
pfd.cDepthBits = 0;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
|
||||
|
@ -688,6 +692,8 @@ GLContextProviderWGL::GetGlobalContext()
|
|||
gGlobalContext = nsnull;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
|
||||
}
|
||||
|
||||
return static_cast<GLContext*>(gGlobalContext);
|
||||
|
|
|
@ -116,6 +116,15 @@ public:
|
|||
GLXContext,
|
||||
Bool);
|
||||
PFNGLXCREATECONTEXT xCreateContext;
|
||||
typedef int (GLAPIENTRY * PFNGLXGETCONFIG) (Display *,
|
||||
XVisualInfo *,
|
||||
int,
|
||||
int *);
|
||||
PFNGLXGETCONFIG xGetConfig;
|
||||
typedef GLXPixmap (GLAPIENTRY * PFNGLXCREATEGLXPIXMAP) (Display *,
|
||||
XVisualInfo *,
|
||||
Pixmap);
|
||||
PFNGLXCREATEGLXPIXMAP xCreateGLXPixmap;
|
||||
|
||||
PRBool EnsureInitialized();
|
||||
|
||||
|
|
|
@ -414,6 +414,11 @@ else
|
|||
CPPSRCS += GLContextProvider$(GL_PROVIDER).cpp
|
||||
endif
|
||||
|
||||
# Win32 is a special snowflake, for ANGLE
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
CPPSRCS += GLContextProviderEGL.cpp
|
||||
endif
|
||||
|
||||
DEFINES += -DIMPL_THEBES -DWOFF_MOZILLA_CLIENT
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -500,9 +500,10 @@ PRBool gfxOS2Font::SetupCairoFont(gfxContext *aContext)
|
|||
already_AddRefed<gfxOS2Font> gfxOS2Font::GetOrMakeFont(const nsAString& aName,
|
||||
const gfxFontStyle *aStyle)
|
||||
{
|
||||
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aName, aStyle);
|
||||
nsRefPtr<gfxOS2FontEntry> fe = new gfxOS2FontEntry(aName);
|
||||
nsRefPtr<gfxFont> font =
|
||||
gfxFontCache::GetCache()->Lookup(static_cast<gfxFontEntry *>(fe), aStyle);
|
||||
if (!font) {
|
||||
nsRefPtr<gfxOS2FontEntry> fe = new gfxOS2FontEntry(aName);
|
||||
font = new gfxOS2Font(fe, aStyle);
|
||||
if (!font)
|
||||
return nsnull;
|
||||
|
|
|
@ -43,13 +43,17 @@
|
|||
* separately to take advantage of the simple switch-case constant propagation
|
||||
* done by SpiderMonkey.
|
||||
*/
|
||||
Narcissus = {};
|
||||
|
||||
Narcissus = {
|
||||
options: { version: 185 }
|
||||
};
|
||||
|
||||
Narcissus.jsdefs = (function() {
|
||||
|
||||
var tokens = [
|
||||
// End of source.
|
||||
"END",
|
||||
|
||||
|
||||
// Operators and punctuators. Some pair-wise order matters, e.g. (+, -)
|
||||
// and (UNARY_PLUS, UNARY_MINUS).
|
||||
"\n", ";",
|
||||
|
@ -72,15 +76,15 @@ Narcissus.jsdefs = (function() {
|
|||
"[", "]",
|
||||
"{", "}",
|
||||
"(", ")",
|
||||
|
||||
|
||||
// Nonterminal tree node type codes.
|
||||
"SCRIPT", "BLOCK", "LABEL", "FOR_IN", "CALL", "NEW_WITH_ARGS", "INDEX",
|
||||
"ARRAY_INIT", "OBJECT_INIT", "PROPERTY_INIT", "GETTER", "SETTER",
|
||||
"GROUP", "LIST", "LET_BLOCK", "ARRAY_COMP", "GENERATOR", "COMP_TAIL",
|
||||
|
||||
|
||||
// Terminals.
|
||||
"IDENTIFIER", "NUMBER", "STRING", "REGEXP",
|
||||
|
||||
|
||||
// Keywords.
|
||||
"break",
|
||||
"case", "catch", "const", "continue",
|
||||
|
@ -97,7 +101,7 @@ Narcissus.jsdefs = (function() {
|
|||
"yield",
|
||||
"while", "with",
|
||||
];
|
||||
|
||||
|
||||
// Operator and punctuator mapping from token to tree node type name.
|
||||
// NB: because the lexer doesn't backtrack, all token prefixes must themselves
|
||||
// be valid tokens (e.g. !== is acceptable because its prefixes are the valid
|
||||
|
@ -142,14 +146,14 @@ Narcissus.jsdefs = (function() {
|
|||
'(': "LEFT_PAREN",
|
||||
')': "RIGHT_PAREN"
|
||||
};
|
||||
|
||||
|
||||
// Hash of keyword identifier to tokens index. NB: we must null __proto__ to
|
||||
// avoid toString, etc. namespace pollution.
|
||||
var keywords = {__proto__: null};
|
||||
|
||||
|
||||
// Define const END, etc., based on the token names. Also map name to index.
|
||||
var tokenIds = {};
|
||||
|
||||
|
||||
// Building up a string to be eval'd in different contexts.
|
||||
var consts = "const ";
|
||||
for (var i = 0, j = tokens.length; i < j; i++) {
|
||||
|
@ -168,23 +172,23 @@ Narcissus.jsdefs = (function() {
|
|||
tokens[t] = i;
|
||||
}
|
||||
consts += ";";
|
||||
|
||||
|
||||
// Map assignment operators to their indexes in the tokens array.
|
||||
var assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%'];
|
||||
|
||||
|
||||
for (i = 0, j = assignOps.length; i < j; i++) {
|
||||
t = assignOps[i];
|
||||
assignOps[t] = tokens[t];
|
||||
}
|
||||
|
||||
|
||||
function defineGetter(obj, prop, fn, dontDelete, dontEnum) {
|
||||
Object.defineProperty(obj, prop, { get: fn, configurable: !dontDelete, enumerable: !dontEnum });
|
||||
}
|
||||
|
||||
|
||||
function defineProperty(obj, prop, val, dontDelete, readOnly, dontEnum) {
|
||||
Object.defineProperty(obj, prop, { value: val, writable: !readOnly, configurable: !dontDelete, enumerable: !dontEnum });
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
"tokens": tokens,
|
||||
"opTypeNames": opTypeNames,
|
||||
|
|
|
@ -52,25 +52,25 @@ Narcissus.jsexec = (function() {
|
|||
|
||||
var jsparse = Narcissus.jsparse;
|
||||
var jsdefs = Narcissus.jsdefs;
|
||||
|
||||
|
||||
// Set constants in the local scope.
|
||||
eval(jsdefs.consts);
|
||||
|
||||
|
||||
const GLOBAL_CODE = 0, EVAL_CODE = 1, FUNCTION_CODE = 2;
|
||||
|
||||
|
||||
function ExecutionContext(type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
var global = {
|
||||
// Value properties.
|
||||
NaN: NaN, Infinity: Infinity, undefined: undefined,
|
||||
|
||||
|
||||
// Function properties.
|
||||
eval: function eval(s) {
|
||||
if (typeof s != "string")
|
||||
return s;
|
||||
|
||||
|
||||
var x = ExecutionContext.current;
|
||||
var x2 = new ExecutionContext(EVAL_CODE);
|
||||
x2.thisObject = x.thisObject;
|
||||
|
@ -110,7 +110,7 @@ Narcissus.jsexec = (function() {
|
|||
decodeURI: decodeURI, encodeURI: encodeURI,
|
||||
decodeURIComponent: decodeURIComponent,
|
||||
encodeURIComponent: encodeURIComponent,
|
||||
|
||||
|
||||
// Class constructors. Where ECMA-262 requires C.length == 1, we declare
|
||||
// a dummy formal parameter.
|
||||
Object: Object,
|
||||
|
@ -125,11 +125,11 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
b += arguments[m];
|
||||
}
|
||||
|
||||
|
||||
// XXX We want to pass a good file and line to the tokenizer.
|
||||
// Note the anonymous name to maintain parity with Spidermonkey.
|
||||
var t = new jsparse.Tokenizer("anonymous(" + p + ") {" + b + "}");
|
||||
|
||||
|
||||
// NB: Use the STATEMENT_FORM constant since we don't want to push this
|
||||
// function onto the fake compilation context.
|
||||
var x = { builder: new jsparse.VanillaBuilder };
|
||||
|
@ -156,27 +156,28 @@ Narcissus.jsexec = (function() {
|
|||
Error: Error, EvalError: EvalError, RangeError: RangeError,
|
||||
ReferenceError: ReferenceError, SyntaxError: SyntaxError,
|
||||
TypeError: TypeError, URIError: URIError,
|
||||
|
||||
|
||||
// Other properties.
|
||||
Math: Math,
|
||||
|
||||
|
||||
// Extensions to ECMA.
|
||||
snarf: snarf, evaluate: evaluate,
|
||||
load: function load(s) {
|
||||
if (typeof s != "string")
|
||||
return s;
|
||||
|
||||
|
||||
evaluate(snarf(s), s, 1)
|
||||
},
|
||||
print: print,
|
||||
version: function() { return 185; }
|
||||
version: function() { return Narcissus.options.version; },
|
||||
quit: function() { throw END; }
|
||||
};
|
||||
|
||||
|
||||
// Helper to avoid Object.prototype.hasOwnProperty polluting scope objects.
|
||||
function hasDirectProperty(o, p) {
|
||||
return Object.prototype.hasOwnProperty.call(o, p);
|
||||
}
|
||||
|
||||
|
||||
// Reflect a host class into the target global environment by delegation.
|
||||
function reflectClass(name, proto) {
|
||||
var gctor = global[name];
|
||||
|
@ -184,19 +185,19 @@ Narcissus.jsexec = (function() {
|
|||
jsdefs.defineProperty(proto, "constructor", gctor, false, false, true);
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
||||
// Reflect Array -- note that all Array methods are generic.
|
||||
reflectClass('Array', new Array);
|
||||
|
||||
|
||||
// Reflect String, overriding non-generic methods.
|
||||
var gSp = reflectClass('String', new String);
|
||||
gSp.toSource = function () { return this.value.toSource(); };
|
||||
gSp.toString = function () { return this.value; };
|
||||
gSp.valueOf = function () { return this.value; };
|
||||
global.String.fromCharCode = String.fromCharCode;
|
||||
|
||||
|
||||
ExecutionContext.current = null;
|
||||
|
||||
|
||||
ExecutionContext.prototype = {
|
||||
caller: null,
|
||||
callee: null,
|
||||
|
@ -204,17 +205,34 @@ Narcissus.jsexec = (function() {
|
|||
thisObject: global,
|
||||
result: undefined,
|
||||
target: null,
|
||||
ecma3OnlyMode: false
|
||||
ecma3OnlyMode: false,
|
||||
// Run a thunk in this execution context and return its result.
|
||||
run: function(thunk) {
|
||||
var prev = ExecutionContext.current;
|
||||
ExecutionContext.current = this;
|
||||
try {
|
||||
thunk();
|
||||
return this.result;
|
||||
} catch (e if e == THROW) {
|
||||
if (prev) {
|
||||
prev.result = this.result;
|
||||
throw THROW;
|
||||
}
|
||||
throw this.result;
|
||||
} finally {
|
||||
ExecutionContext.current = prev;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function Reference(base, propertyName, node) {
|
||||
this.base = base;
|
||||
this.propertyName = propertyName;
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
|
||||
Reference.prototype.toString = function () { return this.node.getSource(); }
|
||||
|
||||
|
||||
function getValue(v) {
|
||||
if (v instanceof Reference) {
|
||||
if (!v.base) {
|
||||
|
@ -225,24 +243,24 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
function putValue(v, w, vn) {
|
||||
if (v instanceof Reference)
|
||||
return (v.base || global)[v.propertyName] = w;
|
||||
throw new ReferenceError("Invalid assignment left-hand side",
|
||||
vn.filename, vn.lineno);
|
||||
}
|
||||
|
||||
|
||||
function isPrimitive(v) {
|
||||
var t = typeof v;
|
||||
return (t == "object") ? v === null : t != "function";
|
||||
}
|
||||
|
||||
|
||||
function isObject(v) {
|
||||
var t = typeof v;
|
||||
return (t == "object") ? v !== null : t == "function";
|
||||
}
|
||||
|
||||
|
||||
// If r instanceof Reference, v == getValue(r); else v === r. If passed, rn
|
||||
// is the node whose execute result was r.
|
||||
function toObject(v, r, rn) {
|
||||
|
@ -263,10 +281,10 @@ Narcissus.jsexec = (function() {
|
|||
throw rn ? new TypeError(message, rn.filename, rn.lineno)
|
||||
: new TypeError(message);
|
||||
}
|
||||
|
||||
|
||||
function execute(n, x) {
|
||||
var a, f, i, j, r, s, t, u, v;
|
||||
|
||||
|
||||
switch (n.type) {
|
||||
case FUNCTION:
|
||||
if (n.functionForm != jsparse.DECLARED_FORM) {
|
||||
|
@ -286,7 +304,7 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case SCRIPT:
|
||||
t = x.scope.object;
|
||||
a = n.funDecls;
|
||||
|
@ -308,19 +326,19 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
}
|
||||
// FALL THROUGH
|
||||
|
||||
|
||||
case BLOCK:
|
||||
for (i = 0, j = n.length; i < j; i++)
|
||||
execute(n[i], x);
|
||||
break;
|
||||
|
||||
|
||||
case IF:
|
||||
if (getValue(execute(n.condition, x)))
|
||||
execute(n.thenPart, x);
|
||||
else if (n.elsePart)
|
||||
execute(n.elsePart, x);
|
||||
break;
|
||||
|
||||
|
||||
case SWITCH:
|
||||
s = getValue(execute(n.discriminant, x));
|
||||
a = n.cases;
|
||||
|
@ -360,7 +378,7 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FOR:
|
||||
n.setup && getValue(execute(n.setup, x));
|
||||
// FALL THROUGH
|
||||
|
@ -376,7 +394,7 @@ Narcissus.jsexec = (function() {
|
|||
n.update && getValue(execute(n.update, x));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FOR_IN:
|
||||
u = n.varDecl;
|
||||
if (u)
|
||||
|
@ -384,7 +402,7 @@ Narcissus.jsexec = (function() {
|
|||
r = n.iterator;
|
||||
s = execute(n.object, x);
|
||||
v = getValue(s);
|
||||
|
||||
|
||||
// ECMA deviation to track extant browser JS implementation behavior.
|
||||
t = (v == null && !x.ecma3OnlyMode) ? v : toObject(v, s, n.object);
|
||||
a = [];
|
||||
|
@ -401,7 +419,7 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case DO:
|
||||
do {
|
||||
try {
|
||||
|
@ -413,12 +431,12 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
} while (getValue(execute(n.condition, x)));
|
||||
break;
|
||||
|
||||
|
||||
case BREAK:
|
||||
case CONTINUE:
|
||||
x.target = n.target;
|
||||
throw n.type;
|
||||
|
||||
|
||||
case TRY:
|
||||
try {
|
||||
execute(n.tryBlock, x);
|
||||
|
@ -447,15 +465,15 @@ Narcissus.jsexec = (function() {
|
|||
execute(n.finallyBlock, x);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case THROW:
|
||||
x.result = getValue(execute(n.exception, x));
|
||||
throw THROW;
|
||||
|
||||
|
||||
case RETURN:
|
||||
x.result = getValue(execute(n.value, x));
|
||||
throw RETURN;
|
||||
|
||||
|
||||
case WITH:
|
||||
r = execute(n.object, x);
|
||||
t = toObject(getValue(r), r, n.object);
|
||||
|
@ -466,7 +484,7 @@ Narcissus.jsexec = (function() {
|
|||
x.scope = x.scope.parent;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case VAR:
|
||||
case CONST:
|
||||
for (i = 0, j = n.length; i < j; i++) {
|
||||
|
@ -485,27 +503,27 @@ Narcissus.jsexec = (function() {
|
|||
s.object[t] = u;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case DEBUGGER:
|
||||
throw "NYI: " + jsdefs.tokens[n.type];
|
||||
|
||||
|
||||
case SEMICOLON:
|
||||
if (n.expression)
|
||||
x.result = getValue(execute(n.expression, x));
|
||||
break;
|
||||
|
||||
|
||||
case LABEL:
|
||||
try {
|
||||
execute(n.statement, x);
|
||||
} catch (e if e == BREAK && x.target == n) {
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case COMMA:
|
||||
for (i = 0, j = n.length; i < j; i++)
|
||||
v = getValue(execute(n[i], x));
|
||||
break;
|
||||
|
||||
|
||||
case ASSIGN:
|
||||
r = execute(n[0], x);
|
||||
t = n.assignOp;
|
||||
|
@ -529,68 +547,68 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
putValue(r, v, n[0]);
|
||||
break;
|
||||
|
||||
|
||||
case HOOK:
|
||||
v = getValue(execute(n[0], x)) ? getValue(execute(n[1], x))
|
||||
: getValue(execute(n[2], x));
|
||||
break;
|
||||
|
||||
|
||||
case OR:
|
||||
v = getValue(execute(n[0], x)) || getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case AND:
|
||||
v = getValue(execute(n[0], x)) && getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case BITWISE_OR:
|
||||
v = getValue(execute(n[0], x)) | getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case BITWISE_XOR:
|
||||
v = getValue(execute(n[0], x)) ^ getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case BITWISE_AND:
|
||||
v = getValue(execute(n[0], x)) & getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case EQ:
|
||||
v = getValue(execute(n[0], x)) == getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case NE:
|
||||
v = getValue(execute(n[0], x)) != getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case STRICT_EQ:
|
||||
v = getValue(execute(n[0], x)) === getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case STRICT_NE:
|
||||
v = getValue(execute(n[0], x)) !== getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case LT:
|
||||
v = getValue(execute(n[0], x)) < getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case LE:
|
||||
v = getValue(execute(n[0], x)) <= getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case GE:
|
||||
v = getValue(execute(n[0], x)) >= getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case GT:
|
||||
v = getValue(execute(n[0], x)) > getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case IN:
|
||||
v = getValue(execute(n[0], x)) in getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case INSTANCEOF:
|
||||
t = getValue(execute(n[0], x));
|
||||
u = getValue(execute(n[1], x));
|
||||
|
@ -599,71 +617,71 @@ Narcissus.jsexec = (function() {
|
|||
else
|
||||
v = t instanceof u;
|
||||
break;
|
||||
|
||||
|
||||
case LSH:
|
||||
v = getValue(execute(n[0], x)) << getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case RSH:
|
||||
v = getValue(execute(n[0], x)) >> getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case URSH:
|
||||
v = getValue(execute(n[0], x)) >>> getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case PLUS:
|
||||
v = getValue(execute(n[0], x)) + getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case MINUS:
|
||||
v = getValue(execute(n[0], x)) - getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case MUL:
|
||||
v = getValue(execute(n[0], x)) * getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case DIV:
|
||||
v = getValue(execute(n[0], x)) / getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case MOD:
|
||||
v = getValue(execute(n[0], x)) % getValue(execute(n[1], x));
|
||||
break;
|
||||
|
||||
|
||||
case DELETE:
|
||||
t = execute(n[0], x);
|
||||
v = !(t instanceof Reference) || delete t.base[t.propertyName];
|
||||
break;
|
||||
|
||||
|
||||
case VOID:
|
||||
getValue(execute(n[0], x));
|
||||
break;
|
||||
|
||||
|
||||
case TYPEOF:
|
||||
t = execute(n[0], x);
|
||||
if (t instanceof Reference)
|
||||
t = t.base ? t.base[t.propertyName] : undefined;
|
||||
v = typeof t;
|
||||
break;
|
||||
|
||||
|
||||
case NOT:
|
||||
v = !getValue(execute(n[0], x));
|
||||
break;
|
||||
|
||||
|
||||
case BITWISE_NOT:
|
||||
v = ~getValue(execute(n[0], x));
|
||||
break;
|
||||
|
||||
|
||||
case UNARY_PLUS:
|
||||
v = +getValue(execute(n[0], x));
|
||||
break;
|
||||
|
||||
|
||||
case UNARY_MINUS:
|
||||
v = -getValue(execute(n[0], x));
|
||||
break;
|
||||
|
||||
|
||||
case INCREMENT:
|
||||
case DECREMENT:
|
||||
t = execute(n[0], x);
|
||||
|
@ -674,21 +692,21 @@ Narcissus.jsexec = (function() {
|
|||
if (!n.postfix)
|
||||
v = u;
|
||||
break;
|
||||
|
||||
|
||||
case DOT:
|
||||
r = execute(n[0], x);
|
||||
t = getValue(r);
|
||||
u = n[1].value;
|
||||
v = new Reference(toObject(t, r, n[0]), u, n);
|
||||
break;
|
||||
|
||||
|
||||
case INDEX:
|
||||
r = execute(n[0], x);
|
||||
t = getValue(r);
|
||||
u = getValue(execute(n[1], x));
|
||||
v = new Reference(toObject(t, r, n[0]), String(u), n);
|
||||
break;
|
||||
|
||||
|
||||
case LIST:
|
||||
// Curse ECMA for specifying that arguments is not an Array object!
|
||||
v = {};
|
||||
|
@ -698,7 +716,7 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
jsdefs.defineProperty(v, "length", i, false, false, true);
|
||||
break;
|
||||
|
||||
|
||||
case CALL:
|
||||
r = execute(n[0], x);
|
||||
a = execute(n[1], x);
|
||||
|
@ -712,7 +730,7 @@ Narcissus.jsexec = (function() {
|
|||
t = null;
|
||||
v = f.__call__(t, a, x);
|
||||
break;
|
||||
|
||||
|
||||
case NEW:
|
||||
case NEW_WITH_ARGS:
|
||||
r = execute(n[0], x);
|
||||
|
@ -729,7 +747,7 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
v = f.__construct__(a, x);
|
||||
break;
|
||||
|
||||
|
||||
case ARRAY_INIT:
|
||||
v = [];
|
||||
for (i = 0, j = n.length; i < j; i++) {
|
||||
|
@ -738,7 +756,7 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
v.length = j;
|
||||
break;
|
||||
|
||||
|
||||
case OBJECT_INIT:
|
||||
v = {};
|
||||
for (i = 0, j = n.length; i < j; i++) {
|
||||
|
@ -753,23 +771,23 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case NULL:
|
||||
v = null;
|
||||
break;
|
||||
|
||||
|
||||
case THIS:
|
||||
v = x.thisObject;
|
||||
break;
|
||||
|
||||
|
||||
case TRUE:
|
||||
v = true;
|
||||
break;
|
||||
|
||||
|
||||
case FALSE:
|
||||
v = false;
|
||||
break;
|
||||
|
||||
|
||||
case IDENTIFIER:
|
||||
for (s = x.scope; s; s = s.parent) {
|
||||
if (n.value in s.object)
|
||||
|
@ -777,37 +795,37 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
v = new Reference(s && s.object, n.value, n);
|
||||
break;
|
||||
|
||||
|
||||
case NUMBER:
|
||||
case STRING:
|
||||
case REGEXP:
|
||||
v = n.value;
|
||||
break;
|
||||
|
||||
|
||||
case GROUP:
|
||||
v = execute(n[0], x);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
throw "PANIC: unknown operation " + n.type + ": " + uneval(n);
|
||||
}
|
||||
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
function Activation(f, a) {
|
||||
for (var i = 0, j = f.params.length; i < j; i++)
|
||||
jsdefs.defineProperty(this, f.params[i], a[i], true);
|
||||
jsdefs.defineProperty(this, "arguments", a, true);
|
||||
}
|
||||
|
||||
|
||||
// Null Activation.prototype's proto slot so that Object.prototype.* does not
|
||||
// pollute the scope of heavyweight functions. Also delete its 'constructor'
|
||||
// property so that it doesn't pollute function scopes.
|
||||
|
||||
|
||||
Activation.prototype.__proto__ = null;
|
||||
delete Activation.prototype.constructor;
|
||||
|
||||
|
||||
function FunctionObject(node, scope) {
|
||||
this.node = node;
|
||||
this.scope = scope;
|
||||
|
@ -816,65 +834,80 @@ Narcissus.jsexec = (function() {
|
|||
jsdefs.defineProperty(this, "prototype", proto, true);
|
||||
jsdefs.defineProperty(proto, "constructor", this, false, false, true);
|
||||
}
|
||||
|
||||
|
||||
function getPropertyDescriptor(obj, name) {
|
||||
while (obj) {
|
||||
if (({}).hasOwnProperty.call(obj, name))
|
||||
return Object.getOwnPropertyDescriptor(obj, name);
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
}
|
||||
}
|
||||
|
||||
function getOwnProperties(obj) {
|
||||
var map = {};
|
||||
for (var name in Object.getOwnPropertyNames(obj))
|
||||
map[name] = Object.getOwnPropertyDescriptor(obj, name);
|
||||
return map;
|
||||
}
|
||||
|
||||
// Returns a new function wrapped with a Proxy.
|
||||
function newFunction(n,x) {
|
||||
var f = new FunctionObject(n, x.scope);
|
||||
var p = Proxy.createFunction(
|
||||
|
||||
// Handler function copied from
|
||||
// http://wiki.ecmascript.org/doku.php?id=harmony:proxies&s=proxy%20object#examplea_no-op_forwarding_proxy
|
||||
function(obj) { return {
|
||||
getOwnPropertyDescriptor: function(name) {
|
||||
var desc = Object.getOwnPropertyDescriptor(obj);
|
||||
|
||||
// a trapping proxy's properties must always be configurable
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
},
|
||||
getPropertyDescriptor: function(name) {
|
||||
var desc = Object.getPropertyDescriptor(obj); //assumed
|
||||
|
||||
// a trapping proxy's properties must always be configurable
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
},
|
||||
getOwnPropertyNames: function() {
|
||||
return Object.getOwnPropertyNames(obj);
|
||||
},
|
||||
defineProperty: function(name, desc) {
|
||||
Object.defineProperty(obj, name, desc);
|
||||
},
|
||||
delete: function(name) { return delete obj[name]; },
|
||||
fix: function() {
|
||||
if (Object.isFrozen(obj)) {
|
||||
return Object.getOwnProperties(obj); // assumed
|
||||
}
|
||||
|
||||
// As long as obj is not frozen, the proxy won't allow itself to be fixed.
|
||||
return undefined; // will cause a TypeError to be thrown
|
||||
},
|
||||
|
||||
has: function(name) { return name in obj; },
|
||||
hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
|
||||
get: function(receiver, name) { return obj[name]; },
|
||||
|
||||
// bad behavior when set fails in non-strict mode
|
||||
set: function(receiver, name, val) { obj[name] = val; return true; },
|
||||
enumerate: function() {
|
||||
var result = [];
|
||||
for (name in obj) { result.push(name); };
|
||||
return result;
|
||||
},
|
||||
enumerateOwn: function() { return Object.keys(obj); } };
|
||||
}(f),
|
||||
function() { return f.__call__(this, arguments, x); },
|
||||
function() { return f.__construct__(arguments, x); });
|
||||
function newFunction(n, x) {
|
||||
var fobj = new FunctionObject(n, x.scope);
|
||||
|
||||
// Handler copied from
|
||||
// http://wiki.ecmascript.org/doku.php?id=harmony:proxies&s=proxy%20object#examplea_no-op_forwarding_proxy
|
||||
var handler = {
|
||||
getOwnPropertyDescriptor: function(name) {
|
||||
var desc = Object.getOwnPropertyDescriptor(fobj, name);
|
||||
|
||||
// a trapping proxy's properties must always be configurable
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
},
|
||||
getPropertyDescriptor: function(name) {
|
||||
var desc = getPropertyDescriptor(fobj, name);
|
||||
|
||||
// a trapping proxy's properties must always be configurable
|
||||
desc.configurable = true;
|
||||
return desc;
|
||||
},
|
||||
getOwnPropertyNames: function() {
|
||||
return Object.getOwnPropertyNames(fobj);
|
||||
},
|
||||
defineProperty: function(name, desc) {
|
||||
Object.defineProperty(fobj, name, desc);
|
||||
},
|
||||
delete: function(name) { return delete fobj[name]; },
|
||||
fix: function() {
|
||||
if (Object.isFrozen(fobj)) {
|
||||
return getOwnProperties(fobj);
|
||||
}
|
||||
|
||||
// As long as fobj is not frozen, the proxy won't allow itself to be fixed.
|
||||
return undefined; // will cause a TypeError to be thrown
|
||||
},
|
||||
|
||||
has: function(name) { return name in fobj; },
|
||||
hasOwn: function(name) { return ({}).hasOwnProperty.call(fobj, name); },
|
||||
get: function(receiver, name) { return fobj[name]; },
|
||||
|
||||
// bad behavior when set fails in non-strict mode
|
||||
set: function(receiver, name, val) { fobj[name] = val; return true; },
|
||||
enumerate: function() {
|
||||
var result = [];
|
||||
for (name in fobj) { result.push(name); };
|
||||
return result;
|
||||
},
|
||||
keys: function() { return Object.keys(fobj); }
|
||||
};
|
||||
var p = Proxy.createFunction(handler,
|
||||
function() { return fobj.__call__(this, arguments, x); },
|
||||
function() { return fobj.__construct__(arguments, x); });
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
var FOp = FunctionObject.prototype = {
|
||||
|
||||
|
||||
// Internal methods.
|
||||
__call__: function (t, a, x) {
|
||||
var x2 = new ExecutionContext(FUNCTION_CODE);
|
||||
|
@ -884,7 +917,7 @@ Narcissus.jsexec = (function() {
|
|||
jsdefs.defineProperty(a, "callee", this, false, false, true);
|
||||
var f = this.node;
|
||||
x2.scope = {object: new Activation(f, a), parent: this.scope};
|
||||
|
||||
|
||||
ExecutionContext.current = x2;
|
||||
try {
|
||||
execute(f.body, x2);
|
||||
|
@ -898,20 +931,20 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
|
||||
__construct__: function (a, x) {
|
||||
var o = new Object;
|
||||
var p = this.prototype;
|
||||
if (isObject(p))
|
||||
o.__proto__ = p;
|
||||
// else o.__proto__ defaulted to Object.prototype
|
||||
|
||||
|
||||
var v = this.__call__(o, a, x);
|
||||
if (isObject(v))
|
||||
return v;
|
||||
return o;
|
||||
},
|
||||
|
||||
|
||||
__hasInstance__: function (v) {
|
||||
if (isPrimitive(v))
|
||||
return false;
|
||||
|
@ -928,24 +961,24 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
// Standard methods.
|
||||
toString: function () {
|
||||
return this.node.getSource();
|
||||
},
|
||||
|
||||
|
||||
apply: function (t, a) {
|
||||
// Curse ECMA again!
|
||||
if (typeof this.__call__ != "function") {
|
||||
throw new TypeError("Function.prototype.apply called on" +
|
||||
" uncallable object");
|
||||
}
|
||||
|
||||
|
||||
if (t === undefined || t === null)
|
||||
t = global;
|
||||
else if (typeof t != "object")
|
||||
t = toObject(t, t);
|
||||
|
||||
|
||||
if (a === undefined || a === null) {
|
||||
a = {};
|
||||
jsdefs.defineProperty(a, "length", 0, false, false, true);
|
||||
|
@ -961,24 +994,24 @@ Narcissus.jsexec = (function() {
|
|||
" must be an array or arguments object",
|
||||
this.node.filename, this.node.lineno);
|
||||
}
|
||||
|
||||
|
||||
return this.__call__(t, a, ExecutionContext.current);
|
||||
},
|
||||
|
||||
|
||||
call: function (t) {
|
||||
// Curse ECMA a third time!
|
||||
var a = Array.prototype.splice.call(arguments, 1);
|
||||
return this.apply(t, a);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Connect Function.prototype and Function.prototype.constructor in global.
|
||||
reflectClass('Function', FOp);
|
||||
|
||||
|
||||
// Help native and host-scripted functions be like FunctionObjects.
|
||||
var Fp = Function.prototype;
|
||||
var REp = RegExp.prototype;
|
||||
|
||||
|
||||
if (!('__call__' in Fp)) {
|
||||
jsdefs.defineProperty(Fp, "__call__",
|
||||
function (t, a, x) {
|
||||
|
@ -1011,7 +1044,7 @@ Narcissus.jsexec = (function() {
|
|||
return eval('new this(' + argStr.slice(0,-1) + ');');
|
||||
}
|
||||
}, true, true, true);
|
||||
|
||||
|
||||
// Since we use native functions such as Date along with host ones such
|
||||
// as global.eval, we want both to be considered instances of the native
|
||||
// Function constructor.
|
||||
|
@ -1020,15 +1053,15 @@ Narcissus.jsexec = (function() {
|
|||
return v instanceof Function || v instanceof global.Function;
|
||||
}, true, true, true);
|
||||
}
|
||||
|
||||
|
||||
function thunk(f, x) {
|
||||
return function () { return f.__call__(this, arguments, x); };
|
||||
}
|
||||
|
||||
|
||||
function evaluate(s, f, l) {
|
||||
if (typeof s != "string")
|
||||
return s;
|
||||
|
||||
|
||||
var x = ExecutionContext.current;
|
||||
var x2 = new ExecutionContext(GLOBAL_CODE);
|
||||
ExecutionContext.current = x2;
|
||||
|
@ -1045,9 +1078,67 @@ Narcissus.jsexec = (function() {
|
|||
}
|
||||
return x2.result;
|
||||
}
|
||||
|
||||
|
||||
// A read-eval-print-loop that roughly tracks the behavior of the js shell.
|
||||
function repl() {
|
||||
|
||||
// Display a value similarly to the js shell.
|
||||
function display(x) {
|
||||
if (typeof x == "object") {
|
||||
// At the js shell, objects with no |toSource| don't print.
|
||||
if (x != null && "toSource" in x) {
|
||||
try {
|
||||
print(x.toSource());
|
||||
} catch (e) {
|
||||
}
|
||||
} else {
|
||||
print("null");
|
||||
}
|
||||
} else if (typeof x == "string") {
|
||||
print(uneval(x));
|
||||
} else if (typeof x != "undefined") {
|
||||
// Since x must be primitive, String can't throw.
|
||||
print(String(x));
|
||||
}
|
||||
}
|
||||
|
||||
// String conversion that never throws.
|
||||
function string(x) {
|
||||
try {
|
||||
return String(x);
|
||||
} catch (e) {
|
||||
return "unknown (can't convert to string)";
|
||||
}
|
||||
}
|
||||
|
||||
var b = new jsparse.VanillaBuilder;
|
||||
var x = new ExecutionContext(GLOBAL_CODE);
|
||||
|
||||
x.run(function() {
|
||||
for (;;) {
|
||||
putstr("njs> ");
|
||||
var line = readline();
|
||||
x.result = undefined;
|
||||
try {
|
||||
execute(jsparse.parse(b, line, "stdin", 1), x);
|
||||
display(x.result);
|
||||
} catch (e if e == THROW) {
|
||||
print("uncaught exception: " + string(x.result));
|
||||
} catch (e if e == END) {
|
||||
break;
|
||||
} catch (e if e instanceof SyntaxError) {
|
||||
print(e.toString());
|
||||
} catch (e) {
|
||||
print("internal Narcissus error");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
"evaluate": evaluate
|
||||
"evaluate": evaluate,
|
||||
"repl": repl
|
||||
};
|
||||
|
||||
}());
|
||||
|
|
|
@ -44,16 +44,16 @@
|
|||
Narcissus.jslex = (function() {
|
||||
|
||||
var jsdefs = Narcissus.jsdefs;
|
||||
|
||||
|
||||
// Set constants in the local scope.
|
||||
eval(jsdefs.consts);
|
||||
|
||||
|
||||
// Build up a trie of operator tokens.
|
||||
var opTokens = {};
|
||||
for (var op in jsdefs.opTypeNames) {
|
||||
if (op === '\n' || op === '.')
|
||||
continue;
|
||||
|
||||
|
||||
var node = opTokens;
|
||||
for (var i = 0; i < op.length; i++) {
|
||||
var ch = op[i];
|
||||
|
@ -63,7 +63,7 @@ Narcissus.jslex = (function() {
|
|||
node.op = op;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Tokenizer :: (file ptr, path, line number) -> Tokenizer
|
||||
*/
|
||||
|
@ -77,28 +77,28 @@ Narcissus.jslex = (function() {
|
|||
this.filename = f || "";
|
||||
this.lineno = l || 1;
|
||||
}
|
||||
|
||||
|
||||
Tokenizer.prototype = {
|
||||
get done() {
|
||||
// We need to set scanOperand to true here because the first thing
|
||||
// might be a regexp.
|
||||
return this.peek(true) == END;
|
||||
},
|
||||
|
||||
|
||||
get token() {
|
||||
return this.tokens[this.tokenIndex];
|
||||
},
|
||||
|
||||
|
||||
match: function (tt, scanOperand) {
|
||||
return this.get(scanOperand) == tt || this.unget();
|
||||
},
|
||||
|
||||
|
||||
mustMatch: function (tt) {
|
||||
if (!this.match(tt))
|
||||
throw this.newSyntaxError("Missing " + tokens[tt].toLowerCase());
|
||||
return this.token;
|
||||
},
|
||||
|
||||
|
||||
peek: function (scanOperand) {
|
||||
var tt, next;
|
||||
if (this.lookahead) {
|
||||
|
@ -112,14 +112,14 @@ Narcissus.jslex = (function() {
|
|||
}
|
||||
return tt;
|
||||
},
|
||||
|
||||
|
||||
peekOnSameLine: function (scanOperand) {
|
||||
this.scanNewlines = true;
|
||||
var tt = this.peek(scanOperand);
|
||||
this.scanNewlines = false;
|
||||
return tt;
|
||||
},
|
||||
|
||||
|
||||
// Eats comments and whitespace.
|
||||
skip: function () {
|
||||
var input = this.source;
|
||||
|
@ -134,7 +134,7 @@ Narcissus.jslex = (function() {
|
|||
ch = input[this.cursor++];
|
||||
if (ch === undefined)
|
||||
throw this.newSyntaxError("Unterminated comment");
|
||||
|
||||
|
||||
if (ch === '*') {
|
||||
next = input[this.cursor];
|
||||
if (next === '/') {
|
||||
|
@ -151,7 +151,7 @@ Narcissus.jslex = (function() {
|
|||
ch = input[this.cursor++];
|
||||
if (ch === undefined)
|
||||
return;
|
||||
|
||||
|
||||
if (ch === '\n') {
|
||||
this.lineno++;
|
||||
break;
|
||||
|
@ -163,7 +163,7 @@ Narcissus.jslex = (function() {
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Lexes the exponential part of a number, if present. Returns true iff an
|
||||
// exponential part was found.
|
||||
lexExponent: function() {
|
||||
|
@ -174,32 +174,32 @@ Narcissus.jslex = (function() {
|
|||
ch = input[this.cursor++];
|
||||
if (ch === '+' || ch === '-')
|
||||
ch = input[this.cursor++];
|
||||
|
||||
|
||||
if (ch < '0' || ch > '9')
|
||||
throw this.newSyntaxError("Missing exponent");
|
||||
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
lexZeroNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '.') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
|
||||
this.lexExponent();
|
||||
token.value = parseFloat(token.start, this.cursor);
|
||||
} else if (ch === 'x' || ch === 'X') {
|
||||
|
@ -208,14 +208,14 @@ Narcissus.jslex = (function() {
|
|||
} while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
|
||||
(ch >= 'A' && ch <= 'F'));
|
||||
this.cursor--;
|
||||
|
||||
|
||||
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||
} else if (ch >= '0' && ch <= '7') {
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '7');
|
||||
this.cursor--;
|
||||
|
||||
|
||||
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||
} else {
|
||||
this.cursor--;
|
||||
|
@ -223,11 +223,11 @@ Narcissus.jslex = (function() {
|
|||
token.value = 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
lexNumber: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = NUMBER;
|
||||
|
||||
|
||||
var floating = false;
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
|
@ -236,16 +236,16 @@ Narcissus.jslex = (function() {
|
|||
ch = input[this.cursor++];
|
||||
}
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
|
||||
|
||||
this.cursor--;
|
||||
|
||||
|
||||
var exponent = this.lexExponent();
|
||||
floating = floating || exponent;
|
||||
|
||||
|
||||
var str = input.substring(token.start, this.cursor);
|
||||
token.value = floating ? parseFloat(str) : parseInt(str);
|
||||
},
|
||||
|
||||
|
||||
lexDot: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
var next = input[this.cursor];
|
||||
|
@ -254,9 +254,9 @@ Narcissus.jslex = (function() {
|
|||
ch = input[this.cursor++];
|
||||
} while (ch >= '0' && ch <= '9');
|
||||
this.cursor--;
|
||||
|
||||
|
||||
this.lexExponent();
|
||||
|
||||
|
||||
token.type = NUMBER;
|
||||
token.value = parseFloat(token.start, this.cursor);
|
||||
} else {
|
||||
|
@ -265,11 +265,11 @@ Narcissus.jslex = (function() {
|
|||
token.value = '.';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
lexString: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = STRING;
|
||||
|
||||
|
||||
var hasEscapes = false;
|
||||
var delim = ch;
|
||||
ch = input[this.cursor++];
|
||||
|
@ -280,16 +280,16 @@ Narcissus.jslex = (function() {
|
|||
}
|
||||
ch = input[this.cursor++];
|
||||
}
|
||||
|
||||
|
||||
token.value = (hasEscapes)
|
||||
? eval(input.substring(token.start, this.cursor))
|
||||
: input.substring(token.start + 1, this.cursor - 1);
|
||||
},
|
||||
|
||||
|
||||
lexRegExp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
token.type = REGEXP;
|
||||
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
if (ch === '\\') {
|
||||
|
@ -298,29 +298,29 @@ Narcissus.jslex = (function() {
|
|||
do {
|
||||
if (ch === undefined)
|
||||
throw this.newSyntaxError("Unterminated character class");
|
||||
|
||||
|
||||
if (ch === '\\')
|
||||
this.cursor++;
|
||||
|
||||
|
||||
ch = input[this.cursor++];
|
||||
} while (ch !== ']');
|
||||
} else if (ch === undefined) {
|
||||
throw this.newSyntaxError("Unterminated regex");
|
||||
}
|
||||
} while (ch !== '/');
|
||||
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while (ch >= 'a' && ch <= 'z');
|
||||
|
||||
|
||||
this.cursor--;
|
||||
|
||||
|
||||
token.value = eval(input.substring(token.start, this.cursor));
|
||||
},
|
||||
|
||||
|
||||
lexOp: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
|
||||
|
||||
// A bit ugly, but it seems wasteful to write a trie lookup routine for
|
||||
// only 3 characters...
|
||||
var node = opTokens[ch];
|
||||
|
@ -335,7 +335,7 @@ Narcissus.jslex = (function() {
|
|||
next = input[this.cursor];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var op = node.op;
|
||||
if (jsdefs.assignOps[op] && input[this.cursor] === '=') {
|
||||
this.cursor++;
|
||||
|
@ -346,27 +346,27 @@ Narcissus.jslex = (function() {
|
|||
token.type = jsdefs.tokenIds[jsdefs.opTypeNames[op]];
|
||||
token.assignOp = null;
|
||||
}
|
||||
|
||||
|
||||
token.value = op;
|
||||
},
|
||||
|
||||
|
||||
// FIXME: Unicode escape sequences
|
||||
// FIXME: Unicode identifiers
|
||||
lexIdent: function (ch) {
|
||||
var token = this.token, input = this.source;
|
||||
|
||||
|
||||
do {
|
||||
ch = input[this.cursor++];
|
||||
} while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
|
||||
(ch >= '0' && ch <= '9') || ch === '$' || ch === '_');
|
||||
|
||||
|
||||
this.cursor--; // Put the non-word character back.
|
||||
|
||||
|
||||
var id = input.substring(token.start, this.cursor);
|
||||
token.type = jsdefs.keywords[id] || IDENTIFIER;
|
||||
token.value = id;
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* Tokenizer.get :: void -> token type
|
||||
*
|
||||
|
@ -382,21 +382,21 @@ Narcissus.jslex = (function() {
|
|||
if (token.type != NEWLINE || this.scanNewlines)
|
||||
return token.type;
|
||||
}
|
||||
|
||||
|
||||
this.skip();
|
||||
|
||||
|
||||
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||
token = this.tokens[this.tokenIndex];
|
||||
if (!token)
|
||||
this.tokens[this.tokenIndex] = token = {};
|
||||
|
||||
|
||||
var input = this.source;
|
||||
if (this.cursor === input.length)
|
||||
return token.type = END;
|
||||
|
||||
|
||||
token.start = this.cursor;
|
||||
token.lineno = this.lineno;
|
||||
|
||||
|
||||
var ch = input[this.cursor++];
|
||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
|
||||
ch === '$' || ch === '_') {
|
||||
|
@ -420,11 +420,11 @@ Narcissus.jslex = (function() {
|
|||
} else {
|
||||
throw this.newSyntaxError("Illegal token");
|
||||
}
|
||||
|
||||
|
||||
token.end = this.cursor;
|
||||
return token.type;
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* Tokenizer.unget :: void -> undefined
|
||||
*
|
||||
|
@ -434,14 +434,14 @@ Narcissus.jslex = (function() {
|
|||
if (++this.lookahead == 4) throw "PANIC: too much lookahead!";
|
||||
this.tokenIndex = (this.tokenIndex - 1) & 3;
|
||||
},
|
||||
|
||||
|
||||
newSyntaxError: function (m) {
|
||||
var e = new SyntaxError(m, this.filename, this.lineno);
|
||||
e.source = this.source;
|
||||
e.cursor = this.cursor;
|
||||
return e;
|
||||
},
|
||||
|
||||
|
||||
save: function () {
|
||||
return {
|
||||
cursor: this.cursor,
|
||||
|
@ -452,7 +452,7 @@ Narcissus.jslex = (function() {
|
|||
lineno: this.lineno
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
rewind: function(point) {
|
||||
this.cursor = point.cursor;
|
||||
this.tokenIndex = point.tokenIndex;
|
||||
|
@ -462,7 +462,7 @@ Narcissus.jslex = (function() {
|
|||
this.lineno = point.lineno;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return { "Tokenizer": Tokenizer };
|
||||
|
||||
}());
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -45,6 +45,9 @@
|
|||
#
|
||||
|
||||
# Define an include-at-most-once flag
|
||||
#ifdef INCLUDED_CONFIG_MK
|
||||
#$(error Don't include config.mk twice!)
|
||||
#endif
|
||||
INCLUDED_CONFIG_MK = 1
|
||||
|
||||
EXIT_ON_ERROR = set -e; # Shell loops continue past errors without this.
|
||||
|
@ -182,7 +185,7 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
MOZALLOC_LIB = -L$(DIST)/bin $(call EXPAND_MOZLIBNAME,mozalloc)
|
||||
MOZALLOC_LIB = $(call EXPAND_LIBNAME_PATH,mozalloc,$(DIST)/lib)
|
||||
|
||||
OS_CFLAGS += $(_DEBUG_CFLAGS)
|
||||
OS_CXXFLAGS += $(_DEBUG_CFLAGS)
|
||||
|
|
|
@ -1520,17 +1520,17 @@ jsvalToPtrExplicit(JSContext* cx, jsval val, uintptr_t* result)
|
|||
return false;
|
||||
}
|
||||
|
||||
template<class IntegerType>
|
||||
template<class IntegerType, class CharType, size_t N, class AP>
|
||||
void
|
||||
IntegerToString(IntegerType i, jsuint radix, AutoString& result)
|
||||
IntegerToString(IntegerType i, jsuint radix, Vector<CharType, N, AP>& result)
|
||||
{
|
||||
JS_STATIC_ASSERT(numeric_limits<IntegerType>::is_exact);
|
||||
|
||||
// The buffer must be big enough for all the bits of IntegerType to fit,
|
||||
// in base-2, including '-'.
|
||||
jschar buffer[sizeof(IntegerType) * 8 + 1];
|
||||
jschar* end = buffer + sizeof(buffer) / sizeof(jschar);
|
||||
jschar* cp = end;
|
||||
CharType buffer[sizeof(IntegerType) * 8 + 1];
|
||||
CharType* end = buffer + sizeof(buffer) / sizeof(CharType);
|
||||
CharType* cp = end;
|
||||
|
||||
// Build the string in reverse. We use multiplication and subtraction
|
||||
// instead of modulus because that's much faster.
|
||||
|
@ -4636,6 +4636,46 @@ PrepareCIF(JSContext* cx,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
FunctionType::BuildSymbolName(JSContext* cx,
|
||||
JSString* name,
|
||||
JSObject* typeObj,
|
||||
AutoCString& result)
|
||||
{
|
||||
FunctionInfo* fninfo = GetFunctionInfo(cx, typeObj);
|
||||
|
||||
switch (GetABICode(cx, fninfo->mABI)) {
|
||||
case ABI_DEFAULT:
|
||||
// For cdecl functions, no mangling is necessary.
|
||||
AppendString(result, name);
|
||||
break;
|
||||
|
||||
case ABI_STDCALL: {
|
||||
// On WIN32, stdcall functions look like:
|
||||
// _foo@40
|
||||
// where 'foo' is the function name, and '40' is the aligned size of the
|
||||
// arguments.
|
||||
AppendString(result, "_");
|
||||
AppendString(result, name);
|
||||
AppendString(result, "@");
|
||||
|
||||
// Compute the suffix by aligning each argument to sizeof(ffi_arg).
|
||||
size_t size = 0;
|
||||
for (size_t i = 0; i < fninfo->mArgTypes.length(); ++i) {
|
||||
JSObject* argType = fninfo->mArgTypes[i];
|
||||
size += Align(CType::GetSize(cx, argType), sizeof(ffi_arg));
|
||||
}
|
||||
|
||||
IntegerToString(size, 10, result);
|
||||
break;
|
||||
}
|
||||
|
||||
case INVALID_ABI:
|
||||
JS_NOT_REACHED("invalid abi");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static FunctionInfo*
|
||||
NewFunctionInfo(JSContext* cx,
|
||||
jsval abiType,
|
||||
|
|
|
@ -111,6 +111,8 @@ class Array : public Vector<T, N, SystemAllocPolicy>
|
|||
// String and AutoString classes, based on Vector.
|
||||
typedef Vector<jschar, 0, SystemAllocPolicy> String;
|
||||
typedef Vector<jschar, 64, SystemAllocPolicy> AutoString;
|
||||
typedef Vector<char, 0, SystemAllocPolicy> CString;
|
||||
typedef Vector<char, 64, SystemAllocPolicy> AutoCString;
|
||||
|
||||
// Convenience functions to append, insert, and compare Strings.
|
||||
template <class T, size_t N, class AP, size_t ArrayLength>
|
||||
|
@ -142,6 +144,20 @@ AppendString(Vector<jschar, N, AP> &v, JSString* str)
|
|||
v.append(str->chars(), str->length());
|
||||
}
|
||||
|
||||
template <size_t N, class AP>
|
||||
void
|
||||
AppendString(Vector<char, N, AP> &v, JSString* str)
|
||||
{
|
||||
JS_ASSERT(str);
|
||||
size_t vlen = v.length();
|
||||
size_t alen = str->length();
|
||||
if (!v.resize(vlen + alen))
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < alen; ++i)
|
||||
v[i + vlen] = char(str->chars()[i]);
|
||||
}
|
||||
|
||||
template <class T, size_t N, class AP, size_t ArrayLength>
|
||||
void
|
||||
PrependString(Vector<T, N, AP> &v, const char (&array)[ArrayLength])
|
||||
|
@ -462,6 +478,8 @@ namespace FunctionType {
|
|||
|
||||
FunctionInfo* GetFunctionInfo(JSContext* cx, JSObject* obj);
|
||||
JSObject* GetLibrary(JSContext* cx, JSObject* obj);
|
||||
void BuildSymbolName(JSContext* cx, JSString* name, JSObject* typeObj,
|
||||
AutoCString& result);
|
||||
}
|
||||
|
||||
namespace CClosure {
|
||||
|
|
|
@ -268,24 +268,21 @@ Library::Declare(JSContext* cx, uintN argc, jsval* vp)
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
const char* name = JS_GetStringBytesZ(cx, JSVAL_TO_STRING(argv[0]));
|
||||
if (!name)
|
||||
return JS_FALSE;
|
||||
|
||||
JSObject* fnObj = NULL;
|
||||
JSObject* typeObj;
|
||||
js::AutoObjectRooter root(cx);
|
||||
bool isFunction = argc > 2;
|
||||
if (isFunction) {
|
||||
// Case 1).
|
||||
// Create a FunctionType representing the function.
|
||||
typeObj = FunctionType::CreateInternal(cx,
|
||||
argv[1], argv[2], &argv[3], argc - 3);
|
||||
if (!typeObj)
|
||||
fnObj = FunctionType::CreateInternal(cx,
|
||||
argv[1], argv[2], &argv[3], argc - 3);
|
||||
if (!fnObj)
|
||||
return JS_FALSE;
|
||||
root.setObject(typeObj);
|
||||
root.setObject(fnObj);
|
||||
|
||||
// Make a function pointer type.
|
||||
typeObj = PointerType::CreateInternal(cx, typeObj);
|
||||
typeObj = PointerType::CreateInternal(cx, fnObj);
|
||||
if (!typeObj)
|
||||
return JS_FALSE;
|
||||
root.setObject(typeObj);
|
||||
|
@ -301,16 +298,22 @@ Library::Declare(JSContext* cx, uintN argc, jsval* vp)
|
|||
|
||||
typeObj = JSVAL_TO_OBJECT(argv[1]);
|
||||
if (CType::GetTypeCode(cx, typeObj) == TYPE_pointer) {
|
||||
JSObject* baseType = PointerType::GetBaseType(cx, typeObj);
|
||||
isFunction = baseType && CType::GetTypeCode(cx, baseType) == TYPE_function;
|
||||
fnObj = PointerType::GetBaseType(cx, typeObj);
|
||||
isFunction = fnObj && CType::GetTypeCode(cx, fnObj) == TYPE_function;
|
||||
}
|
||||
}
|
||||
|
||||
void* data;
|
||||
PRFuncPtr fnptr;
|
||||
JSString* nameStr = JSVAL_TO_STRING(argv[0]);
|
||||
AutoCString symbol;
|
||||
if (isFunction) {
|
||||
// Build the symbol, with mangling if necessary.
|
||||
FunctionType::BuildSymbolName(cx, nameStr, fnObj, symbol);
|
||||
AppendString(symbol, "\0");
|
||||
|
||||
// Look up the function symbol.
|
||||
fnptr = PR_FindFunctionSymbol(library, name);
|
||||
fnptr = PR_FindFunctionSymbol(library, symbol.begin());
|
||||
if (!fnptr) {
|
||||
JS_ReportError(cx, "couldn't find function symbol in library");
|
||||
return JS_FALSE;
|
||||
|
@ -319,7 +322,10 @@ Library::Declare(JSContext* cx, uintN argc, jsval* vp)
|
|||
|
||||
} else {
|
||||
// 'typeObj' is another data type. Look up the data symbol.
|
||||
data = PR_FindSymbol(library, name);
|
||||
AppendString(symbol, nameStr);
|
||||
AppendString(symbol, "\0");
|
||||
|
||||
data = PR_FindSymbol(library, symbol.begin());
|
||||
if (!data) {
|
||||
JS_ReportError(cx, "couldn't find symbol in library");
|
||||
return JS_FALSE;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Patch libffi to fix bug 550602, bug 528129, bug 538216, bug 556902, bug 538002, and bug 581909.
|
||||
Patch libffi to fix bug 550602 and bug 538216.
|
||||
|
||||
diff --git a/js/src/ctypes/libffi/Makefile.in b/js/src/ctypes/libffi/Makefile.in
|
||||
--- a/js/src/ctypes/libffi/Makefile.in
|
||||
|
@ -107,645 +107,4 @@ diff --git a/js/src/ctypes/libffi/configure b/js/src/ctypes/libffi/configure
|
|||
|
||||
archive_cmds_need_lc=no
|
||||
hardcode_direct=no
|
||||
@@ -12179,17 +12179,17 @@ case "$host" in
|
||||
;;
|
||||
hppa*-*-hpux*)
|
||||
TARGET=PA_HPUX; TARGETDIR=pa
|
||||
;;
|
||||
|
||||
i?86-*-freebsd* | i?86-*-openbsd*)
|
||||
TARGET=X86_FREEBSD; TARGETDIR=x86
|
||||
;;
|
||||
- i?86-win32* | i?86-*-cygwin* | i?86-*-mingw*)
|
||||
+ i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2*)
|
||||
TARGET=X86_WIN32; TARGETDIR=x86
|
||||
# All mingw/cygwin/win32 builds require this for sharedlib
|
||||
AM_LTLDFLAGS="-no-undefined"
|
||||
;;
|
||||
i?86-*-darwin*)
|
||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
||||
;;
|
||||
i?86-*-solaris2.1[0-9]*)
|
||||
diff --git a/js/src/ctypes/libffi/msvcc.sh b/js/src/ctypes/libffi/msvcc.sh
|
||||
--- a/js/src/ctypes/libffi/msvcc.sh
|
||||
+++ b/js/src/ctypes/libffi/msvcc.sh
|
||||
@@ -37,20 +37,21 @@
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# GCC-compatible wrapper for cl.exe and ml.exe. Arguments are given in GCC
|
||||
# format and translated into something sensible for cl or ml.
|
||||
#
|
||||
|
||||
-args="-nologo -W3"
|
||||
+args="-nologo"
|
||||
md=-MD
|
||||
cl="cl"
|
||||
ml="ml"
|
||||
+safeseh="-safeseh"
|
||||
output=
|
||||
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
case $1
|
||||
in
|
||||
-fexceptions)
|
||||
# Don't enable exceptions for now.
|
||||
@@ -58,16 +59,17 @@ do
|
||||
shift 1
|
||||
;;
|
||||
-m32)
|
||||
shift 1
|
||||
;;
|
||||
-m64)
|
||||
cl="cl" # "$MSVC/x86_amd64/cl"
|
||||
ml="ml64" # "$MSVC/x86_amd64/ml64"
|
||||
+ safeseh=
|
||||
shift 1
|
||||
;;
|
||||
-O*)
|
||||
args="$args $1"
|
||||
shift 1
|
||||
;;
|
||||
-g)
|
||||
# Can't specify -RTC1 or -Zi in opt. -Gy is ok. Use -OPT:REF?
|
||||
@@ -103,17 +105,18 @@ do
|
||||
includes="$includes $1"
|
||||
shift 1
|
||||
;;
|
||||
-W|-Wextra)
|
||||
# TODO map extra warnings
|
||||
shift 1
|
||||
;;
|
||||
-Wall)
|
||||
- args="$args -Wall"
|
||||
+ # -Wall on MSVC is overzealous. Use -W3 instead.
|
||||
+ args="$args -W3"
|
||||
shift 1
|
||||
;;
|
||||
-Werror)
|
||||
args="$args -WX"
|
||||
shift 1
|
||||
;;
|
||||
-W*)
|
||||
# TODO map specific warnings
|
||||
@@ -158,17 +161,17 @@ done
|
||||
if [ -n "$assembly" ]; then
|
||||
if [ -z "$outdir" ]; then
|
||||
outdir="."
|
||||
fi
|
||||
ppsrc="$outdir/$(basename $src|sed 's/.S$/.asm/g')"
|
||||
echo "$cl -nologo -EP $includes $defines $src > $ppsrc"
|
||||
"$cl" -nologo -EP $includes $defines $src > $ppsrc || exit $?
|
||||
output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')"
|
||||
- args="-nologo -safeseh $single $output $ppsrc"
|
||||
+ args="-nologo $safeseh $single $output $ppsrc"
|
||||
|
||||
echo "$ml $args"
|
||||
eval "\"$ml\" $args"
|
||||
result=$?
|
||||
|
||||
# required to fix ml64 broken output?
|
||||
#mv *.obj $outdir
|
||||
else
|
||||
diff --git a/js/src/ctypes/libffi/src/powerpc/ffi_darwin.c b/js/src/ctypes/libffi/src/powerpc/ffi_darwin.c
|
||||
--- a/js/src/ctypes/libffi/src/powerpc/ffi_darwin.c
|
||||
+++ b/js/src/ctypes/libffi/src/powerpc/ffi_darwin.c
|
||||
@@ -339,17 +339,17 @@ aix_adjust_aggregate_sizes (ffi_type *s)
|
||||
/* Do not add additional tail padding. */
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep (ffi_cif *cif)
|
||||
{
|
||||
/* All this is for the DARWIN ABI. */
|
||||
- int i;
|
||||
+ unsigned i;
|
||||
ffi_type **ptr;
|
||||
unsigned bytes;
|
||||
int fparg_count = 0, intarg_count = 0;
|
||||
unsigned flags = 0;
|
||||
unsigned size_al = 0;
|
||||
|
||||
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||
All the calculation of structure sizes will also be wrong.
|
||||
@@ -537,21 +537,21 @@ ffi_call (ffi_cif *cif, void (*fn)(void)
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_AIX:
|
||||
ffi_call_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
|
||||
- ffi_prep_args);
|
||||
+ FFI_FN(ffi_prep_args));
|
||||
break;
|
||||
case FFI_DARWIN:
|
||||
ffi_call_DARWIN(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
|
||||
- ffi_prep_args);
|
||||
+ FFI_FN(ffi_prep_args));
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void flush_icache(char *);
|
||||
@@ -794,32 +794,32 @@ ffi_closure_helper_DARWIN (ffi_closure *
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#ifdef POWERPC64
|
||||
size_al = arg_types[i]->size;
|
||||
if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
|
||||
size_al = ALIGN (arg_types[i]->size, 8);
|
||||
if (size_al < 3 && cif->abi == FFI_DARWIN)
|
||||
- avalue[i] = (void *) pgr + 8 - size_al;
|
||||
+ avalue[i] = (char *) pgr + 8 - size_al;
|
||||
else
|
||||
- avalue[i] = (void *) pgr;
|
||||
+ avalue[i] = pgr;
|
||||
pgr += (size_al + 7) / 8;
|
||||
#else
|
||||
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
|
||||
SI 4 bytes) are aligned as if they were those modes. */
|
||||
size_al = arg_types[i]->size;
|
||||
/* If the first member of the struct is a double, then align
|
||||
the struct to double-word. */
|
||||
if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
|
||||
size_al = ALIGN(arg_types[i]->size, 8);
|
||||
if (size_al < 3 && cif->abi == FFI_DARWIN)
|
||||
- avalue[i] = (void*) pgr + 4 - size_al;
|
||||
+ avalue[i] = (char*) pgr + 4 - size_al;
|
||||
else
|
||||
- avalue[i] = (void*) pgr;
|
||||
+ avalue[i] = pgr;
|
||||
pgr += (size_al + 3) / 4;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
#ifdef POWERPC64
|
||||
case FFI_TYPE_POINTER:
|
||||
diff --git a/js/src/ctypes/libffi/src/x86/ffi.c b/js/src/ctypes/libffi/src/x86/ffi.c
|
||||
--- a/js/src/ctypes/libffi/src/x86/ffi.c
|
||||
+++ b/js/src/ctypes/libffi/src/x86/ffi.c
|
||||
@@ -204,17 +204,17 @@ ffi_status ffi_prep_cif_machdep(ffi_cif
|
||||
else if (cif->rtype->size == 8)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
- // allocate space for return value pointer
|
||||
+ /* allocate space for return value pointer */
|
||||
cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef X86_WIN64
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
@@ -229,17 +229,17 @@ ffi_status ffi_prep_cif_machdep(ffi_cif
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
if (((*ptr)->alignment - 1) & cif->bytes)
|
||||
cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
|
||||
cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
|
||||
}
|
||||
|
||||
#ifdef X86_WIN64
|
||||
- // ensure space for storing four registers
|
||||
+ /* ensure space for storing four registers */
|
||||
cif->bytes += 4 * sizeof(ffi_arg);
|
||||
#endif
|
||||
|
||||
#ifdef X86_DARWIN
|
||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||
#endif
|
||||
|
||||
return FFI_OK;
|
||||
@@ -287,18 +287,18 @@ void ffi_call(ffi_cif *cif, void (*fn)(v
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#ifdef X86_WIN64
|
||||
case FFI_WIN64:
|
||||
{
|
||||
- // Make copies of all struct arguments
|
||||
- // NOTE: not sure if responsibility should be here or in caller
|
||||
+ /* Make copies of all struct arguments
|
||||
+ NOTE: not sure if responsibility should be here or in caller */
|
||||
unsigned int i;
|
||||
for (i=0; i < cif->nargs;i++) {
|
||||
size_t size = cif->arg_types[i]->size;
|
||||
if ((cif->arg_types[i]->type == FFI_TYPE_STRUCT
|
||||
&& (size != 1 && size != 2 && size != 4 && size != 8))
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| cif->arg_types[i]->type == FFI_TYPE_LONGDOUBLE
|
||||
#endif
|
||||
@@ -580,20 +580,20 @@ ffi_prep_raw_closure_loc (ffi_raw_closur
|
||||
void *codeloc)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cif->abi != FFI_SYSV) {
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
|
||||
- // we currently don't support certain kinds of arguments for raw
|
||||
- // closures. This should be implemented by a separate assembly language
|
||||
- // routine, since it would require argument processing, something we
|
||||
- // don't do now for performance.
|
||||
+ /* we currently don't support certain kinds of arguments for raw
|
||||
+ closures. This should be implemented by a separate assembly language
|
||||
+ routine, since it would require argument processing, something we
|
||||
+ don't do now for performance. */
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--)
|
||||
{
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
|
||||
}
|
||||
|
||||
|
||||
diff --git a/js/src/ctypes/libffi/src/x86/ffitarget.h b/js/src/ctypes/libffi/src/x86/ffitarget.h
|
||||
--- a/js/src/ctypes/libffi/src/x86/ffitarget.h
|
||||
+++ b/js/src/ctypes/libffi/src/x86/ffitarget.h
|
||||
@@ -33,17 +33,17 @@
|
||||
|
||||
#if defined (X86_64) && defined (__i386__)
|
||||
#undef X86_64
|
||||
#define X86
|
||||
#endif
|
||||
|
||||
#ifdef X86_WIN64
|
||||
#define FFI_SIZEOF_ARG 8
|
||||
-#define USE_BUILTIN_FFS 0 // not yet implemented in mingw-64
|
||||
+#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */
|
||||
#endif
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
#ifdef X86_WIN64
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int64 ffi_arg;
|
||||
diff --git a/js/src/ctypes/libffi/src/closures.c b/js/src/ctypes/libffi/src/closures.c
|
||||
--- a/js/src/ctypes/libffi/src/closures.c
|
||||
+++ b/js/src/ctypes/libffi/src/closures.c
|
||||
@@ -39,17 +39,17 @@
|
||||
option is defined will attempt to map such pages once, but if it
|
||||
fails, it falls back to creating a temporary file in a writable and
|
||||
executable filesystem and mapping pages from it into separate
|
||||
locations in the virtual memory space, one location writable and
|
||||
another executable. */
|
||||
# define FFI_MMAP_EXEC_WRIT 1
|
||||
# define HAVE_MNTENT 1
|
||||
# endif
|
||||
-# if defined(X86_WIN32) || defined(X86_WIN64)
|
||||
+# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)
|
||||
/* Windows systems may have Data Execution Protection (DEP) enabled,
|
||||
which requires the use of VirtualMalloc/VirtualFree to alloc/free
|
||||
executable memory. */
|
||||
# define FFI_MMAP_EXEC_WRIT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
|
||||
@@ -188,31 +188,31 @@ static size_t dlmalloc_footprint(void) M
|
||||
static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED;
|
||||
static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED;
|
||||
static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED;
|
||||
static void *dlpvalloc(size_t) MAYBE_UNUSED;
|
||||
static int dlmalloc_trim(size_t) MAYBE_UNUSED;
|
||||
static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
|
||||
static void dlmalloc_stats(void) MAYBE_UNUSED;
|
||||
|
||||
-#if !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__)
|
||||
+#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__)
|
||||
/* Use these for mmap and munmap within dlmalloc.c. */
|
||||
static void *dlmmap(void *, size_t, int, int, int, off_t);
|
||||
static int dlmunmap(void *, size_t);
|
||||
-#endif /* !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__) */
|
||||
+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) */
|
||||
|
||||
#define mmap dlmmap
|
||||
#define munmap dlmunmap
|
||||
|
||||
#include "dlmalloc.c"
|
||||
|
||||
#undef mmap
|
||||
#undef munmap
|
||||
|
||||
-#if !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__)
|
||||
+#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__)
|
||||
|
||||
/* A mutex used to synchronize access to *exec* variables in this file. */
|
||||
static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* A file descriptor of a temporary file from which we'll map
|
||||
executable pages. */
|
||||
static int execfd = -1;
|
||||
|
||||
@@ -517,17 +517,17 @@ segment_holding_code (mstate m, char* ad
|
||||
&& addr < add_segment_exec_offset (sp->base, sp) + sp->size)
|
||||
return sp;
|
||||
if ((sp = sp->next) == 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
-#endif /* !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__) */
|
||||
+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) */
|
||||
|
||||
/* Allocate a chunk of memory with the given size. Returns a pointer
|
||||
to the writable address, and sets *CODE to the executable
|
||||
corresponding virtual address. */
|
||||
void *
|
||||
ffi_closure_alloc (size_t size, void **code)
|
||||
{
|
||||
void *ptr;
|
||||
diff --git a/js/src/ctypes/libffi/src/dlmalloc.c b/js/src/ctypes/libffi/src/dlmalloc.c
|
||||
--- a/js/src/ctypes/libffi/src/dlmalloc.c
|
||||
+++ b/js/src/ctypes/libffi/src/dlmalloc.c
|
||||
@@ -454,16 +454,24 @@ DEFAULT_MMAP_THRESHOLD default: 25
|
||||
#define LACKS_STRING_H
|
||||
#define LACKS_STRINGS_H
|
||||
#define LACKS_SYS_TYPES_H
|
||||
#define LACKS_ERRNO_H
|
||||
#define MALLOC_FAILURE_ACTION
|
||||
#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */
|
||||
#endif /* WIN32 */
|
||||
|
||||
+#ifdef __OS2__
|
||||
+#define INCL_DOS
|
||||
+#include <os2.h>
|
||||
+#define HAVE_MMAP 1
|
||||
+#define HAVE_MORECORE 0
|
||||
+#define LACKS_SYS_MMAN_H
|
||||
+#endif /* __OS2__ */
|
||||
+
|
||||
#if defined(DARWIN) || defined(_DARWIN)
|
||||
/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
|
||||
#ifndef HAVE_MORECORE
|
||||
#define HAVE_MORECORE 0
|
||||
#define HAVE_MMAP 1
|
||||
#endif /* HAVE_MORECORE */
|
||||
#endif /* DARWIN */
|
||||
|
||||
@@ -1283,17 +1291,17 @@ extern void* sbrk(ptrdiff_t);
|
||||
#define CALL_MMAP(s) MFAIL
|
||||
#define CALL_MUNMAP(a, s) (-1)
|
||||
#define DIRECT_MMAP(s) MFAIL
|
||||
|
||||
#else /* HAVE_MMAP */
|
||||
#define IS_MMAPPED_BIT (SIZE_T_ONE)
|
||||
#define USE_MMAP_BIT (SIZE_T_ONE)
|
||||
|
||||
-#ifndef WIN32
|
||||
+#if !defined(WIN32) && !defined (__OS2__)
|
||||
#define CALL_MUNMAP(a, s) munmap((a), (s))
|
||||
#define MMAP_PROT (PROT_READ|PROT_WRITE)
|
||||
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif /* MAP_ANON */
|
||||
#ifdef MAP_ANONYMOUS
|
||||
#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
|
||||
#define CALL_MMAP(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
|
||||
@@ -1306,16 +1314,52 @@ extern void* sbrk(ptrdiff_t);
|
||||
static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
|
||||
#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
|
||||
(dev_zero_fd = open("/dev/zero", O_RDWR), \
|
||||
mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
|
||||
mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
|
||||
#endif /* MAP_ANONYMOUS */
|
||||
|
||||
#define DIRECT_MMAP(s) CALL_MMAP(s)
|
||||
+
|
||||
+#elif defined(__OS2__)
|
||||
+
|
||||
+/* OS/2 MMAP via DosAllocMem */
|
||||
+static void* os2mmap(size_t size) {
|
||||
+ void* ptr;
|
||||
+ if (DosAllocMem(&ptr, size, OBJ_ANY|PAG_COMMIT|PAG_READ|PAG_WRITE) &&
|
||||
+ DosAllocMem(&ptr, size, PAG_COMMIT|PAG_READ|PAG_WRITE))
|
||||
+ return MFAIL;
|
||||
+ return ptr;
|
||||
+}
|
||||
+
|
||||
+#define os2direct_mmap(n) os2mmap(n)
|
||||
+
|
||||
+/* This function supports releasing coalesed segments */
|
||||
+static int os2munmap(void* ptr, size_t size) {
|
||||
+ while (size) {
|
||||
+ ULONG ulSize = size;
|
||||
+ ULONG ulFlags = 0;
|
||||
+ if (DosQueryMem(ptr, &ulSize, &ulFlags) != 0)
|
||||
+ return -1;
|
||||
+ if ((ulFlags & PAG_BASE) == 0 ||(ulFlags & PAG_COMMIT) == 0 ||
|
||||
+ ulSize > size)
|
||||
+ return -1;
|
||||
+ if (DosFreeMem(ptr) != 0)
|
||||
+ return -1;
|
||||
+ ptr = ( void * ) ( ( char * ) ptr + ulSize );
|
||||
+ size -= ulSize;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define CALL_MMAP(s) os2mmap(s)
|
||||
+#define CALL_MUNMAP(a, s) os2munmap((a), (s))
|
||||
+#define DIRECT_MMAP(s) os2direct_mmap(s)
|
||||
+
|
||||
#else /* WIN32 */
|
||||
|
||||
/* Win32 MMAP via VirtualAlloc */
|
||||
static void* win32mmap(size_t size) {
|
||||
void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
return (ptr != 0)? ptr: MFAIL;
|
||||
}
|
||||
|
||||
@@ -1382,30 +1426,40 @@ static int win32munmap(void* ptr, size_t
|
||||
protect against direct calls to MORECORE by other threads not
|
||||
using this lock, so there is still code to cope the best we can on
|
||||
interference.
|
||||
|
||||
* magic_init_mutex ensures that mparams.magic and other
|
||||
unique mparams values are initialized only once.
|
||||
*/
|
||||
|
||||
-#ifndef WIN32
|
||||
+#if !defined(WIN32) && !defined(__OS2__)
|
||||
/* By default use posix locks */
|
||||
#include <pthread.h>
|
||||
#define MLOCK_T pthread_mutex_t
|
||||
#define INITIAL_LOCK(l) pthread_mutex_init(l, NULL)
|
||||
#define ACQUIRE_LOCK(l) pthread_mutex_lock(l)
|
||||
#define RELEASE_LOCK(l) pthread_mutex_unlock(l)
|
||||
|
||||
#if HAVE_MORECORE
|
||||
static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif /* HAVE_MORECORE */
|
||||
|
||||
static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
+#elif defined(__OS2__)
|
||||
+#define MLOCK_T HMTX
|
||||
+#define INITIAL_LOCK(l) DosCreateMutexSem(0, l, 0, FALSE)
|
||||
+#define ACQUIRE_LOCK(l) DosRequestMutexSem(*l, SEM_INDEFINITE_WAIT)
|
||||
+#define RELEASE_LOCK(l) DosReleaseMutexSem(*l)
|
||||
+#if HAVE_MORECORE
|
||||
+static MLOCK_T morecore_mutex;
|
||||
+#endif /* HAVE_MORECORE */
|
||||
+static MLOCK_T magic_init_mutex;
|
||||
+
|
||||
#else /* WIN32 */
|
||||
/*
|
||||
Because lock-protected regions have bounded times, and there
|
||||
are no recursive lock calls, we can use simple spinlocks.
|
||||
*/
|
||||
|
||||
#define MLOCK_T long
|
||||
static int win32_acquire_lock (MLOCK_T *sl) {
|
||||
@@ -2487,20 +2541,25 @@ static int init_mparams(void) {
|
||||
if (mparams.magic == 0) {
|
||||
mparams.magic = s;
|
||||
/* Set up lock for main malloc area */
|
||||
INITIAL_LOCK(&gm->mutex);
|
||||
gm->mflags = mparams.default_mflags;
|
||||
}
|
||||
RELEASE_MAGIC_INIT_LOCK();
|
||||
|
||||
-#ifndef WIN32
|
||||
+#if !defined(WIN32) && !defined(__OS2__)
|
||||
mparams.page_size = malloc_getpagesize;
|
||||
mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
|
||||
DEFAULT_GRANULARITY : mparams.page_size);
|
||||
+#elif defined (__OS2__)
|
||||
+ /* if low-memory is used, os2munmap() would break
|
||||
+ if it were anything other than 64k */
|
||||
+ mparams.page_size = 4096u;
|
||||
+ mparams.granularity = 65536u;
|
||||
#else /* WIN32 */
|
||||
{
|
||||
SYSTEM_INFO system_info;
|
||||
GetSystemInfo(&system_info);
|
||||
mparams.page_size = system_info.dwPageSize;
|
||||
mparams.granularity = system_info.dwAllocationGranularity;
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
diff --git a/js/src/ctypes/libffi/src/x86/win32.S b/js/src/ctypes/libffi/src/x86/win32.S
|
||||
--- a/js/src/ctypes/libffi/src/x86/win32.S
|
||||
+++ b/js/src/ctypes/libffi/src/x86/win32.S
|
||||
@@ -390,17 +390,19 @@ END
|
||||
|
||||
#else
|
||||
|
||||
.text
|
||||
|
||||
# This assumes we are using gas.
|
||||
.balign 16
|
||||
.globl _ffi_call_win32
|
||||
+#ifndef __OS2__
|
||||
.def _ffi_call_win32; .scl 2; .type 32; .endef
|
||||
+#endif
|
||||
_ffi_call_win32:
|
||||
.LFB1:
|
||||
pushl %ebp
|
||||
.LCFI0:
|
||||
movl %esp,%ebp
|
||||
.LCFI1:
|
||||
# Make room for all of the new args.
|
||||
movl 16(%ebp),%ecx
|
||||
@@ -542,17 +544,19 @@ 1:
|
||||
popl %ebp
|
||||
ret
|
||||
.ffi_call_win32_end:
|
||||
.LFE1:
|
||||
|
||||
# This assumes we are using gas.
|
||||
.balign 16
|
||||
.globl _ffi_closure_SYSV
|
||||
+#ifndef __OS2__
|
||||
.def _ffi_closure_SYSV; .scl 2; .type 32; .endef
|
||||
+#endif
|
||||
_ffi_closure_SYSV:
|
||||
.LFB3:
|
||||
pushl %ebp
|
||||
.LCFI4:
|
||||
movl %esp, %ebp
|
||||
.LCFI5:
|
||||
subl $40, %esp
|
||||
leal -24(%ebp), %edx
|
||||
@@ -663,17 +667,19 @@ 1:
|
||||
#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
|
||||
#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
|
||||
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
|
||||
#define CIF_FLAGS_OFFSET 20
|
||||
|
||||
# This assumes we are using gas.
|
||||
.balign 16
|
||||
.globl _ffi_closure_raw_SYSV
|
||||
+#ifndef __OS2__
|
||||
.def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef
|
||||
+#endif
|
||||
_ffi_closure_raw_SYSV:
|
||||
.LFB4:
|
||||
pushl %ebp
|
||||
.LCFI6:
|
||||
movl %esp, %ebp
|
||||
.LCFI7:
|
||||
pushl %esi
|
||||
.LCFI8:
|
||||
@@ -779,17 +785,19 @@ 1:
|
||||
.ffi_closure_raw_SYSV_end:
|
||||
.LFE4:
|
||||
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
|
||||
# This assumes we are using gas.
|
||||
.balign 16
|
||||
.globl _ffi_closure_STDCALL
|
||||
+#ifndef __OS2__
|
||||
.def _ffi_closure_STDCALL; .scl 2; .type 32; .endef
|
||||
+#endif
|
||||
_ffi_closure_STDCALL:
|
||||
.LFB5:
|
||||
pushl %ebp
|
||||
.LCFI9:
|
||||
movl %esp, %ebp
|
||||
.LCFI10:
|
||||
subl $40, %esp
|
||||
leal -24(%ebp), %edx
|
||||
@@ -885,17 +893,19 @@ 1:
|
||||
.Lscls_noretval:
|
||||
.Lscls_epilogue:
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
.ffi_closure_STDCALL_end:
|
||||
.LFE5:
|
||||
|
||||
+#ifndef __OS2__
|
||||
.section .eh_frame,"w"
|
||||
+#endif
|
||||
.Lframe1:
|
||||
.LSCIE1:
|
||||
.long .LECIE1-.LASCIE1 /* Length of Common Information Entry */
|
||||
.LASCIE1:
|
||||
.long 0x0 /* CIE Identifier Tag */
|
||||
.byte 0x1 /* CIE Version */
|
||||
#ifdef __PIC__
|
||||
.ascii "zR\0" /* CIE Augmentation */
|
||||
|
||||
|
|
|
@ -1,3 +1,122 @@
|
|||
2010-08-05 Dan Witte <dwitte@mozilla.com>
|
||||
|
||||
* Makefile.am: Pass FFI_DEBUG define to msvcc.sh for linking to the
|
||||
debug CRT when --enable-debug is given.
|
||||
* configure.ac: Define it.
|
||||
* msvcc.sh: Translate -g and -DFFI_DEBUG appropriately.
|
||||
|
||||
2010-08-04 Dan Witte <dwitte@mozilla.com>
|
||||
|
||||
* src/x86/ffitarget.h: Add X86_ANY define for all x86/x86_64
|
||||
platforms.
|
||||
* src/x86/ffi.c: Remove redundant ifdef checks.
|
||||
* src/prep_cif.c: Push stack space computation into src/x86/ffi.c
|
||||
for X86_ANY so return value space doesn't get added twice.
|
||||
|
||||
2010-08-03 Neil Rashbrooke <neil@parkwaycc.co.uk>
|
||||
|
||||
* msvcc.sh: Don't pass -safeseh to ml64 because behavior is buggy.
|
||||
|
||||
2010-07-22 Dan Witte <dwitte@mozilla.com>
|
||||
|
||||
* src/*/ffitarget.h: Make FFI_LAST_ABI one past the last valid ABI.
|
||||
* src/prep_cif.c: Fix ABI assertion.
|
||||
* src/cris/ffi.c: Ditto.
|
||||
|
||||
2010-07-10 Evan Phoenix <evan@fallingsnow.net>
|
||||
|
||||
* src/closures.c (selinux_enabled_check): Fix strncmp usage bug.
|
||||
|
||||
2010-07-07 Dan Horák <dan@danny.cz>
|
||||
|
||||
* include/ffi.h.in: Protect #define with #ifndef.
|
||||
* src/powerpc/ffitarget.h: Ditto.
|
||||
* src/s390/ffitarget.h: Ditto.
|
||||
* src/sparc/ffitarget.h: Ditto.
|
||||
|
||||
2010-05-11 Dan Witte <dwitte@mozilla.com>
|
||||
|
||||
* doc/libffi.tex: Document previous change.
|
||||
|
||||
2010-05-11 Makoto Kato <m_kato@ga2.so-net.ne.jp>
|
||||
|
||||
* src/x86/ffi.c (ffi_call): Don't copy structs passed by value.
|
||||
|
||||
2010-05-05 Michael Kohler <michaelkohler@live.com>
|
||||
|
||||
* src/dlmalloc.c (dlfree): Fix spelling.
|
||||
* src/ia64/ffi.c (ffi_prep_cif_machdep): Ditto.
|
||||
* configure.ac: Ditto.
|
||||
* configure: Rebuilt.
|
||||
|
||||
2010-04-13 Dan Witte <dwitte@mozilla.com>
|
||||
|
||||
* msvcc.sh: Build with -W3 instead of -Wall.
|
||||
* src/powerpc/ffi_darwin.c: Remove build warnings.
|
||||
* src/x86/ffi.c: Ditto.
|
||||
* src/x86/ffitarget.h: Ditto.
|
||||
|
||||
2010-03-30 Dan Witte <dwitte@mozilla.com>
|
||||
|
||||
* msvcc.sh: Disable build warnings.
|
||||
* README (tested): Clarify windows build procedure.
|
||||
|
||||
2010-03-14 Matthias Klose <doko@ubuntu.com>
|
||||
|
||||
* src/x86/ffi64.c: Fix typo in comment.
|
||||
* src/x86/ffi.c: Use /* ... */ comment style.
|
||||
|
||||
2010-07-07 Neil Roberts <neil@linux.intel.com>
|
||||
|
||||
* src/x86/sysv.S (ffi_call_SYSV): Align the stack pointer to
|
||||
16-bytes.
|
||||
|
||||
2010-07-02 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* Makefile.am (AM_MAKEFLAGS): Pass also mandir to submakes.
|
||||
* Makefile.in: Regenerated.
|
||||
|
||||
2010-05-19 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
||||
|
||||
* configure.ac (libffi_cv_as_x86_pcrel): Check for illegal in as
|
||||
output, too.
|
||||
(libffi_cv_as_ascii_pseudo_op): Check for .ascii.
|
||||
(libffi_cv_as_string_pseudo_op): Check for .string.
|
||||
* configure: Regenerate.
|
||||
* fficonfig.h.in: Regenerate.
|
||||
* src/x86/sysv.S (.eh_frame): Use .ascii, .string or error.
|
||||
|
||||
2010-04-07 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* regex.c (byte_re_match_2_internal): Avoid set but not used
|
||||
warning.
|
||||
|
||||
2010-04-02 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
|
||||
|
||||
* Makefile.in: Regenerate.
|
||||
* aclocal.m4: Regenerate.
|
||||
* include/Makefile.in: Regenerate.
|
||||
* man/Makefile.in: Regenerate.
|
||||
* testsuite/Makefile.in: Regenerate.
|
||||
|
||||
2010-03-15 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
||||
|
||||
* configure.ac (libffi_cv_as_x86_64_unwind_section_type): New test.
|
||||
* configure: Regenerate.
|
||||
* fficonfig.h.in: Regenerate.
|
||||
* libffi/src/x86/unix64.S (.eh_frame)
|
||||
[HAVE_AS_X86_64_UNWIND_SECTION_TYPE]: Use @unwind section type.
|
||||
|
||||
2010-02-24 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
||||
|
||||
* doc/libffi.texi (The Closure API): Fix typo.
|
||||
* doc/libffi.info: Remove.
|
||||
|
||||
2010-02-15 Matthias Klose <doko@ubuntu.com>
|
||||
|
||||
* src/arm/sysv.S (__ARM_ARCH__): Define for processor
|
||||
__ARM_ARCH_7EM__.
|
||||
|
||||
2010-01-07 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
||||
|
||||
PR libffi/40701
|
||||
|
|
|
@ -69,6 +69,7 @@ AM_MAKEFLAGS = \
|
|||
"exec_prefix=$(exec_prefix)" \
|
||||
"infodir=$(infodir)" \
|
||||
"libdir=$(libdir)" \
|
||||
"mandir=$(mandir)" \
|
||||
"prefix=$(prefix)" \
|
||||
"AR=$(AR)" \
|
||||
"AS=$(AS)" \
|
||||
|
@ -151,6 +152,9 @@ endif
|
|||
if FRV
|
||||
nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c
|
||||
endif
|
||||
if MOXIE
|
||||
nodist_libffi_la_SOURCES += src/moxie/eabi.S src/moxie/ffi.c
|
||||
endif
|
||||
if S390
|
||||
nodist_libffi_la_SOURCES += src/s390/sysv.S src/s390/ffi.c
|
||||
endif
|
||||
|
@ -174,6 +178,14 @@ libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
|
|||
nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
|
||||
|
||||
AM_CFLAGS = -Wall -g -fexceptions
|
||||
if FFI_DEBUG
|
||||
# Build debug. Define FFI_DEBUG on the commandline so that, when building with
|
||||
# MSVC, it can link against the debug CRT.
|
||||
AM_CFLAGS += -DFFI_DEBUG
|
||||
else
|
||||
# Build opt.
|
||||
AM_CFLAGS += -O2
|
||||
endif
|
||||
|
||||
libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Makefile.in generated by automake 1.11 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
|
@ -55,12 +55,18 @@ target_triplet = @target@
|
|||
@AVR32_TRUE@am__append_17 = src/avr32/sysv.S src/avr32/ffi.c
|
||||
@LIBFFI_CRIS_TRUE@am__append_18 = src/cris/sysv.S src/cris/ffi.c
|
||||
@FRV_TRUE@am__append_19 = src/frv/eabi.S src/frv/ffi.c
|
||||
@S390_TRUE@am__append_20 = src/s390/sysv.S src/s390/ffi.c
|
||||
@X86_64_TRUE@am__append_21 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
|
||||
@SH_TRUE@am__append_22 = src/sh/sysv.S src/sh/ffi.c
|
||||
@SH64_TRUE@am__append_23 = src/sh64/sysv.S src/sh64/ffi.c
|
||||
@PA_LINUX_TRUE@am__append_24 = src/pa/linux.S src/pa/ffi.c
|
||||
@PA_HPUX_TRUE@am__append_25 = src/pa/hpux32.S src/pa/ffi.c
|
||||
@MOXIE_TRUE@am__append_20 = src/moxie/eabi.S src/moxie/ffi.c
|
||||
@S390_TRUE@am__append_21 = src/s390/sysv.S src/s390/ffi.c
|
||||
@X86_64_TRUE@am__append_22 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
|
||||
@SH_TRUE@am__append_23 = src/sh/sysv.S src/sh/ffi.c
|
||||
@SH64_TRUE@am__append_24 = src/sh64/sysv.S src/sh64/ffi.c
|
||||
@PA_LINUX_TRUE@am__append_25 = src/pa/linux.S src/pa/ffi.c
|
||||
@PA_HPUX_TRUE@am__append_26 = src/pa/hpux32.S src/pa/ffi.c
|
||||
# Build debug. Define FFI_DEBUG on the commandline so that, when building with
|
||||
# MSVC, it can link against the debug CRT.
|
||||
@FFI_DEBUG_TRUE@am__append_27 = -DFFI_DEBUG
|
||||
# Build opt.
|
||||
@FFI_DEBUG_FALSE@am__append_28 = -O2
|
||||
subdir = .
|
||||
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/doc/stamp-vti \
|
||||
|
@ -138,13 +144,14 @@ am_libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \
|
|||
@AVR32_TRUE@am__objects_17 = src/avr32/sysv.lo src/avr32/ffi.lo
|
||||
@LIBFFI_CRIS_TRUE@am__objects_18 = src/cris/sysv.lo src/cris/ffi.lo
|
||||
@FRV_TRUE@am__objects_19 = src/frv/eabi.lo src/frv/ffi.lo
|
||||
@S390_TRUE@am__objects_20 = src/s390/sysv.lo src/s390/ffi.lo
|
||||
@X86_64_TRUE@am__objects_21 = src/x86/ffi64.lo src/x86/unix64.lo \
|
||||
@MOXIE_TRUE@am__objects_20 = src/moxie/eabi.lo src/moxie/ffi.lo
|
||||
@S390_TRUE@am__objects_21 = src/s390/sysv.lo src/s390/ffi.lo
|
||||
@X86_64_TRUE@am__objects_22 = src/x86/ffi64.lo src/x86/unix64.lo \
|
||||
@X86_64_TRUE@ src/x86/ffi.lo src/x86/sysv.lo
|
||||
@SH_TRUE@am__objects_22 = src/sh/sysv.lo src/sh/ffi.lo
|
||||
@SH64_TRUE@am__objects_23 = src/sh64/sysv.lo src/sh64/ffi.lo
|
||||
@PA_LINUX_TRUE@am__objects_24 = src/pa/linux.lo src/pa/ffi.lo
|
||||
@PA_HPUX_TRUE@am__objects_25 = src/pa/hpux32.lo src/pa/ffi.lo
|
||||
@SH_TRUE@am__objects_23 = src/sh/sysv.lo src/sh/ffi.lo
|
||||
@SH64_TRUE@am__objects_24 = src/sh64/sysv.lo src/sh64/ffi.lo
|
||||
@PA_LINUX_TRUE@am__objects_25 = src/pa/linux.lo src/pa/ffi.lo
|
||||
@PA_HPUX_TRUE@am__objects_26 = src/pa/hpux32.lo src/pa/ffi.lo
|
||||
nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
|
||||
$(am__objects_3) $(am__objects_4) $(am__objects_5) \
|
||||
$(am__objects_6) $(am__objects_7) $(am__objects_8) \
|
||||
|
@ -153,17 +160,17 @@ nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
|
|||
$(am__objects_15) $(am__objects_16) $(am__objects_17) \
|
||||
$(am__objects_18) $(am__objects_19) $(am__objects_20) \
|
||||
$(am__objects_21) $(am__objects_22) $(am__objects_23) \
|
||||
$(am__objects_24) $(am__objects_25)
|
||||
$(am__objects_24) $(am__objects_25) $(am__objects_26)
|
||||
libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) \
|
||||
$(nodist_libffi_la_OBJECTS)
|
||||
libffi_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(libffi_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
libffi_convenience_la_LIBADD =
|
||||
am__objects_26 = src/debug.lo src/prep_cif.lo src/types.lo \
|
||||
am__objects_27 = src/debug.lo src/prep_cif.lo src/types.lo \
|
||||
src/raw_api.lo src/java_raw_api.lo src/closures.lo
|
||||
am_libffi_convenience_la_OBJECTS = $(am__objects_26)
|
||||
am__objects_27 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
||||
am_libffi_convenience_la_OBJECTS = $(am__objects_27)
|
||||
am__objects_28 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
||||
$(am__objects_4) $(am__objects_5) $(am__objects_6) \
|
||||
$(am__objects_7) $(am__objects_8) $(am__objects_9) \
|
||||
$(am__objects_10) $(am__objects_11) $(am__objects_12) \
|
||||
|
@ -171,8 +178,8 @@ am__objects_27 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
|||
$(am__objects_16) $(am__objects_17) $(am__objects_18) \
|
||||
$(am__objects_19) $(am__objects_20) $(am__objects_21) \
|
||||
$(am__objects_22) $(am__objects_23) $(am__objects_24) \
|
||||
$(am__objects_25)
|
||||
nodist_libffi_convenience_la_OBJECTS = $(am__objects_27)
|
||||
$(am__objects_25) $(am__objects_26)
|
||||
nodist_libffi_convenience_la_OBJECTS = $(am__objects_28)
|
||||
libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \
|
||||
$(nodist_libffi_convenience_la_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||
|
@ -319,6 +326,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
|||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
|
@ -448,6 +456,7 @@ AM_MAKEFLAGS = \
|
|||
"exec_prefix=$(exec_prefix)" \
|
||||
"infodir=$(infodir)" \
|
||||
"libdir=$(libdir)" \
|
||||
"mandir=$(mandir)" \
|
||||
"prefix=$(prefix)" \
|
||||
"AR=$(AR)" \
|
||||
"AS=$(AS)" \
|
||||
|
@ -475,10 +484,10 @@ nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \
|
|||
$(am__append_15) $(am__append_16) $(am__append_17) \
|
||||
$(am__append_18) $(am__append_19) $(am__append_20) \
|
||||
$(am__append_21) $(am__append_22) $(am__append_23) \
|
||||
$(am__append_24) $(am__append_25)
|
||||
$(am__append_24) $(am__append_25) $(am__append_26)
|
||||
libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
|
||||
nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
|
||||
AM_CFLAGS = -Wall -g -fexceptions
|
||||
AM_CFLAGS = -Wall -g -fexceptions $(am__append_27) $(am__append_28)
|
||||
libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
|
||||
AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
|
||||
AM_CCASFLAGS = $(AM_CPPFLAGS)
|
||||
|
@ -744,6 +753,16 @@ src/frv/eabi.lo: src/frv/$(am__dirstamp) \
|
|||
src/frv/$(DEPDIR)/$(am__dirstamp)
|
||||
src/frv/ffi.lo: src/frv/$(am__dirstamp) \
|
||||
src/frv/$(DEPDIR)/$(am__dirstamp)
|
||||
src/moxie/$(am__dirstamp):
|
||||
@$(MKDIR_P) src/moxie
|
||||
@: > src/moxie/$(am__dirstamp)
|
||||
src/moxie/$(DEPDIR)/$(am__dirstamp):
|
||||
@$(MKDIR_P) src/moxie/$(DEPDIR)
|
||||
@: > src/moxie/$(DEPDIR)/$(am__dirstamp)
|
||||
src/moxie/eabi.lo: src/moxie/$(am__dirstamp) \
|
||||
src/moxie/$(DEPDIR)/$(am__dirstamp)
|
||||
src/moxie/ffi.lo: src/moxie/$(am__dirstamp) \
|
||||
src/moxie/$(DEPDIR)/$(am__dirstamp)
|
||||
src/s390/$(am__dirstamp):
|
||||
@$(MKDIR_P) src/s390
|
||||
@: > src/s390/$(am__dirstamp)
|
||||
|
@ -837,6 +856,10 @@ mostlyclean-compile:
|
|||
-rm -f src/mips/n32.lo
|
||||
-rm -f src/mips/o32.$(OBJEXT)
|
||||
-rm -f src/mips/o32.lo
|
||||
-rm -f src/moxie/eabi.$(OBJEXT)
|
||||
-rm -f src/moxie/eabi.lo
|
||||
-rm -f src/moxie/ffi.$(OBJEXT)
|
||||
-rm -f src/moxie/ffi.lo
|
||||
-rm -f src/pa/ffi.$(OBJEXT)
|
||||
-rm -f src/pa/ffi.lo
|
||||
-rm -f src/pa/hpux32.$(OBJEXT)
|
||||
|
@ -934,6 +957,8 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/ffi.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/n32.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/o32.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/moxie/$(DEPDIR)/eabi.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/moxie/$(DEPDIR)/ffi.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/ffi.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/hpux32.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/linux.Plo@am__quote@
|
||||
|
@ -1029,6 +1054,7 @@ clean-libtool:
|
|||
-rm -rf src/m32r/.libs src/m32r/_libs
|
||||
-rm -rf src/m68k/.libs src/m68k/_libs
|
||||
-rm -rf src/mips/.libs src/mips/_libs
|
||||
-rm -rf src/moxie/.libs src/moxie/_libs
|
||||
-rm -rf src/pa/.libs src/pa/_libs
|
||||
-rm -rf src/powerpc/.libs src/powerpc/_libs
|
||||
-rm -rf src/s390/.libs src/s390/_libs
|
||||
|
@ -1232,7 +1258,7 @@ uninstall-pkgconfigDATA:
|
|||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
$(RECURSIVE_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
@fail= failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
|
@ -1257,7 +1283,7 @@ $(RECURSIVE_TARGETS):
|
|||
fi; test -z "$$fail"
|
||||
|
||||
$(RECURSIVE_CLEAN_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
@fail= failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
|
@ -1424,7 +1450,8 @@ distdir: $(DISTFILES)
|
|||
top_distdir="$(top_distdir)" distdir="$(distdir)" \
|
||||
dist-info
|
||||
-test -n "$(am__skip_mode_fix)" \
|
||||
|| find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
|
||||
|| find "$(distdir)" -type d ! -perm -755 \
|
||||
-exec chmod u+rwx,go+rx {} \; -o \
|
||||
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||
|
@ -1468,17 +1495,17 @@ dist dist-all: distdir
|
|||
distcheck: dist
|
||||
case '$(DIST_ARCHIVES)' in \
|
||||
*.tar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
|
||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||
*.tar.bz2*) \
|
||||
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
*.tar.lzma*) \
|
||||
unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
|
||||
lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
|
||||
*.tar.xz*) \
|
||||
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
|
||||
*.tar.Z*) \
|
||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||
*.shar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
|
||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
|
||||
*.zip*) \
|
||||
unzip $(distdir).zip ;;\
|
||||
esac
|
||||
|
@ -1587,6 +1614,8 @@ distclean-generic:
|
|||
-rm -f src/m68k/$(am__dirstamp)
|
||||
-rm -f src/mips/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f src/mips/$(am__dirstamp)
|
||||
-rm -f src/moxie/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f src/moxie/$(am__dirstamp)
|
||||
-rm -f src/pa/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f src/pa/$(am__dirstamp)
|
||||
-rm -f src/powerpc/$(DEPDIR)/$(am__dirstamp)
|
||||
|
@ -1612,7 +1641,7 @@ clean-am: clean-aminfo clean-generic clean-libLTLIBRARIES \
|
|||
|
||||
distclean: distclean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -rf src/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/x86/$(DEPDIR)
|
||||
-rm -rf src/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/x86/$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-hdr distclean-libtool distclean-tags
|
||||
|
@ -1732,7 +1761,7 @@ installcheck-am:
|
|||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -rf $(top_srcdir)/autom4te.cache
|
||||
-rm -rf src/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/x86/$(DEPDIR)
|
||||
-rm -rf src/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/x86/$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-aminfo \
|
||||
maintainer-clean-generic maintainer-clean-vti
|
||||
|
|
|
@ -75,6 +75,7 @@ tested:
|
|||
| X86 | Linux |
|
||||
| X86 | Mac OSX |
|
||||
| X86 | OpenBSD |
|
||||
| X86 | OS/2 |
|
||||
| X86 | Solaris |
|
||||
| X86 | Windows/Cygwin |
|
||||
| X86 | Windows/MingW |
|
||||
|
@ -113,9 +114,13 @@ It's also possible to build libffi on Windows platforms with
|
|||
Microsoft's Visual C++ compiler. In this case, use the msvcc.sh
|
||||
wrapper script during configuration like so:
|
||||
|
||||
path/to/configure --enable-shared --enable-static \
|
||||
CC=path/to/msvcc.sh LD=link \
|
||||
CPP=\"cl -nologo -EP\"
|
||||
path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
|
||||
|
||||
For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
|
||||
You may also need to specify --build appropriately. When building with MSVC
|
||||
under a MingW environment, you may need to remove the line in configure
|
||||
that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
|
||||
present in MingW, and is not required when using MingW-style paths.)
|
||||
|
||||
Configure has many other options. Use "configure --help" to see them all.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# generated automatically by aclocal 1.11 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
|
@ -13,8 +13,8 @@
|
|||
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.63],,
|
||||
[m4_warning([this file was generated for autoconf 2.63.
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],,
|
||||
[m4_warning([this file was generated for autoconf 2.65.
|
||||
You have another version of autoconf. It may work, but is not guaranteed to.
|
||||
If you have problems, you may need to regenerate the build system entirely.
|
||||
To do so, use the procedure documented by the package, typically `autoreconf'.])])
|
||||
|
@ -7862,15 +7862,15 @@ m4_define([lt_dict_filter],
|
|||
|
||||
# Generated from ltversion.in.
|
||||
|
||||
# serial 3012 ltversion.m4
|
||||
# serial 3017 ltversion.m4
|
||||
# This file is part of GNU Libtool
|
||||
|
||||
m4_define([LT_PACKAGE_VERSION], [2.2.6])
|
||||
m4_define([LT_PACKAGE_REVISION], [1.3012])
|
||||
m4_define([LT_PACKAGE_VERSION], [2.2.6b])
|
||||
m4_define([LT_PACKAGE_REVISION], [1.3017])
|
||||
|
||||
AC_DEFUN([LTVERSION_VERSION],
|
||||
[macro_version='2.2.6'
|
||||
macro_revision='1.3012'
|
||||
[macro_version='2.2.6b'
|
||||
macro_revision='1.3017'
|
||||
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
|
||||
_LT_DECL(, macro_revision, 0)
|
||||
])
|
||||
|
@ -7983,7 +7983,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
|
|||
[am__api_version='1.11'
|
||||
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
|
||||
dnl require some minimum version. Point them to the right macro.
|
||||
m4_if([$1], [1.11], [],
|
||||
m4_if([$1], [1.11.1], [],
|
||||
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
|
||||
])
|
||||
|
||||
|
@ -7999,7 +7999,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
|
|||
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
|
||||
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
|
||||
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
|
||||
[AM_AUTOMAKE_VERSION([1.11])dnl
|
||||
[AM_AUTOMAKE_VERSION([1.11.1])dnl
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -16,10 +16,14 @@ AM_INIT_AUTOMAKE
|
|||
# We must force CC to /not/ be precious variables; otherwise
|
||||
# the wrong, non-multilib-adjusted value will be used in multilibs.
|
||||
# As a side effect, we have to subst CFLAGS ourselves.
|
||||
# Also save and restore CFLAGS, since AC_PROG_CC will come up with
|
||||
# defaults of its own if none are provided.
|
||||
|
||||
m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
|
||||
m4_define([_AC_ARG_VAR_PRECIOUS],[])
|
||||
save_CFLAGS=$CFLAGS
|
||||
AC_PROG_CC
|
||||
CFLAGS=$save_CFLAGS
|
||||
m4_undefine([_AC_ARG_VAR_PRECIOUS])
|
||||
m4_rename([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
|
||||
|
||||
|
@ -43,7 +47,7 @@ TARGETDIR="unknown"
|
|||
case "$host" in
|
||||
alpha*-*-*)
|
||||
TARGET=ALPHA; TARGETDIR=alpha;
|
||||
# Support 128-bit long double, changable via command-line switch.
|
||||
# Support 128-bit long double, changeable via command-line switch.
|
||||
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
|
||||
;;
|
||||
|
||||
|
@ -120,6 +124,10 @@ case "$host" in
|
|||
TARGET=MIPS; TARGETDIR=mips
|
||||
;;
|
||||
|
||||
moxie-*-*)
|
||||
TARGET=MOXIE; TARGETDIR=moxie
|
||||
;;
|
||||
|
||||
powerpc*-*-linux* | powerpc-*-sysv*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
|
@ -185,6 +193,7 @@ AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
|
|||
AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
|
||||
AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
|
||||
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
|
||||
AM_CONDITIONAL(MOXIE, test x$TARGET = xMOXIE)
|
||||
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
|
||||
AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
|
||||
AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
|
||||
|
@ -270,7 +279,7 @@ if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64
|
|||
libffi_cv_as_x86_pcrel, [
|
||||
libffi_cv_as_x86_pcrel=yes
|
||||
echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
|
||||
if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
|
||||
if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
|
||||
libffi_cv_as_x86_pcrel=no
|
||||
fi
|
||||
])
|
||||
|
@ -278,6 +287,32 @@ if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64
|
|||
AC_DEFINE(HAVE_AS_X86_PCREL, 1,
|
||||
[Define if your assembler supports PC relative relocs.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([assembler .ascii pseudo-op support],
|
||||
libffi_cv_as_ascii_pseudo_op, [
|
||||
libffi_cv_as_ascii_pseudo_op=unknown
|
||||
# Check if we have .ascii
|
||||
AC_TRY_COMPILE([asm (".ascii \"string\"");],,
|
||||
[libffi_cv_as_ascii_pseudo_op=yes],
|
||||
[libffi_cv_as_ascii_pseudo_op=no])
|
||||
])
|
||||
if test "x$libffi_cv_as_ascii_pseudo_op" = xyes; then
|
||||
AC_DEFINE(HAVE_AS_ASCII_PSEUDO_OP, 1,
|
||||
[Define if your assembler supports .ascii.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([assembler .string pseudo-op support],
|
||||
libffi_cv_as_string_pseudo_op, [
|
||||
libffi_cv_as_string_pseudo_op=unknown
|
||||
# Check if we have .string
|
||||
AC_TRY_COMPILE([asm (".string \"string\"");],,
|
||||
[libffi_cv_as_string_pseudo_op=yes],
|
||||
[libffi_cv_as_string_pseudo_op=no])
|
||||
])
|
||||
if test "x$libffi_cv_as_string_pseudo_op" = xyes; then
|
||||
AC_DEFINE(HAVE_AS_STRING_PSEUDO_OP, 1,
|
||||
[Define if your assembler supports .string.])
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$target" in
|
||||
|
@ -288,6 +323,21 @@ case "$target" in
|
|||
;;
|
||||
esac
|
||||
|
||||
if test x$TARGET = xX86_64; then
|
||||
AC_CACHE_CHECK([assembler supports unwind section type],
|
||||
libffi_cv_as_x86_64_unwind_section_type, [
|
||||
libffi_cv_as_x86_64_unwind_section_type=yes
|
||||
echo '.section .eh_frame,"a",@unwind' > conftest.s
|
||||
if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
|
||||
libffi_cv_as_x86_64_unwind_section_type=no
|
||||
fi
|
||||
])
|
||||
if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then
|
||||
AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
|
||||
[Define if your assembler supports unwind section type.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([whether .eh_frame section should be read-only],
|
||||
libffi_cv_ro_eh_frame, [
|
||||
libffi_cv_ro_eh_frame=no
|
||||
|
@ -354,6 +404,7 @@ AC_ARG_ENABLE(debug,
|
|||
if test "$enable_debug" = "yes"; then
|
||||
AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.])
|
||||
fi)
|
||||
AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
|
||||
|
||||
AC_ARG_ENABLE(structs,
|
||||
[ --disable-structs omit code for struct support],
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче