зеркало из https://github.com/mozilla/gecko-dev.git
Merge mc->Maple
This commit is contained in:
Коммит
1d55c5f593
|
@ -696,6 +696,16 @@ nsApplicationAccessibleWrap::Unload()
|
|||
// }
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessibleWrap::GetName(nsAString& aName)
|
||||
{
|
||||
// ATK doesn't provide a way to obtain an application name (for example,
|
||||
// Firefox or Thunderbird) like IA2 does. Thus let's return an application
|
||||
// name as accessible name that was used to get a branding name (for example,
|
||||
// Minefield aka nightly Firefox or Daily aka nightly Thunderbird).
|
||||
return GetAppName(aName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessibleWrap::GetNativeInterface(void **aOutAccessible)
|
||||
{
|
||||
|
|
|
@ -57,6 +57,8 @@ public:
|
|||
virtual bool Init();
|
||||
|
||||
// nsAccessible
|
||||
NS_IMETHOD GetName(nsAString &aName);
|
||||
|
||||
virtual bool AppendChild(nsAccessible* aChild);
|
||||
virtual bool RemoveChild(nsAccessible* aChild);
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "States.h"
|
||||
|
||||
#include "nsIClipboard.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
@ -1153,15 +1154,14 @@ nsHyperTextAccessible::GetTextAttributes(bool aIncludeDefAttrs,
|
|||
// Compute spelling attributes on text accessible only.
|
||||
nsIFrame *offsetFrame = accAtOffset->GetFrame();
|
||||
if (offsetFrame && offsetFrame->GetType() == nsGkAtoms::textFrame) {
|
||||
nsCOMPtr<nsIDOMNode> node = accAtOffset->DOMNode();
|
||||
|
||||
PRInt32 nodeOffset = 0;
|
||||
nsresult rv = RenderedToContentOffset(offsetFrame, offsetInAcc,
|
||||
&nodeOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Set 'misspelled' text attribute.
|
||||
rv = GetSpellTextAttribute(node, nodeOffset, &startOffset, &endOffset,
|
||||
rv = GetSpellTextAttribute(accAtOffset->GetNode(), nodeOffset,
|
||||
&startOffset, &endOffset,
|
||||
aAttributes ? *aAttributes : nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
@ -1789,13 +1789,11 @@ nsHyperTextAccessible::GetSelectionDOMRanges(PRInt16 aType,
|
|||
|
||||
// Remove collapsed ranges
|
||||
PRUint32 numRanges = aRanges->Length();
|
||||
for (PRUint32 count = 0; count < numRanges; count ++) {
|
||||
bool isCollapsed = false;
|
||||
(*aRanges)[count]->GetCollapsed(&isCollapsed);
|
||||
if (isCollapsed) {
|
||||
aRanges->RemoveElementAt(count);
|
||||
for (PRUint32 idx = 0; idx < numRanges; idx ++) {
|
||||
if ((*aRanges)[idx]->Collapsed()) {
|
||||
aRanges->RemoveElementAt(idx);
|
||||
--numRanges;
|
||||
--count;
|
||||
--idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1837,29 +1835,19 @@ nsHyperTextAccessible::GetSelectionBounds(PRInt32 aSelectionNum,
|
|||
|
||||
nsRange* range = ranges[aSelectionNum];
|
||||
|
||||
// Get start point
|
||||
nsCOMPtr<nsIDOMNode> startDOMNode;
|
||||
range->GetStartContainer(getter_AddRefs(startDOMNode));
|
||||
nsCOMPtr<nsINode> startNode(do_QueryInterface(startDOMNode));
|
||||
PRInt32 startOffset = 0;
|
||||
range->GetStartOffset(&startOffset);
|
||||
// Get start and end points.
|
||||
nsINode* startNode = range->GetStartParent();
|
||||
nsINode* endNode = range->GetEndParent();
|
||||
PRInt32 startOffset = range->StartOffset(), endOffset = range->EndOffset();
|
||||
|
||||
// Get end point
|
||||
nsCOMPtr<nsIDOMNode> endDOMNode;
|
||||
range->GetEndContainer(getter_AddRefs(endDOMNode));
|
||||
nsCOMPtr<nsINode> endNode(do_QueryInterface(endDOMNode));
|
||||
PRInt32 endOffset = 0;
|
||||
range->GetEndOffset(&endOffset);
|
||||
|
||||
PRInt16 rangeCompareResult = 0;
|
||||
nsresult rv = range->CompareBoundaryPoints(nsIDOMRange::START_TO_END, range,
|
||||
&rangeCompareResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (rangeCompareResult < 0) {
|
||||
// Make sure start is before end, by swapping offsets
|
||||
// This occurs when the user selects backwards in the text
|
||||
startNode.swap(endNode);
|
||||
// Make sure start is before end, by swapping DOM points. This occurs when
|
||||
// the user selects backwards in the text.
|
||||
PRInt32 rangeCompare = nsContentUtils::ComparePoints(endNode, endOffset,
|
||||
startNode, startOffset);
|
||||
if (rangeCompare < 0) {
|
||||
nsINode* tempNode = startNode;
|
||||
startNode = endNode;
|
||||
endNode = tempNode;
|
||||
PRInt32 tempOffset = startOffset;
|
||||
startOffset = endOffset;
|
||||
endOffset = tempOffset;
|
||||
|
@ -2324,25 +2312,17 @@ nsHyperTextAccessible::RangeBoundToHypertextOffset(nsRange *aRange,
|
|||
bool aIsStartHTOffset,
|
||||
PRInt32 *aHTOffset)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> DOMNode;
|
||||
nsINode* node = nsnull;
|
||||
PRInt32 nodeOffset = 0;
|
||||
|
||||
nsresult rv;
|
||||
if (aIsStartBound) {
|
||||
rv = aRange->GetStartContainer(getter_AddRefs(DOMNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aRange->GetStartOffset(&nodeOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
node = aRange->GetStartParent();
|
||||
nodeOffset = aRange->StartOffset();
|
||||
} else {
|
||||
rv = aRange->GetEndContainer(getter_AddRefs(DOMNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aRange->GetEndOffset(&nodeOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
node = aRange->GetEndParent();
|
||||
nodeOffset = aRange->EndOffset();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(DOMNode));
|
||||
nsAccessible *startAcc =
|
||||
DOMPointToHypertextOffset(node, nodeOffset, aHTOffset);
|
||||
|
||||
|
@ -2354,7 +2334,7 @@ nsHyperTextAccessible::RangeBoundToHypertextOffset(nsRange *aRange,
|
|||
|
||||
// nsHyperTextAccessible
|
||||
nsresult
|
||||
nsHyperTextAccessible::GetSpellTextAttribute(nsIDOMNode *aNode,
|
||||
nsHyperTextAccessible::GetSpellTextAttribute(nsINode* aNode,
|
||||
PRInt32 aNodeOffset,
|
||||
PRInt32 *aHTStartOffset,
|
||||
PRInt32 *aHTEndOffset,
|
||||
|
@ -2367,25 +2347,19 @@ nsHyperTextAccessible::GetSpellTextAttribute(nsIDOMNode *aNode,
|
|||
if (!rangeCount)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> DOMNode = do_QueryInterface(aNode);
|
||||
for (PRUint32 index = 0; index < rangeCount; index++) {
|
||||
nsRange* range = ranges[index];
|
||||
|
||||
PRInt16 result;
|
||||
nsresult rv = range->ComparePoint(aNode, aNodeOffset, &result);
|
||||
nsresult rv = range->ComparePoint(DOMNode, aNodeOffset, &result);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// ComparePoint checks boundary points, but we need to check that
|
||||
// text at aNodeOffset is inside the range.
|
||||
// See also bug 460690.
|
||||
if (result == 0) {
|
||||
nsCOMPtr<nsIDOMNode> end;
|
||||
rv = range->GetEndContainer(getter_AddRefs(end));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRInt32 endOffset;
|
||||
rv = range->GetEndOffset(&endOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aNode == end && aNodeOffset == endOffset) {
|
||||
if (aNode == range->GetEndParent() && aNodeOffset == range->EndOffset())
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 1) { // range is before point
|
||||
|
|
|
@ -409,7 +409,7 @@ protected:
|
|||
* @param aEndOffset [in, out] the end offset
|
||||
* @param aAttributes [out, optional] result attributes
|
||||
*/
|
||||
nsresult GetSpellTextAttribute(nsIDOMNode *aNode, PRInt32 aNodeOffset,
|
||||
nsresult GetSpellTextAttribute(nsINode* aNode, PRInt32 aNodeOffset,
|
||||
PRInt32 *aStartOffset,
|
||||
PRInt32 *aEndOffset,
|
||||
nsIPersistentProperties *aAttributes);
|
||||
|
|
|
@ -15,41 +15,46 @@
|
|||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
var accessible = getApplicationAccessible();
|
||||
if (!accessible) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
var accessible = getApplicationAccessible();
|
||||
if (!accessible) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// nsIAccessible::name
|
||||
var bundleServ = Components.classes["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Components.interfaces.nsIStringBundleService);
|
||||
var bundle = bundleServ.createBundle("chrome://branding/locale/brand.properties");
|
||||
var bundleServ =
|
||||
Components.classes["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Components.interfaces.nsIStringBundleService);
|
||||
var brandBundle =
|
||||
bundleServ.createBundle("chrome://branding/locale/brand.properties");
|
||||
|
||||
var applicationName = "";
|
||||
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].
|
||||
getService(Components.interfaces.nsIXULAppInfo);
|
||||
|
||||
// nsIAccessible::name
|
||||
var applicationName = "";
|
||||
if (LINUX || SOLARIS) {
|
||||
applicationName = appInfo.name;
|
||||
} else {
|
||||
try {
|
||||
applicationName = bundle.GetStringFromName("brandShortName");
|
||||
} catch(e) {
|
||||
applicationName = brandBundle.GetStringFromName("brandShortName");
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
if (applicationName == "")
|
||||
applicationName = "Gecko based application";
|
||||
applicationName = "Gecko based application";
|
||||
}
|
||||
is (accessible.name, applicationName, "wrong application accessible name");
|
||||
|
||||
is (accessible.name, applicationName, "wrong application accessible name");
|
||||
// nsIAccessibleApplication
|
||||
is(accessible.appName, appInfo.name, "Wrong application name");
|
||||
is(accessible.appVersion, appInfo.version, "Wrong application version");
|
||||
is(accessible.platformName, "Gecko", "Wrong platform name");
|
||||
is(accessible.platformVersion, appInfo.platformVersion,
|
||||
"Wrong platform version");
|
||||
|
||||
// nsIAccessibleApplication
|
||||
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].
|
||||
getService(Components.interfaces.nsIXULAppInfo);
|
||||
|
||||
is(accessible.appName, appInfo.name, "Wrong application name");
|
||||
is(accessible.appVersion, appInfo.version, "Wrong application version");
|
||||
is(accessible.platformName, "Gecko", "Wrong platform name");
|
||||
is(accessible.platformVersion, appInfo.platformVersion,
|
||||
"Wrong platform version");
|
||||
|
||||
SimpleTest.finish();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
|
|
|
@ -1563,49 +1563,6 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
|
|||
gHomeButton.updateTooltip(homeButton);
|
||||
gHomeButton.updatePersonalToolbarStyle(homeButton);
|
||||
|
||||
#ifdef HAVE_SHELL_SERVICE
|
||||
// Perform default browser checking (after window opens).
|
||||
var shell = getShellService();
|
||||
if (shell) {
|
||||
#ifdef DEBUG
|
||||
var shouldCheck = false;
|
||||
#else
|
||||
var shouldCheck = shell.shouldCheckDefaultBrowser;
|
||||
#endif
|
||||
var willRecoverSession = false;
|
||||
try {
|
||||
var ss = Cc["@mozilla.org/browser/sessionstartup;1"].
|
||||
getService(Ci.nsISessionStartup);
|
||||
willRecoverSession =
|
||||
(ss.sessionType == Ci.nsISessionStartup.RECOVER_SESSION);
|
||||
}
|
||||
catch (ex) { /* never mind; suppose SessionStore is broken */ }
|
||||
if (shouldCheck && !shell.isDefaultBrowser(true) && !willRecoverSession) {
|
||||
// Delay the set-default-browser prompt so it doesn't block
|
||||
// initialisation of the session store service.
|
||||
setTimeout(function () {
|
||||
var brandBundle = document.getElementById("bundle_brand");
|
||||
var shellBundle = document.getElementById("bundle_shell");
|
||||
|
||||
var brandShortName = brandBundle.getString("brandShortName");
|
||||
var promptTitle = shellBundle.getString("setDefaultBrowserTitle");
|
||||
var promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage",
|
||||
[brandShortName]);
|
||||
var checkboxLabel = shellBundle.getFormattedString("setDefaultBrowserDontAsk",
|
||||
[brandShortName]);
|
||||
var checkEveryTime = { value: shouldCheck };
|
||||
var ps = Services.prompt;
|
||||
var rv = ps.confirmEx(window, promptTitle, promptMessage,
|
||||
ps.STD_YES_NO_BUTTONS,
|
||||
null, null, null, checkboxLabel, checkEveryTime);
|
||||
if (rv == 0)
|
||||
shell.setDefaultBrowser(true, false);
|
||||
shell.shouldCheckDefaultBrowser = checkEveryTime.value;
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// BiDi UI
|
||||
gBidiUI = isBidiEnabled();
|
||||
if (gBidiUI) {
|
||||
|
@ -5374,6 +5331,7 @@ function setToolbarVisibility(toolbar, isVisible) {
|
|||
|
||||
var TabsOnTop = {
|
||||
init: function TabsOnTop_init() {
|
||||
this._initialized = true;
|
||||
this.syncUI();
|
||||
Services.prefs.addObserver(this._prefName, this, false);
|
||||
},
|
||||
|
@ -5387,6 +5345,9 @@ var TabsOnTop = {
|
|||
},
|
||||
|
||||
syncUI: function () {
|
||||
if (!this._initialized)
|
||||
return;
|
||||
|
||||
let userEnabled = Services.prefs.getBoolPref(this._prefName);
|
||||
let enabled = userEnabled && gBrowser.tabContainer.visible;
|
||||
|
||||
|
|
|
@ -426,6 +426,49 @@ BrowserGlue.prototype = {
|
|||
|
||||
let keywordURLUserSet = Services.prefs.prefHasUserValue("keyword.URL");
|
||||
Services.telemetry.getHistogramById("FX_KEYWORD_URL_USERSET").add(keywordURLUserSet);
|
||||
|
||||
// Perform default browser checking.
|
||||
var shell;
|
||||
try {
|
||||
shell = Components.classes["@mozilla.org/browser/shell-service;1"]
|
||||
.getService(Components.interfaces.nsIShellService);
|
||||
} catch (e) { }
|
||||
if (shell) {
|
||||
#ifdef DEBUG
|
||||
var shouldCheck = false;
|
||||
#else
|
||||
var shouldCheck = shell.shouldCheckDefaultBrowser;
|
||||
#endif
|
||||
var willRecoverSession = false;
|
||||
try {
|
||||
var ss = Cc["@mozilla.org/browser/sessionstartup;1"].
|
||||
getService(Ci.nsISessionStartup);
|
||||
willRecoverSession =
|
||||
(ss.sessionType == Ci.nsISessionStartup.RECOVER_SESSION);
|
||||
}
|
||||
catch (ex) { /* never mind; suppose SessionStore is broken */ }
|
||||
if (shouldCheck && !shell.isDefaultBrowser(true) && !willRecoverSession) {
|
||||
Services.tm.mainThread.dispatch(function() {
|
||||
var brandBundle = win.document.getElementById("bundle_brand");
|
||||
var shellBundle = win.document.getElementById("bundle_shell");
|
||||
|
||||
var brandShortName = brandBundle.getString("brandShortName");
|
||||
var promptTitle = shellBundle.getString("setDefaultBrowserTitle");
|
||||
var promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage",
|
||||
[brandShortName]);
|
||||
var checkboxLabel = shellBundle.getFormattedString("setDefaultBrowserDontAsk",
|
||||
[brandShortName]);
|
||||
var checkEveryTime = { value: shouldCheck };
|
||||
var ps = Services.prompt;
|
||||
var rv = ps.confirmEx(win, promptTitle, promptMessage,
|
||||
ps.STD_YES_NO_BUTTONS,
|
||||
null, null, null, checkboxLabel, checkEveryTime);
|
||||
if (rv == 0)
|
||||
shell.setDefaultBrowser(true, false);
|
||||
shell.shouldCheckDefaultBrowser = checkEveryTime.value;
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onQuitRequest: function BG__onQuitRequest(aCancelQuit, aQuitType) {
|
||||
|
|
|
@ -167,73 +167,33 @@ PlacesViewBase.prototype = {
|
|||
},
|
||||
|
||||
_cleanPopup: function PVB_cleanPopup(aPopup) {
|
||||
// Remove places popup children and update markers to keep track of
|
||||
// their indices.
|
||||
let start = aPopup._startMarker != -1 ? aPopup._startMarker + 1 : 0;
|
||||
let end = aPopup._endMarker != -1 ? aPopup._endMarker :
|
||||
aPopup.childNodes.length;
|
||||
let items = [];
|
||||
|
||||
// Automatically adjust the start and the end markers.
|
||||
let firstNonStaticNodeFound = false;
|
||||
for (let i = start; i < end; ++i) {
|
||||
let item = aPopup.childNodes[i];
|
||||
if (item.getAttribute("builder") == "end") {
|
||||
// we need to do this for menus that have static content at the end but
|
||||
// are initially empty, eg. the history menu, we need to know where to
|
||||
// start inserting new items.
|
||||
aPopup._endMarker = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (item._placesNode) {
|
||||
items.push(item);
|
||||
firstNonStaticNodeFound = true;
|
||||
}
|
||||
else {
|
||||
// This is static content.
|
||||
if (!firstNonStaticNodeFound) {
|
||||
// We are at the beginning of the popup, in static content.
|
||||
// The markers are initialized in menu.xml, in the base binding.
|
||||
aPopup._startMarker++;
|
||||
}
|
||||
else {
|
||||
// We are at the end of the popup, after places nodes
|
||||
aPopup._endMarker = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < items.length; ++i) {
|
||||
aPopup.removeChild(items[i]);
|
||||
if (aPopup._endMarker != -1)
|
||||
aPopup._endMarker--;
|
||||
// Remove Places nodes from the popup.
|
||||
let child = aPopup._startMarker;
|
||||
while (child.nextSibling != aPopup._endMarker) {
|
||||
if (child.nextSibling._placesNode)
|
||||
aPopup.removeChild(child.nextSibling);
|
||||
else
|
||||
child = child.nextSibling;
|
||||
}
|
||||
},
|
||||
|
||||
_rebuildPopup: function PVB__rebuildPopup(aPopup) {
|
||||
this._cleanPopup(aPopup);
|
||||
|
||||
let resultNode = aPopup._placesNode;
|
||||
if (!resultNode.containerOpen)
|
||||
return;
|
||||
|
||||
if (resultNode._feedURI) {
|
||||
aPopup.removeAttribute("emptyplacesresult");
|
||||
if (aPopup._emptyMenuItem) {
|
||||
aPopup._emptyMenuItem.hidden = true;
|
||||
}
|
||||
this._setEmptyPopupStatus(aPopup, false);
|
||||
aPopup._built = true;
|
||||
this._populateLivemarkPopup(aPopup);
|
||||
return;
|
||||
}
|
||||
|
||||
this._cleanPopup(aPopup);
|
||||
|
||||
let cc = resultNode.childCount;
|
||||
if (cc > 0) {
|
||||
aPopup.removeAttribute("emptyplacesresult");
|
||||
if (aPopup._emptyMenuItem)
|
||||
aPopup._emptyMenuItem.hidden = true;
|
||||
this._setEmptyPopupStatus(aPopup, false);
|
||||
|
||||
for (let i = 0; i < cc; ++i) {
|
||||
let child = resultNode.getChild(i);
|
||||
|
@ -241,11 +201,7 @@ PlacesViewBase.prototype = {
|
|||
}
|
||||
}
|
||||
else {
|
||||
aPopup.setAttribute("emptyplacesresult", "true");
|
||||
// This menu is empty. If there is no static content, add
|
||||
// an element to show it is empty.
|
||||
if (aPopup._startMarker == -1 && aPopup._endMarker == -1)
|
||||
this._showEmptyMenuItem(aPopup);
|
||||
this._setEmptyPopupStatus(aPopup, true);
|
||||
}
|
||||
aPopup._built = true;
|
||||
},
|
||||
|
@ -260,17 +216,28 @@ PlacesViewBase.prototype = {
|
|||
aChild.parentNode.removeChild(aChild);
|
||||
},
|
||||
|
||||
_showEmptyMenuItem: function PVB__showEmptyMenuItem(aPopup) {
|
||||
if (aPopup._emptyMenuItem) {
|
||||
aPopup._emptyMenuItem.hidden = false;
|
||||
return;
|
||||
_setEmptyPopupStatus:
|
||||
function PVB__setEmptyPopupStatus(aPopup, aEmpty) {
|
||||
if (!aPopup._emptyMenuitem) {
|
||||
let label = PlacesUIUtils.getString("bookmarksMenuEmptyFolder");
|
||||
aPopup._emptyMenuitem = document.createElement("menuitem");
|
||||
aPopup._emptyMenuitem.setAttribute("label", label);
|
||||
aPopup._emptyMenuitem.setAttribute("disabled", true);
|
||||
}
|
||||
|
||||
let label = PlacesUIUtils.getString("bookmarksMenuEmptyFolder");
|
||||
aPopup._emptyMenuItem = document.createElement("menuitem");
|
||||
aPopup._emptyMenuItem.setAttribute("label", label);
|
||||
aPopup._emptyMenuItem.setAttribute("disabled", true);
|
||||
aPopup.appendChild(aPopup._emptyMenuItem);
|
||||
if (aEmpty) {
|
||||
aPopup.setAttribute("emptyplacesresult", "true");
|
||||
// Don't add the menuitem if there is static content.
|
||||
if (!aPopup._startMarker.previousSibling &&
|
||||
!aPopup._endMarker.nextSibling)
|
||||
aPopup.insertBefore(aPopup._emptyMenuitem, aPopup._endMarker);
|
||||
}
|
||||
else {
|
||||
aPopup.removeAttribute("emptyplacesresult");
|
||||
try {
|
||||
aPopup.removeChild(aPopup._emptyMenuitem);
|
||||
} catch (ex) {}
|
||||
}
|
||||
},
|
||||
|
||||
_createMenuItemForPlacesNode:
|
||||
|
@ -308,6 +275,12 @@ PlacesViewBase.prototype = {
|
|||
function (aStatus, aLivemark) {
|
||||
if (Components.isSuccessCode(aStatus)) {
|
||||
element.setAttribute("livemark", "true");
|
||||
#ifdef XP_MACOSX
|
||||
// OS X native menubar doesn't track list-style-images since
|
||||
// it doesn't have a frame (bug 733415). Thus enforce updating.
|
||||
element.setAttribute("image", "");
|
||||
element.removeAttribute("image");
|
||||
#endif
|
||||
// Set an expando on the node, controller will use it to build
|
||||
// its metadata.
|
||||
aPlacesNode._feedURI = aLivemark.feedURI;
|
||||
|
@ -319,12 +292,11 @@ PlacesViewBase.prototype = {
|
|||
|
||||
let popup = document.createElement("menupopup");
|
||||
popup._placesNode = PlacesUtils.asContainer(aPlacesNode);
|
||||
if (this._nativeView) {
|
||||
popup._startMarker = -1;
|
||||
popup._endMarker = -1;
|
||||
}
|
||||
else
|
||||
|
||||
if (!this._nativeView) {
|
||||
popup.setAttribute("placespopup", "true");
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// No context menu on mac.
|
||||
popup.setAttribute("context", "placesContext");
|
||||
|
@ -354,26 +326,8 @@ PlacesViewBase.prototype = {
|
|||
_insertNewItemToPopup:
|
||||
function PVB__insertNewItemToPopup(aNewChild, aPopup, aBefore) {
|
||||
let element = this._createMenuItemForPlacesNode(aNewChild);
|
||||
|
||||
if (aBefore) {
|
||||
aPopup.insertBefore(element, aBefore);
|
||||
}
|
||||
else {
|
||||
// Add the new element to the menu. If there is static content at
|
||||
// the end of the menu, add the element before that. Otherwise,
|
||||
// just add to the end.
|
||||
if (aPopup._endMarker != -1) {
|
||||
let lastElt = aPopup.childNodes[aPopup._endMarker];
|
||||
aPopup.insertBefore(element, lastElt);
|
||||
}
|
||||
else {
|
||||
aPopup.appendChild(element);
|
||||
}
|
||||
}
|
||||
|
||||
if (aPopup._endMarker != -1)
|
||||
aPopup._endMarker++;
|
||||
|
||||
let before = aBefore || aPopup._endMarker;
|
||||
aPopup.insertBefore(element, before);
|
||||
return element;
|
||||
},
|
||||
|
||||
|
@ -384,10 +338,8 @@ PlacesViewBase.prototype = {
|
|||
if (!siteUrl && aPopup._siteURIMenuitem) {
|
||||
aPopup.removeChild(aPopup._siteURIMenuitem);
|
||||
aPopup._siteURIMenuitem = null;
|
||||
aPopup._startMarker--;
|
||||
aPopup.removeChild(aPopup._siteURIMenuseparator);
|
||||
aPopup._siteURIMenuseparator = null;
|
||||
aPopup._startMarker--;
|
||||
}
|
||||
else if (siteUrl && !aPopup._siteURIMenuitem) {
|
||||
// Add "Open (Feed Name)" menuitem.
|
||||
|
@ -407,14 +359,10 @@ PlacesViewBase.prototype = {
|
|||
PlacesUIUtils.getFormattedString("menuOpenLivemarkOrigin.label",
|
||||
[aPopup.parentNode.getAttribute("label")])
|
||||
aPopup._siteURIMenuitem.setAttribute("label", label);
|
||||
aPopup.insertBefore(aPopup._siteURIMenuitem,
|
||||
aPopup.childNodes.item(aPopup._startMarker + 1));
|
||||
aPopup._startMarker++;
|
||||
aPopup.insertBefore(aPopup._siteURIMenuitem, aPopup._startMarker);
|
||||
|
||||
aPopup._siteURIMenuseparator = document.createElement("menuseparator");
|
||||
aPopup.insertBefore(aPopup._siteURIMenuseparator,
|
||||
aPopup.childNodes.item(aPopup._startMarker + 1));
|
||||
aPopup._startMarker++;
|
||||
aPopup.insertBefore(aPopup._siteURIMenuseparator, aPopup._startMarker);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -427,7 +375,6 @@ PlacesViewBase.prototype = {
|
|||
*/
|
||||
_setLivemarkStatusMenuItem:
|
||||
function PVB_setLivemarkStatusMenuItem(aPopup, aStatus) {
|
||||
let itemId = aPopup._placesNode.itemId;
|
||||
let statusMenuitem = aPopup._statusMenuitem;
|
||||
let stringId = "";
|
||||
if (aStatus == Ci.mozILivemark.STATUS_LOADING)
|
||||
|
@ -439,12 +386,11 @@ PlacesViewBase.prototype = {
|
|||
// Create the status menuitem and cache it in the popup object.
|
||||
statusMenuitem = document.createElement("menuitem");
|
||||
statusMenuitem.setAttribute("livemarkStatus", stringId);
|
||||
statusMenuitem.className = "livemarkstatus-menuitem";
|
||||
statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
|
||||
statusMenuitem.setAttribute("disabled", true);
|
||||
aPopup.insertBefore(statusMenuitem,
|
||||
aPopup.childNodes.item(aPopup._startMarker + 1));
|
||||
aPopup.insertBefore(statusMenuitem, aPopup._startMarker.nextSibling);
|
||||
aPopup._statusMenuitem = statusMenuitem;
|
||||
aPopup._startMarker++;
|
||||
}
|
||||
else if (stringId &&
|
||||
statusMenuitem.getAttribute("livemarkStatus") != stringId) {
|
||||
|
@ -455,7 +401,6 @@ PlacesViewBase.prototype = {
|
|||
// The livemark has finished loading.
|
||||
aPopup.removeChild(aPopup._statusMenuitem);
|
||||
aPopup._statusMenuitem = null;
|
||||
aPopup._startMarker--;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -517,6 +462,12 @@ PlacesViewBase.prototype = {
|
|||
let menu = elt.parentNode;
|
||||
if (!menu.hasAttribute("livemark")) {
|
||||
menu.setAttribute("livemark", "true");
|
||||
#ifdef XP_MACOSX
|
||||
// OS X native menubar doesn't track list-style-images since
|
||||
// it doesn't have a frame (bug 733415). Thus enforce updating.
|
||||
menu.setAttribute("image", "");
|
||||
menu.removeAttribute("image");
|
||||
#endif
|
||||
}
|
||||
|
||||
PlacesUtils.livemarks.getLivemark(
|
||||
|
@ -580,13 +531,8 @@ PlacesViewBase.prototype = {
|
|||
// Figure out if we need to show the "<Empty>" menu-item.
|
||||
// TODO Bug 517701: This doesn't seem to handle the case of an empty
|
||||
// root.
|
||||
if (!parentElt.hasChildNodes() ||
|
||||
(parentElt.childNodes.length == 1 &&
|
||||
parentElt.firstChild == parentElt._emptyMenuItem))
|
||||
this._showEmptyMenuItem(parentElt);
|
||||
|
||||
if (parentElt._endMarker != -1)
|
||||
parentElt._endMarker--;
|
||||
if (parentElt._startMarker.nextSibling == parentElt._endMarker)
|
||||
this._setEmptyPopupStatus(parentElt, true);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -620,8 +566,9 @@ PlacesViewBase.prototype = {
|
|||
if (aPlacesNode.parent && aPlacesNode.parent._feedURI) {
|
||||
// Find the node in the parent.
|
||||
let popup = aPlacesNode.parent._DOMElement;
|
||||
for (let i = popup._startMarker; i < popup.childNodes.length; i++) {
|
||||
let child = popup.childNodes[i];
|
||||
for (let child = popup._startMarker.nextSibling;
|
||||
child != popup._endMarker;
|
||||
child = child.nextSibling) {
|
||||
if (child._placesNode && child._placesNode.uri == aPlacesNode.uri) {
|
||||
if (aCount)
|
||||
child.setAttribute("visited", "true");
|
||||
|
@ -649,11 +596,11 @@ PlacesViewBase.prototype = {
|
|||
if (!parentElt._built)
|
||||
return;
|
||||
|
||||
let index = parentElt._startMarker + 1 + aIndex;
|
||||
let index = Array.indexOf(parentElt.childNodes, parentElt._startMarker) +
|
||||
aIndex + 1;
|
||||
this._insertNewItemToPopup(aPlacesNode, parentElt,
|
||||
parentElt.childNodes[index]);
|
||||
if (parentElt._emptyMenuItem)
|
||||
parentElt._emptyMenuItem.hidden = true;
|
||||
this._setEmptyPopupStatus(parentElt, false);
|
||||
},
|
||||
|
||||
nodeMoved:
|
||||
|
@ -684,7 +631,8 @@ PlacesViewBase.prototype = {
|
|||
if (parentElt._built) {
|
||||
// Move the node.
|
||||
parentElt.removeChild(elt);
|
||||
let index = parentElt._startMarker + 1 + aNewIndex;
|
||||
let index = Array.indexOf(parentElt.childNodes, parentElt._startMarker) +
|
||||
aNewIndex + 1;
|
||||
parentElt.insertBefore(elt, parentElt.childNodes[index]);
|
||||
}
|
||||
},
|
||||
|
@ -821,11 +769,9 @@ PlacesViewBase.prototype = {
|
|||
if (aPopup._endOptOpenAllInTabs) {
|
||||
aPopup.removeChild(aPopup._endOptOpenAllInTabs);
|
||||
aPopup._endOptOpenAllInTabs = null;
|
||||
aPopup._endMarker--;
|
||||
|
||||
aPopup.removeChild(aPopup._endOptSeparator);
|
||||
aPopup._endOptSeparator = null;
|
||||
aPopup._endMarker--;
|
||||
}
|
||||
}
|
||||
else if (!aPopup._endOptOpenAllInTabs) {
|
||||
|
@ -833,7 +779,6 @@ PlacesViewBase.prototype = {
|
|||
aPopup._endOptSeparator = document.createElement("menuseparator");
|
||||
aPopup._endOptSeparator.className = "bookmarks-actions-menuseparator";
|
||||
aPopup.appendChild(aPopup._endOptSeparator);
|
||||
aPopup._endMarker++;
|
||||
|
||||
// Add the "Open All in Tabs" menuitem.
|
||||
aPopup._endOptOpenAllInTabs = document.createElement("menuitem");
|
||||
|
@ -846,13 +791,51 @@ PlacesViewBase.prototype = {
|
|||
aPopup._endOptOpenAllInTabs.setAttribute("label",
|
||||
gNavigatorBundle.getString("menuOpenAllInTabs.label"));
|
||||
aPopup.appendChild(aPopup._endOptOpenAllInTabs);
|
||||
aPopup._endMarker++;
|
||||
}
|
||||
},
|
||||
|
||||
_ensureMarkers: function PVB__ensureMarkers(aPopup) {
|
||||
if (aPopup._startMarker)
|
||||
return;
|
||||
|
||||
// _startMarker is an hidden menuseparator that lives before places nodes.
|
||||
aPopup._startMarker = document.createElement("menuseparator");
|
||||
aPopup._startMarker.hidden = true;
|
||||
aPopup.insertBefore(aPopup._startMarker, aPopup.firstChild);
|
||||
|
||||
// _endMarker is an hidden menuseparator that lives after places nodes.
|
||||
aPopup._endMarker = document.createElement("menuseparator");
|
||||
aPopup._endMarker.hidden = true;
|
||||
aPopup.appendChild(aPopup._endMarker);
|
||||
|
||||
// Move the markers to the right position.
|
||||
let firstNonStaticNodeFound = false;
|
||||
for (let i = 0; i < aPopup.childNodes.length; i++) {
|
||||
let child = aPopup.childNodes[i];
|
||||
// Menus that have static content at the end, but are initially empty,
|
||||
// use a special "builder" attribute to figure out where to start
|
||||
// inserting places nodes.
|
||||
if (child.getAttribute("builder") == "end") {
|
||||
aPopup.insertBefore(aPopup._endMarker, child);
|
||||
break;
|
||||
}
|
||||
|
||||
if (child._placesNode && !firstNonStaticNodeFound) {
|
||||
firstNonStaticNodeFound = true;
|
||||
aPopup.insertBefore(aPopup._startMarker, child);
|
||||
}
|
||||
}
|
||||
if (!firstNonStaticNodeFound) {
|
||||
aPopup.insertBefore(aPopup._startMarker, aPopup._endMarker);
|
||||
}
|
||||
},
|
||||
|
||||
_onPopupShowing: function PVB__onPopupShowing(aEvent) {
|
||||
// Avoid handling popupshowing of inner views.
|
||||
let popup = aEvent.originalTarget;
|
||||
|
||||
this._ensureMarkers(popup);
|
||||
|
||||
if (popup._placesNode && PlacesUIUtils.getViewForNode(popup) == this) {
|
||||
if (!popup._placesNode.containerOpen)
|
||||
popup._placesNode.containerOpen = true;
|
||||
|
@ -1808,8 +1791,6 @@ function PlacesMenu(aPopupShowingEvent, aPlace) {
|
|||
#ifdef XP_MACOSX
|
||||
if (this._viewElt.parentNode.localName == "menubar") {
|
||||
this._nativeView = true;
|
||||
this._rootElt._startMarker = -1;
|
||||
this._rootElt._endMarker = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1829,8 +1810,6 @@ PlacesMenu.prototype = {
|
|||
|
||||
_removeChild: function PM_removeChild(aChild) {
|
||||
PlacesViewBase.prototype._removeChild.apply(this, arguments);
|
||||
if (this._endMarker != -1)
|
||||
this._endMarker--;
|
||||
},
|
||||
|
||||
uninit: function PM_uninit() {
|
||||
|
|
|
@ -72,10 +72,6 @@
|
|||
"popup-internal-box");
|
||||
</field>
|
||||
|
||||
<!-- markers for start and end of valid places items -->
|
||||
<field name="_startMarker">-1</field>
|
||||
<field name="_endMarker">-1</field>
|
||||
|
||||
<!-- This is the view that manage the popup -->
|
||||
<field name="_rootView">PlacesUIUtils.getViewForNode(this);</field>
|
||||
|
||||
|
@ -83,17 +79,16 @@
|
|||
<method name="_hideDropIndicator">
|
||||
<parameter name="aEvent"/>
|
||||
<body><![CDATA[
|
||||
var target = aEvent.target;
|
||||
let target = aEvent.target;
|
||||
|
||||
// in some view we have _startMarker and _endMarker, we should not
|
||||
// draw the drop indicator outside of them
|
||||
var betweenMarkers = true;
|
||||
if (this._startMarker != -1 &&
|
||||
target.boxObject.y <= this.childNodes[this._startMarker].boxObject.y)
|
||||
betweenMarkers = false;
|
||||
if (this._endMarker != -1 &&
|
||||
target.boxObject.y >= this.childNodes[this._endMarker].boxObject.y)
|
||||
betweenMarkers = false;
|
||||
// Don't draw the drop indicator outside of markers.
|
||||
// The markers are hidden, since otherwise sometimes popups acquire
|
||||
// scrollboxes on OS X, so we can't use them directly.
|
||||
let firstChildTop = this._startMarker.nextSibling.boxObject.y;
|
||||
let lastChildBottom = this._endMarker.previousSibling.boxObject.y +
|
||||
this._endMarker.previousSibling.boxObject.height;
|
||||
let betweenMarkers = target.boxObject.y >= firstChildTop ||
|
||||
target.boxObject.y <= lastChildBottom;
|
||||
|
||||
// Hide the dropmarker if current node is not a Places node.
|
||||
return !(target && target._placesNode && betweenMarkers);
|
||||
|
|
|
@ -199,7 +199,7 @@ menuitem.bookmark-item {
|
|||
}
|
||||
|
||||
/* Bookmark items */
|
||||
.bookmark-item:not([container]) {
|
||||
.bookmark-item {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
|
||||
}
|
||||
|
||||
|
|
|
@ -229,15 +229,20 @@ toolbarbutton.bookmark-item > menupopup {
|
|||
list-style-image: url("chrome://global/skin/tree/folder.png");
|
||||
}
|
||||
|
||||
.query-item[container] {
|
||||
list-style-image: url("chrome://browser/skin/places/history.png");
|
||||
}
|
||||
|
||||
.bookmark-item[livemark] {
|
||||
.bookmark-item[container][livemark] {
|
||||
list-style-image: url("chrome://browser/skin/page-livemarks.png");
|
||||
}
|
||||
|
||||
.bookmark-item[query] {
|
||||
.bookmark-item[container][livemark] .bookmark-item {
|
||||
list-style-image: url("chrome://browser/skin/places/livemark-item.png");
|
||||
-moz-image-region: rect(0px, 16px, 16px, 0px);
|
||||
}
|
||||
|
||||
.bookmark-item[container][livemark] .bookmark-item[visited] {
|
||||
-moz-image-region: rect(0px, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
.bookmark-item[container][query] {
|
||||
list-style-image: url("chrome://browser/skin/places/query.png");
|
||||
}
|
||||
|
||||
|
@ -257,20 +262,23 @@ toolbarbutton.bookmark-item > menupopup {
|
|||
list-style-image: url("chrome://global/skin/tree/folder.png");
|
||||
}
|
||||
|
||||
.bookmark-item[livemark] .menuitem-iconic {
|
||||
list-style-image: url("chrome://browser/skin/places/livemark-item.png");
|
||||
-moz-image-region: rect(0px, 16px, 16px, 0px);
|
||||
}
|
||||
|
||||
.bookmark-item[livemark] .menuitem-iconic[visited] {
|
||||
-moz-image-region: rect(0px, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
.bookmark-item menuitem[openInTabs],
|
||||
.bookmark-item menuitem[siteURI] {
|
||||
/* Workaround for native menubar inheritance */
|
||||
.openintabs-menuitem,
|
||||
.openlivemarksite-menuitem,
|
||||
.livemarkstatus-menuitem {
|
||||
list-style-image: none;
|
||||
}
|
||||
|
||||
.bookmark-item[cutting] > .toolbarbutton-icon,
|
||||
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-icon {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.bookmark-item[cutting] > .toolbarbutton-text,
|
||||
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-text {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#wrapper-personal-bookmarks[place="palette"] > .toolbarpaletteitem-box {
|
||||
background: url("chrome://browser/skin/places/bookmarksToolbar.png") no-repeat center;
|
||||
}
|
||||
|
@ -287,16 +295,6 @@ toolbarbutton.bookmark-item > menupopup {
|
|||
height: 16px;
|
||||
}
|
||||
|
||||
.bookmark-item[cutting] > .toolbarbutton-icon,
|
||||
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-icon {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.bookmark-item[cutting] > .toolbarbutton-text,
|
||||
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-text {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#bookmarksToolbarFolderMenu,
|
||||
#BMB_bookmarksToolbar {
|
||||
list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png");
|
||||
|
|
|
@ -459,7 +459,7 @@ class ShutdownLeakLogger(object):
|
|||
DOM windows (that are still around after test suite shutdown, despite running
|
||||
the GC) to the tests that created them and prints leak statistics.
|
||||
"""
|
||||
MAX_LEAK_COUNT = 130
|
||||
MAX_LEAK_COUNT = 123
|
||||
|
||||
def __init__(self, logger):
|
||||
self.logger = logger
|
||||
|
|
|
@ -77,5 +77,5 @@ public interface Driver {
|
|||
* @return A 2-D array of pixels (indexed by y, then x). The pixels
|
||||
* are in ARGB-8888 format.
|
||||
*/
|
||||
int[][] getPaintedSurface();
|
||||
PaintedSurface getPaintedSurface();
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ import java.io.IOException;
|
|||
import java.nio.IntBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
import java.lang.Class;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
@ -291,7 +293,7 @@ public class FennecNativeDriver implements Driver {
|
|||
return null;
|
||||
}
|
||||
|
||||
public int[][] getPaintedSurface() {
|
||||
public PaintedSurface getPaintedSurface() {
|
||||
GLSurfaceView view = getSurfaceView();
|
||||
if (view == null) {
|
||||
return null;
|
||||
|
@ -309,14 +311,34 @@ public class FennecNativeDriver implements Driver {
|
|||
int w = view.getWidth();
|
||||
int h = view.getHeight();
|
||||
pixelBuffer.position(0);
|
||||
int[][] pixels = new int[h][w];
|
||||
for (int y = h - 1; y >= 0; y--) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int agbr = pixelBuffer.get();
|
||||
pixels[y][x] = (agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000);
|
||||
String mapFile = "/mnt/sdcard/pixels.map";
|
||||
|
||||
FileOutputStream fos = null;
|
||||
DataOutputStream dos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(mapFile);
|
||||
dos = new DataOutputStream(fos);
|
||||
|
||||
for (int y = h - 1; y >= 0; y--) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int agbr = pixelBuffer.get();
|
||||
dos.writeInt((agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000));
|
||||
}
|
||||
}
|
||||
return new PaintedSurface(mapFile, w, h);
|
||||
} catch (IOException e) {
|
||||
throw new RoboCopException("exception with pixel writer on file: " + mapFile);
|
||||
} finally {
|
||||
try {
|
||||
if (dos != null && fos != null) {
|
||||
dos.flush();
|
||||
dos.close();
|
||||
fos.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RoboCopException("exception closing pixel writer on file: " + mapFile);
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
public int mHeight=0;
|
||||
|
|
|
@ -61,6 +61,7 @@ _JAVA_HARNESS = \
|
|||
FennecNativeDriver.java \
|
||||
FennecNativeElement.java \
|
||||
RoboCopException.java \
|
||||
PaintedSurface.java \
|
||||
$(NULL)
|
||||
|
||||
_JAVA_TESTS = $(patsubst $(TESTPATH)/%.in,%,$(wildcard $(TESTPATH)/*.java.in))
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
#filter substitution
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
public class PaintedSurface {
|
||||
private String mFileName = null;
|
||||
private int mWidth = -1;
|
||||
private int mHeight = -1;
|
||||
private MappedByteBuffer mPixelBuffer = null;
|
||||
|
||||
public PaintedSurface(String filename, int width, int height) {
|
||||
mFileName = filename;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
try {
|
||||
File f = new File(filename);
|
||||
int pixelSize = (int)f.length();
|
||||
|
||||
FileInputStream pixelFile = new FileInputStream(filename);
|
||||
mPixelBuffer = pixelFile.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, pixelSize);
|
||||
} catch (java.io.FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (java.io.IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public final int getPixelAt(int x, int y) {
|
||||
if (mPixelBuffer == null) {
|
||||
throw new RoboCopException("Trying to access PaintedSurface with no active PixelBuffer");
|
||||
}
|
||||
|
||||
if (x >= mWidth || x < 0) {
|
||||
throw new RoboCopException("Trying to access PaintedSurface with invalid x value");
|
||||
}
|
||||
|
||||
if (y >= mHeight || y < 0) {
|
||||
throw new RoboCopException("Trying to access PaintedSurface with invalid y value");
|
||||
}
|
||||
|
||||
// The rows are reversed so row 0 is at the end and we start with the last row.
|
||||
// This is why we do mHeight-y;
|
||||
int index = (x + ((mHeight - y - 1) * mWidth)) * 4;
|
||||
int b1 = mPixelBuffer.get(index) & 0xFF;
|
||||
int b2 = mPixelBuffer.get(index + 1) & 0xFF;
|
||||
int b3 = mPixelBuffer.get(index + 2) & 0xFF;
|
||||
int b4 = mPixelBuffer.get(index + 3) & 0xFF;
|
||||
int value = (b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
@ -148,6 +148,9 @@ xpcshell-tests:
|
|||
$(testxpcsrcdir)/runxpcshelltests.py \
|
||||
--symbols-path=$(DIST)/crashreporter-symbols \
|
||||
--build-info-json=$(DEPTH)/mozinfo.json \
|
||||
--tests-root-dir=$(testxpcobjdir) \
|
||||
--xunit-file=$(testxpcobjdir)/$(relativesrcdir)/results.xml \
|
||||
--xunit-suite-name=xpcshell \
|
||||
$(EXTRA_TEST_ARGS) \
|
||||
$(LIBXUL_DIST)/bin/xpcshell \
|
||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
|
||||
|
|
|
@ -628,9 +628,10 @@ if test "$GXX" = "yes"; then
|
|||
GNU_CXX=1
|
||||
CXX_VERSION=`$CXX -v 2>&1 | grep 'gcc version'`
|
||||
fi
|
||||
if test "`echo | $AS -v 2>&1 | grep -c GNU`" != "0"; then
|
||||
if test "`echo | $AS -o conftest.out -v 2>&1 | grep -c GNU`" != "0"; then
|
||||
GNU_AS=1
|
||||
fi
|
||||
rm -f conftest.out
|
||||
if test "`echo | $LD -v 2>&1 | grep -c GNU`" != "0"; then
|
||||
GNU_LD=1
|
||||
fi
|
||||
|
@ -9212,7 +9213,7 @@ if test -z "$MOZ_NATIVE_NSPR"; then
|
|||
fi
|
||||
if test "$MOZ_OPTIMIZE" = "1"; then
|
||||
ac_configure_args="$ac_configure_args --enable-optimize"
|
||||
else
|
||||
elif test -z "$MOZ_OPTIMIZE"; then
|
||||
ac_configure_args="$ac_configure_args --disable-optimize"
|
||||
fi
|
||||
if test -n "$HAVE_64BIT_OS"; then
|
||||
|
|
|
@ -882,9 +882,7 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope)
|
|||
JS_SetContextPrivate(cx, aScope);
|
||||
|
||||
nsresult rv =
|
||||
xpc->InitClassesWithNewWrappedGlobal(cx, aScope,
|
||||
NS_GET_IID(nsISupports),
|
||||
mPrincipal, nsnull,
|
||||
xpc->InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal,
|
||||
flags, getter_AddRefs(mGlobal));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
|
|
|
@ -597,29 +597,10 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
|
|||
if (aCx && wrapper) {
|
||||
nsIXPConnect *xpc = nsContentUtils::XPConnect();
|
||||
if (xpc) {
|
||||
JSObject *preservedWrapper = nsnull;
|
||||
|
||||
// If reparenting moves us to a new compartment, preserving causes
|
||||
// problems. In that case, we release ourselves and re-preserve after
|
||||
// reparenting so we're sure to have the right JS object preserved.
|
||||
// We use a JSObject stack copy of the wrapper to protect it from GC
|
||||
// under ReparentWrappedNativeIfFound.
|
||||
if (aNode->PreservingWrapper()) {
|
||||
preservedWrapper = wrapper;
|
||||
nsContentUtils::ReleaseWrapper(aNode, aNode);
|
||||
NS_ASSERTION(aNode->GetWrapper(),
|
||||
"ReleaseWrapper cleared our wrapper, this code needs to "
|
||||
"be changed to deal with that!");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> oldWrapper;
|
||||
rv = xpc->ReparentWrappedNativeIfFound(aCx, wrapper, aNewScope, aNode,
|
||||
getter_AddRefs(oldWrapper));
|
||||
|
||||
if (preservedWrapper) {
|
||||
nsContentUtils::PreserveWrapper(aNode, aNode);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aNode->mNodeInfo.swap(nodeInfo);
|
||||
|
||||
|
|
|
@ -602,7 +602,7 @@ nsWebSocket::Initialize(nsISupports* aOwner,
|
|||
if (JSVAL_IS_OBJECT(aArgv[1]) &&
|
||||
(jsobj = JSVAL_TO_OBJECT(aArgv[1])) &&
|
||||
JS_IsArrayObject(aContext, jsobj)) {
|
||||
jsuint len;
|
||||
uint32_t len;
|
||||
JS_GetArrayLength(aContext, jsobj, &len);
|
||||
|
||||
for (PRUint32 index = 0; index < len; ++index) {
|
||||
|
|
|
@ -122,7 +122,7 @@ JSValToMatrixElts(JSContext* cx, const jsval& val,
|
|||
double* (&elts)[N], nsresult* rv)
|
||||
{
|
||||
JSObject* obj;
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(val) ||
|
||||
!(obj = JSVAL_TO_OBJECT(val)) ||
|
||||
|
|
|
@ -146,11 +146,11 @@ JSValToDashArray(JSContext* cx, const jsval& patternArray,
|
|||
{
|
||||
// The cap is pretty arbitrary. 16k should be enough for
|
||||
// anybody...
|
||||
static const jsuint MAX_NUM_DASHES = 1 << 14;
|
||||
static const uint32_t MAX_NUM_DASHES = 1 << 14;
|
||||
|
||||
if (!JSVAL_IS_PRIMITIVE(patternArray)) {
|
||||
JSObject* obj = JSVAL_TO_OBJECT(patternArray);
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!JS_GetArrayLength(cx, obj, &length)) {
|
||||
// Not an array-like thing
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "nsMediaCache.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "prio.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
@ -545,8 +546,15 @@ nsMediaCache::Init()
|
|||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
NS_ASSERTION(!mFD, "Cache file already open?");
|
||||
|
||||
// In single process Gecko, store the media cache in the profile directory
|
||||
// so that multiple users can use separate media caches concurrently.
|
||||
// In multi-process Gecko, there is no profile dir, so just store it in the
|
||||
// system temp directory instead.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFile> tmp;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmp));
|
||||
const char* dir = (XRE_GetProcessType() == GeckoProcessType_Content) ?
|
||||
NS_OS_TEMP_DIR : NS_APP_USER_PROFILE_LOCAL_50_DIR;
|
||||
rv = NS_GetSpecialDirectory(dir, getter_AddRefs(tmp));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr<nsILocalFile> tmpFile = do_QueryInterface(tmp);
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* helper object for APIs that deal with DOMRequest and need to release them properly
|
||||
* when the window goes out of scope
|
||||
*/
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
let EXPORTED_SYMBOLS = ["DOMRequestIpcHelper"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Services, "rs", function() {
|
||||
return Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
|
||||
return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
});
|
||||
|
||||
function DOMRequestIpcHelper() {
|
||||
}
|
||||
|
||||
DOMRequestIpcHelper.prototype = {
|
||||
getRequestId: function(aRequest) {
|
||||
let id = "id" + this._getRandomId();
|
||||
this._requests[id] = aRequest;
|
||||
return id;
|
||||
},
|
||||
|
||||
getRequest: function(aId) {
|
||||
if (this._requests[aId])
|
||||
return this._requests[aId];
|
||||
},
|
||||
|
||||
removeRequest: function(aId) {
|
||||
if (this._requests[aId])
|
||||
delete this._requests[aId];
|
||||
},
|
||||
|
||||
_getRandomId: function() {
|
||||
return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId == this.innerWindowID) {
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
this._requests = [];
|
||||
this._window = null;
|
||||
this._messages.forEach((function(msgName) {
|
||||
cpmm.removeMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
if(this.uninit)
|
||||
this.uninit();
|
||||
}
|
||||
},
|
||||
|
||||
initHelper: function(aWindow, aMessages) {
|
||||
this._messages = aMessages;
|
||||
this._requests = [];
|
||||
this._window = aWindow;
|
||||
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
this.innerWindowID = util.currentInnerWindowID;
|
||||
this._id = this._getRandomId();
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
this._messages.forEach((function(msgName) {
|
||||
cpmm.addMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
createRequest: function() {
|
||||
return Services.rs.createRequest(this._window);
|
||||
}
|
||||
}
|
|
@ -66,6 +66,7 @@ EXTRA_COMPONENTS = \
|
|||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES += Webapps.jsm \
|
||||
DOMRequestHelper.jsm \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
|
|
@ -1,38 +1,6 @@
|
|||
/* ***** 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 Open Web Apps.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabrice Desré <fabrice@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either 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 ***** */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
@ -41,27 +9,31 @@ const Cr = Components.results;
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Services, "rs", function() {
|
||||
return Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
|
||||
return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
});
|
||||
|
||||
function convertAppsArray(aApps, aWindow) {
|
||||
let apps = new Array();
|
||||
for (let i = 0; i < aApps.length; i++) {
|
||||
let app = aApps[i];
|
||||
apps.push(new WebappsApplication(aWindow, app.origin, app.manifest, app.manifestURL,
|
||||
app.receipts, app.installOrigin, app.installTime));
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
|
||||
function WebappsRegistry() {
|
||||
this.messages = ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
|
||||
"Webapps:Uninstall:Return:OK", "Webapps:Uninstall:Return:KO",
|
||||
"Webapps:Enumerate:Return:OK", "Webapps:Enumerate:Return:KO"];
|
||||
|
||||
this.mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
|
||||
this.messages.forEach((function(msgName) {
|
||||
this.mm.addMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
this._window = null;
|
||||
this._id = this._getRandomId();
|
||||
this._callbacks = [];
|
||||
}
|
||||
|
||||
WebappsRegistry.prototype = {
|
||||
_onerror: null,
|
||||
_oninstall: null,
|
||||
_onuninstall: null,
|
||||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
|
||||
/** from https://developer.mozilla.org/en/OpenWebApps/The_Manifest
|
||||
* only the name property is mandatory
|
||||
|
@ -70,7 +42,7 @@ WebappsRegistry.prototype = {
|
|||
// TODO : check for install_allowed_from
|
||||
if (aManifest.name == undefined)
|
||||
return false;
|
||||
|
||||
|
||||
if (aManifest.installs_allowed_from) {
|
||||
ok = false;
|
||||
aManifest.installs_allowed_from.forEach(function(aOrigin) {
|
||||
|
@ -81,97 +53,41 @@ WebappsRegistry.prototype = {
|
|||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
getCallbackId: function(aCallback) {
|
||||
let id = "id" + this._getRandomId();
|
||||
this._callbacks[id] = aCallback;
|
||||
return id;
|
||||
},
|
||||
|
||||
getCallback: function(aId) {
|
||||
return this._callbacks[aId];
|
||||
},
|
||||
|
||||
removeCallback: function(aId) {
|
||||
if (this._callbacks[aId])
|
||||
delete this._callbacks[aId];
|
||||
},
|
||||
|
||||
_getRandomId: function() {
|
||||
return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
|
||||
},
|
||||
|
||||
_convertAppsArray: function(aApps) {
|
||||
let apps = new Array();
|
||||
for (let i = 0; i < aApps.length; i++) {
|
||||
let app = aApps[i];
|
||||
apps.push(new WebappsApplication(app.origin, app.manifest, app.receipt, app.installOrigin, app.installTime));
|
||||
}
|
||||
return apps;
|
||||
},
|
||||
|
||||
set oninstall(aCallback) {
|
||||
if (this.hasPrivileges)
|
||||
this._oninstall = aCallback;
|
||||
else
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
set onuninstall(aCallback) {
|
||||
if (this.hasPrivileges)
|
||||
this._onuninstall = aCallback;
|
||||
else
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
set onerror(aCallback) {
|
||||
this._onerror = aCallback;
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
if (!(msg.oid == this._id || aMessage.name == "Webapps:Install:Return:OK" || aMessage.name == "Webapps:Uninstall:Return:OK"))
|
||||
if (msg.oid != this._id)
|
||||
return
|
||||
let req = this.getRequest(msg.requestID);
|
||||
if (!req)
|
||||
return;
|
||||
let app = msg.app;
|
||||
let cb;
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:Install:Return:OK":
|
||||
if (this._oninstall)
|
||||
this._oninstall.handleEvent(new WebappsApplication(app.origin, app.manifest, app.receipt,
|
||||
Services.rs.fireSuccess(req, new WebappsApplication(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
|
||||
app.installOrigin, app.installTime));
|
||||
break;
|
||||
case "Webapps:Install:Return:KO":
|
||||
if (this._onerror)
|
||||
this._onerror.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.DENIED));
|
||||
Services.rs.fireError(req, "DENIED");
|
||||
break;
|
||||
case "Webapps:Uninstall:Return:OK":
|
||||
if (this._onuninstall)
|
||||
this._onuninstall.handleEvent(new WebappsApplication(msg.origin, null, null, null, 0));
|
||||
break;
|
||||
case "Webapps:Uninstall:Return:KO":
|
||||
if (this._onerror)
|
||||
this._onerror.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
|
||||
break;
|
||||
case "Webapps:Enumerate:Return:OK":
|
||||
cb = this.getCallback(msg.callbackID);
|
||||
if (cb.success) {
|
||||
let apps = this._convertAppsArray(msg.apps);
|
||||
cb.success.handleEvent(apps, apps.length);
|
||||
case "Webapps:GetSelf:Return:OK":
|
||||
if (msg.apps.length) {
|
||||
app = msg.apps[0];
|
||||
Services.rs.fireSuccess(req, new WebappsApplication(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
|
||||
app.installOrigin, app.installTime));
|
||||
} else {
|
||||
Services.rs.fireSuccess(req, null);
|
||||
}
|
||||
break;
|
||||
case "Webapps:Enumerate:Return:KO":
|
||||
cb = this.getCallback(msg.callbackID);
|
||||
if (cb.error)
|
||||
cb.error.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
|
||||
case "Webapps:GetInstalled:Return:OK":
|
||||
Services.rs.fireSuccess(req, convertAppsArray(msg.apps, this._window));
|
||||
break;
|
||||
case "Webapps:GetSelf:Return:KO":
|
||||
case "Webapps:GetInstalled:Return:KO":
|
||||
Services.rs.fireError(req, "ERROR");
|
||||
break;
|
||||
}
|
||||
this.removeCallback(msg.callbackID);
|
||||
},
|
||||
|
||||
_fireError: function(aCode) {
|
||||
if (!this._onerror)
|
||||
return;
|
||||
this._onerror.handleEvent(new RegistryError(aCode));
|
||||
this.removeRequest(msg.requestID);
|
||||
},
|
||||
|
||||
_getOrigin: function(aURL) {
|
||||
|
@ -181,7 +97,9 @@ WebappsRegistry.prototype = {
|
|||
|
||||
// mozIDOMApplicationRegistry implementation
|
||||
|
||||
install: function(aURL, aReceipt) {
|
||||
install: function(aURL, aParams) {
|
||||
let request = this.createRequest();
|
||||
let requestID = this.getRequestId(request);
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open("GET", aURL, true);
|
||||
|
||||
|
@ -191,90 +109,70 @@ WebappsRegistry.prototype = {
|
|||
let installOrigin = this._getOrigin(this._window.location.href);
|
||||
let manifest = JSON.parse(xhr.responseText, installOrigin);
|
||||
if (!this.checkManifest(manifest, installOrigin)) {
|
||||
this._fireError(Ci.mozIDOMApplicationRegistryError.INVALID_MANIFEST);
|
||||
Services.rs.fireError(request, "INVALID_MANIFEST");
|
||||
} else {
|
||||
this.mm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin,
|
||||
origin: this._getOrigin(aURL),
|
||||
manifest: manifest,
|
||||
receipt: aReceipt },
|
||||
from: this._window.location.href,
|
||||
oid: this._id });
|
||||
let receipts = (aParams && aParams.receipts && Array.isArray(aParams.receipts)) ? aParams.receipts : [];
|
||||
cpmm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin,
|
||||
origin: this._getOrigin(aURL),
|
||||
manifestURL: aURL,
|
||||
manifest: manifest,
|
||||
receipts: receipts },
|
||||
from: this._window.location.href,
|
||||
oid: this._id,
|
||||
requestID: requestID });
|
||||
}
|
||||
} catch(e) {
|
||||
this._fireError(Ci.mozIDOMApplicationRegistryError.MANIFEST_PARSE_ERROR);
|
||||
Services.rs.fireError(request, "MANIFEST_PARSE_ERROR");
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._fireError(Ci.mozIDOMApplicationRegistryError.MANIFEST_URL_ERROR);
|
||||
Services.rs.fireError(request, "MANIFEST_URL_ERROR");
|
||||
}
|
||||
}).bind(this), false);
|
||||
|
||||
xhr.addEventListener("error", (function() {
|
||||
this._fireError(Ci.mozIDOMApplicationRegistryError.NETWORK_ERROR);
|
||||
Services.rs.fireError(request, "NETWORK_ERROR");
|
||||
}).bind(this), false);
|
||||
|
||||
xhr.send(null);
|
||||
return request;
|
||||
},
|
||||
|
||||
uninstall: function(aOrigin) {
|
||||
if (this.hasPrivileges)
|
||||
this.mm.sendAsyncMessage("Webapps:Uninstall", { from: this._window.location.href,
|
||||
origin: aOrigin,
|
||||
oid: this._id });
|
||||
else
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
getSelf: function() {
|
||||
let request = this.createRequest();
|
||||
cpmm.sendAsyncMessage("Webapps:GetSelf", { origin: this._getOrigin(this._window.location.href),
|
||||
oid: this._id,
|
||||
requestID: this.getRequestId(request) });
|
||||
return request;
|
||||
},
|
||||
|
||||
launch: function(aOrigin) {
|
||||
this.mm.sendAsyncMessage("Webapps:Launch", { origin: aOrigin,
|
||||
from: this._window.location.href});
|
||||
},
|
||||
|
||||
enumerate: function(aSuccess, aError) {
|
||||
this.mm.sendAsyncMessage("Webapps:Enumerate", { from: this._window.location.href,
|
||||
origin: this._getOrigin(this._window.location.href),
|
||||
getInstalled: function() {
|
||||
let request = this.createRequest();
|
||||
cpmm.sendAsyncMessage("Webapps:GetInstalled", { origin: this._getOrigin(this._window.location.href),
|
||||
oid: this._id,
|
||||
callbackID: this.getCallbackId({ success: aSuccess, error: aError }) });
|
||||
requestID: this.getRequestId(request) });
|
||||
return request;
|
||||
},
|
||||
|
||||
enumerateAll: function(aSuccess, aError) {
|
||||
if (this.hasPrivileges) {
|
||||
this.mm.sendAsyncMessage("Webapps:EnumerateAll", { from: this._window.location.href,
|
||||
origin: this._getOrigin(this._window.location.href),
|
||||
oid: this._id,
|
||||
callbackID: this.getCallbackId({ success: aSuccess, error: aError }) });
|
||||
} else {
|
||||
if (aError)
|
||||
aError.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
|
||||
}
|
||||
get mgmt() {
|
||||
if (!this._mgmt)
|
||||
this._mgmt = new WebappsApplicationMgmt(this._window);
|
||||
return this._mgmt;
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId == this.innerWindowID) {
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
this._oninstall = null;
|
||||
this._onuninstall = null;
|
||||
this._onerror = null;
|
||||
this._callbacks = [];
|
||||
this._window = null;
|
||||
}
|
||||
uninit: function() {
|
||||
this._mgmt = null;
|
||||
},
|
||||
|
||||
// nsIDOMGlobalPropertyInitializer implementation
|
||||
init: function(aWindow) {
|
||||
dump("DOMApplicationRegistry::init() " + aWindow + "\n");
|
||||
this._window = aWindow;
|
||||
this._window.appId = this._id;
|
||||
let from = Services.io.newURI(this._window.location.href, null, null);
|
||||
let perm = Services.perms.testExactPermission(from, "webapps-manage");
|
||||
|
||||
//only pages with perm set and chrome or about pages can uninstall, enumerate all set oninstall an onuninstall
|
||||
this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION || from.schemeIs("chrome") || from.schemeIs("about");
|
||||
this.initHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
|
||||
"Webapps:GetInstalled:Return:OK", "Webapps:GetInstalled:Return:KO",
|
||||
"Webapps:GetSelf:Return:OK", "Webapps:GetSelf:Return:KO"]);
|
||||
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
this.innerWindowID = util.currentInnerWindowID;
|
||||
this._id = util.outerWindowID;
|
||||
},
|
||||
|
||||
classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
|
||||
|
@ -288,18 +186,26 @@ WebappsRegistry.prototype = {
|
|||
classDescription: "Webapps Registry"})
|
||||
}
|
||||
|
||||
function WebappsApplication(aOrigin, aManifest, aReceipt, aInstallOrigin, aInstallTime) {
|
||||
/**
|
||||
* mozIDOMApplication object
|
||||
*/
|
||||
function WebappsApplication(aWindow, aOrigin, aManifest, aManifestURL, aReceipts, aInstallOrigin, aInstallTime) {
|
||||
this._origin = aOrigin;
|
||||
this._manifest = aManifest;
|
||||
this._receipt = aReceipt;
|
||||
this._manifestURL = aManifestURL;
|
||||
this._receipts = aReceipts;
|
||||
this._installOrigin = aInstallOrigin;
|
||||
this._installTime = aInstallTime;
|
||||
|
||||
this.initHelper(aWindow, ["Webapps:Uninstall:Return:OK", "Webapps:Uninstall:Return:KO"]);
|
||||
}
|
||||
|
||||
WebappsApplication.prototype = {
|
||||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
_origin: null,
|
||||
_manifest: null,
|
||||
_receipt: null,
|
||||
_manifestURL: null,
|
||||
_receipts: [],
|
||||
_installOrigin: null,
|
||||
_installTime: 0,
|
||||
|
||||
|
@ -311,8 +217,12 @@ WebappsApplication.prototype = {
|
|||
return this._manifest;
|
||||
},
|
||||
|
||||
get receipt() {
|
||||
return this._receipt;
|
||||
get manifestURL() {
|
||||
return this._manifestURL;
|
||||
},
|
||||
|
||||
get receipts() {
|
||||
return this._receipts;
|
||||
},
|
||||
|
||||
get installOrigin() {
|
||||
|
@ -323,6 +233,39 @@ WebappsApplication.prototype = {
|
|||
return this._installTime;
|
||||
},
|
||||
|
||||
launch: function(aStartPoint) {
|
||||
let request = this.createRequest();
|
||||
cpmm.sendAsyncMessage("Webapps:Launch", { origin: this._origin,
|
||||
startPoint: aStartPoint,
|
||||
oid: this._id,
|
||||
requestID: this.getRequestId(request) });
|
||||
return request;
|
||||
},
|
||||
|
||||
uninstall: function() {
|
||||
let request = this.createRequest();
|
||||
cpmm.sendAsyncMessage("Webapps:Uninstall", { origin: this._origin,
|
||||
oid: this._id,
|
||||
requestID: this.getRequestId(request) });
|
||||
return request;
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
var msg = aMessage.json;
|
||||
let req = this.getRequest(msg.requestID);
|
||||
if (msg.oid != this._id || !req)
|
||||
return;
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:Uninstall:Return:OK":
|
||||
Services.rs.fireSuccess(req, msg.origin);
|
||||
break;
|
||||
case "Webapps:Uninstall:Return:KO":
|
||||
Services.rs.fireError(req, msg.origin);
|
||||
break;
|
||||
}
|
||||
this.removeRequest(msg.requestID);
|
||||
},
|
||||
|
||||
classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplication]),
|
||||
|
@ -334,26 +277,131 @@ WebappsApplication.prototype = {
|
|||
classDescription: "Webapps Application"})
|
||||
}
|
||||
|
||||
function RegistryError(aCode) {
|
||||
this._code = aCode;
|
||||
/**
|
||||
* mozIDOMApplicationMgmt object
|
||||
*/
|
||||
function WebappsApplicationMgmt(aWindow) {
|
||||
let principal = aWindow.document.nodePrincipal;
|
||||
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
|
||||
|
||||
let perm = principal == secMan.getSystemPrincipal() ?
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION :
|
||||
Services.perms.testExactPermission(principal.URI, "webapps-manage");
|
||||
|
||||
//only pages with perm set can use some functions
|
||||
this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
|
||||
this.initHelper(aWindow, ["Webapps:GetAll:Return:OK", "Webapps:GetAll:Return:KO",
|
||||
"Webapps:Install:Return:OK", "Webapps:Uninstall:Return:OK"]);
|
||||
|
||||
this._oninstall = null;
|
||||
this._onuninstall = null;
|
||||
}
|
||||
|
||||
RegistryError.prototype = {
|
||||
_code: null,
|
||||
|
||||
get code() {
|
||||
return this._code;
|
||||
WebappsApplicationMgmt.prototype = {
|
||||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
|
||||
uninit: function() {
|
||||
this._oninstall = null;
|
||||
this._onuninstall = null;
|
||||
},
|
||||
|
||||
classID: Components.ID("{b4937718-11a3-400b-a69f-ab442a418569}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationRegistryError]),
|
||||
getAll: function() {
|
||||
let request = this.createRequest();
|
||||
cpmm.sendAsyncMessage("Webapps:GetAll", { oid: this._id,
|
||||
requestID: this.getRequestId(request),
|
||||
hasPrivileges: this.hasPrivileges });
|
||||
return request;
|
||||
},
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{b4937718-11a3-400b-a69f-ab442a418569}"),
|
||||
contractID: "@mozilla.org/webapps/error;1",
|
||||
interfaces: [Ci.mozIDOMApplicationRegistryError],
|
||||
get oninstall() {
|
||||
return this._oninstall;
|
||||
},
|
||||
|
||||
get onuninstall() {
|
||||
this._onuninstall;
|
||||
},
|
||||
|
||||
set oninstall(aCallback) {
|
||||
if (this.hasPrivileges)
|
||||
this._oninstall = aCallback;
|
||||
else
|
||||
|
||||
throw new Components.exception("Denied", Cr.NS_ERROR_FAILURE);
|
||||
},
|
||||
|
||||
set onuninstall(aCallback) {
|
||||
if (this.hasPrivileges)
|
||||
this._onuninstall = aCallback;
|
||||
else
|
||||
throw new Components.exception("Denied", Cr.NS_ERROR_FAILURE);
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
var msg = aMessage.json;
|
||||
let req = this.getRequest(msg.requestID);
|
||||
// We want Webapps:Install:Return:OK and Webapps:Uninstall:Return:OK to be boradcasted
|
||||
// to all instances of mozApps.mgmt
|
||||
if (!((msg.oid == this._id && req)
|
||||
|| aMessage.name == "Webapps:Install:Return:OK" || aMessage.name == "Webapps:Uninstall:Return:OK"))
|
||||
return;
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:GetAll:Return:OK":
|
||||
Services.rs.fireSuccess(req, convertAppsArray(msg.apps, this._window));
|
||||
break;
|
||||
case "Webapps:GetAll:Return:KO":
|
||||
Services.rs.fireError(req, "DENIED");
|
||||
break;
|
||||
case "Webapps:Install:Return:OK":
|
||||
if (this._oninstall) {
|
||||
let app = msg.app;
|
||||
let event = new WebappsApplicationEvent(new WebappsApplication(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
|
||||
app.installOrigin, app.installTime));
|
||||
this._oninstall.handleEvent(event);
|
||||
}
|
||||
break;
|
||||
case "Webapps:Uninstall:Return:OK":
|
||||
if (this._onuninstall) {
|
||||
let event = new WebappsApplicationEvent(new WebappsApplication(this._window, msg.origin, null, null, null, null, 0));
|
||||
this._onuninstall.handleEvent(event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.removeRequest(msg.requestID);
|
||||
},
|
||||
|
||||
classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationMgmt]),
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
|
||||
contractID: "@mozilla.org/webapps/application-mgmt;1",
|
||||
interfaces: [Ci.mozIDOMApplicationMgmt],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Webapps Registry Error"})
|
||||
classDescription: "Webapps Application Mgmt"})
|
||||
}
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry, WebappsApplication, RegistryError]);
|
||||
/**
|
||||
* mozIDOMApplicationEvent object
|
||||
*/
|
||||
function WebappsApplicationEvent(aApp) {
|
||||
this._app = aApp;
|
||||
}
|
||||
|
||||
WebappsApplicationEvent.prototype = {
|
||||
get application() {
|
||||
return this._app;
|
||||
},
|
||||
|
||||
classID: Components.ID("{5bc42b2a-9acc-49d5-a336-c353c8125e48}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationEvent]),
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
|
||||
contractID: "@mozilla.org/webapps/application-event;1",
|
||||
interfaces: [Ci.mozIDOMApplicationEvent],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Webapps Application Event"})
|
||||
}
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry, WebappsApplication]);
|
||||
|
|
|
@ -1,39 +1,6 @@
|
|||
/* ***** 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 Mobile Browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabrice Desré <fabrice@mozilla.com>
|
||||
* Mark Finkle <mfinkle@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either 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 ***** */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
@ -50,17 +17,21 @@ XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
|||
return NetUtil;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
|
||||
return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
});
|
||||
|
||||
let DOMApplicationRegistry = {
|
||||
appsFile: null,
|
||||
webapps: { },
|
||||
|
||||
init: function() {
|
||||
this.mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
let messages = ["Webapps:Install", "Webapps:Uninstall",
|
||||
"Webapps:Enumerate", "Webapps:EnumerateAll", "Webapps:Launch"];
|
||||
"Webapps:GetSelf", "Webapps:GetInstalled",
|
||||
"Webapps:Launch", "Webapps:GetAll"];
|
||||
|
||||
messages.forEach((function(msgName) {
|
||||
this.mm.addMessageListener(msgName, this);
|
||||
ppmm.addMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
let appsDir = FileUtils.getDir("ProfD", ["webapps"], true, true);
|
||||
|
@ -114,29 +85,29 @@ let DOMApplicationRegistry = {
|
|||
|
||||
receiveMessage: function(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
let from = Services.io.newURI(msg.from, null, null);
|
||||
let perm = Services.perms.testExactPermission(from, "webapps-manage");
|
||||
|
||||
//only pages with perm set and chrome or about pages can uninstall, enumerate all set oninstall an onuninstall
|
||||
let hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION || from.schemeIs("chrome") || from.schemeIs("about");
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:Install":
|
||||
// always ask for UI to install
|
||||
Services.obs.notifyObservers(this, "webapps-ask-install", JSON.stringify(msg));
|
||||
break;
|
||||
case "Webapps:GetSelf":
|
||||
this.getSelf(msg);
|
||||
break;
|
||||
case "Webapps:Uninstall":
|
||||
if (hasPrivileges)
|
||||
this.uninstall(msg);
|
||||
this.uninstall(msg);
|
||||
break;
|
||||
case "Webapps:Launch":
|
||||
Services.obs.notifyObservers(this, "webapps-launch", JSON.stringify(msg));
|
||||
break;
|
||||
case "Webapps:Enumerate":
|
||||
this.enumerate(msg);
|
||||
case "Webapps:GetInstalled":
|
||||
this.getInstalled(msg);
|
||||
break;
|
||||
case "Webapps:EnumerateAll":
|
||||
this.enumerateAll(msg);
|
||||
case "Webapps:GetAll":
|
||||
if (msg.hasPrivileges)
|
||||
this.getAll(msg);
|
||||
else
|
||||
ppmm.sendAsyncMessage("Webapps:GetAll:Return:KO", msg);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -162,14 +133,15 @@ let DOMApplicationRegistry = {
|
|||
let clone = {
|
||||
installOrigin: aApp.installOrigin,
|
||||
origin: aApp.origin,
|
||||
receipt: aApp.receipt,
|
||||
installTime: aApp.installTime
|
||||
receipts: aApp.receipts,
|
||||
installTime: aApp.installTime,
|
||||
manifestURL: aApp.manifestURL
|
||||
};
|
||||
return clone;
|
||||
},
|
||||
|
||||
denyInstall: function(aData) {
|
||||
this.mm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
|
||||
ppmm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
|
||||
},
|
||||
|
||||
confirmInstall: function(aData, aFromSync) {
|
||||
|
@ -202,7 +174,7 @@ let DOMApplicationRegistry = {
|
|||
|
||||
if (!aFromSync)
|
||||
this._saveApps((function() {
|
||||
this.mm.sendAsyncMessage("Webapps:Install:Return:OK", aData);
|
||||
ppmm.sendAsyncMessage("Webapps:Install:Return:OK", aData);
|
||||
Services.obs.notifyObservers(this, "webapps-sync-install", id);
|
||||
}).bind(this));
|
||||
},
|
||||
|
@ -244,9 +216,11 @@ let DOMApplicationRegistry = {
|
|||
},
|
||||
|
||||
uninstall: function(aData) {
|
||||
let found = false;
|
||||
for (let id in this.webapps) {
|
||||
let app = this.webapps[id];
|
||||
if (app.origin == aData.origin) {
|
||||
found = true;
|
||||
delete this.webapps[id];
|
||||
let dir = FileUtils.getDir("ProfD", ["webapps", id], true, true);
|
||||
try {
|
||||
|
@ -254,62 +228,53 @@ let DOMApplicationRegistry = {
|
|||
} catch (e) {
|
||||
}
|
||||
this._saveApps((function() {
|
||||
this.mm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData);
|
||||
ppmm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData);
|
||||
Services.obs.notifyObservers(this, "webapps-sync-uninstall", id);
|
||||
}).bind(this));
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
ppmm.sendAsyncMessage("Webapps:Uninstall:Return:KO", aData);
|
||||
},
|
||||
|
||||
enumerate: function(aData) {
|
||||
getSelf: function(aData) {
|
||||
aData.apps = [];
|
||||
let tmp = [];
|
||||
let selfId;
|
||||
|
||||
let id = this._appId(aData.origin);
|
||||
// if it's an app, add itself to the result
|
||||
|
||||
if (id) {
|
||||
let app = this._cloneAppObject(this.webapps[id]);
|
||||
aData.apps.push(app);
|
||||
tmp.push({ id: id });
|
||||
selfId = id;
|
||||
}
|
||||
|
||||
// check if it's a store.
|
||||
let isStore = false;
|
||||
this._readManifests(tmp, (function(aResult) {
|
||||
for (let i = 0; i < aResult.length; i++)
|
||||
aData.apps[i].manifest = aResult[i].manifest;
|
||||
ppmm.sendAsyncMessage("Webapps:GetSelf:Return:OK", aData);
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
getInstalled: function(aData) {
|
||||
aData.apps = [];
|
||||
let tmp = [];
|
||||
let id = this._appId(aData.origin);
|
||||
|
||||
for (id in this.webapps) {
|
||||
let app = this.webapps[id];
|
||||
if (app.installOrigin == aData.origin) {
|
||||
isStore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add all the apps from this store
|
||||
if (isStore) {
|
||||
for (id in this.webapps) {
|
||||
if (id == selfId)
|
||||
continue;
|
||||
let app = this._cloneAppObject(this.webapps[id]);
|
||||
if (app.installOrigin == aData.origin) {
|
||||
aData.apps.push(app);
|
||||
tmp.push({ id: id });
|
||||
}
|
||||
if (this.webapps[id].installOrigin == aData.origin) {
|
||||
aData.apps.push(this._cloneAppObject(this.webapps[id]));
|
||||
tmp.push({ id: id });
|
||||
}
|
||||
}
|
||||
|
||||
this._readManifests(tmp, (function(aResult) {
|
||||
for (let i = 0; i < aResult.length; i++)
|
||||
aData.apps[i].manifest = aResult[i].manifest;
|
||||
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:OK", aData);
|
||||
ppmm.sendAsyncMessage("Webapps:GetInstalled:Return:OK", aData);
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
denyEnumerate: function(aData) {
|
||||
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:KO", aData);
|
||||
},
|
||||
|
||||
enumerateAll: function(aData) {
|
||||
getAll: function(aData) {
|
||||
aData.apps = [];
|
||||
let tmp = [];
|
||||
|
||||
|
@ -322,7 +287,7 @@ let DOMApplicationRegistry = {
|
|||
this._readManifests(tmp, (function(aResult) {
|
||||
for (let i = 0; i < aResult.length; i++)
|
||||
aData.apps[i].manifest = aResult[i].manifest;
|
||||
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:OK", aData);
|
||||
ppmm.sendAsyncMessage("Webapps:GetAll:Return:OK", aData);
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
|
@ -368,7 +333,7 @@ let DOMApplicationRegistry = {
|
|||
dir.remove(true);
|
||||
} catch (e) {
|
||||
}
|
||||
this.mm.sendAsyncMessage("Webapps:Uninstall:Return:OK", { origin: origin });
|
||||
ppmm.sendAsyncMessage("Webapps:Uninstall:Return:OK", { origin: origin });
|
||||
} else {
|
||||
if (!!this.webapps[record.id]) {
|
||||
this.webapps[record.id] = record.value;
|
||||
|
@ -377,7 +342,7 @@ let DOMApplicationRegistry = {
|
|||
else {
|
||||
let data = { app: record.value };
|
||||
this.confirmInstall(data, true);
|
||||
this.mm.sendAsyncMessage("Webapps:Install:Return:OK", data);
|
||||
ppmm.sendAsyncMessage("Webapps:Install:Return:OK", data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,3 @@
|
|||
component {fff440b3-fae2-45c1-bf03-3b5a2e432270} Webapps.js
|
||||
contract @mozilla.org/webapps;1 {fff440b3-fae2-45c1-bf03-3b5a2e432270}
|
||||
category JavaScript-navigator-property mozApps @mozilla.org/webapps;1
|
||||
|
||||
component {723ed303-7757-4fb0-b261-4f78b1f6bd22} Webapps.js
|
||||
contract @mozilla.org/webapps/application;1 {723ed303-7757-4fb0-b261-4f78b1f6bd22}
|
||||
|
||||
component {b4937718-11a3-400b-a69f-ab442a418569} Webapps.js
|
||||
contract @mozilla.org/webapps/error;1 {b4937718-11a3-400b-a69f-ab442a418569}
|
||||
|
|
|
@ -548,6 +548,7 @@ static const char kDOMStringBundleURL[] =
|
|||
nsIXPCScriptable::WANT_ENUMERATE | \
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
|
||||
nsIXPCScriptable::USE_STUB_EQUALITY_HOOK | \
|
||||
nsIXPCScriptable::IS_GLOBAL_OBJECT | \
|
||||
nsIXPCScriptable::WANT_OUTER_OBJECT)
|
||||
|
||||
#define NODE_SCRIPTABLE_FLAGS \
|
||||
|
@ -1549,7 +1550,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
NS_DEFINE_CLASSINFO_DATA(AnimationEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS | nsIXPCScriptable::IS_GLOBAL_OBJECT)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(FormData, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
|
|
@ -144,7 +144,11 @@ static PRLogModuleInfo* gJSDiagnostics;
|
|||
|
||||
#define NS_CC_SKIPPABLE_DELAY 400 // ms
|
||||
|
||||
#define NS_CC_FORCED (5 * 60 * PR_USEC_PER_SEC) // 5 min
|
||||
// Force a CC after this long if there's anything in the purple buffer.
|
||||
#define NS_CC_FORCED (2 * 60 * PR_USEC_PER_SEC) // 2 min
|
||||
|
||||
// Trigger a CC if the purple buffer exceeds this size when we check it.
|
||||
#define NS_CC_PURPLE_LIMIT 250
|
||||
|
||||
#define JAVASCRIPT nsIProgrammingLanguage::JAVASCRIPT
|
||||
|
||||
|
@ -2227,11 +2231,9 @@ nsJSContext::CreateNativeGlobalForInner(
|
|||
|
||||
nsRefPtr<nsIXPConnectJSObjectHolder> jsholder;
|
||||
nsresult rv = xpc->
|
||||
InitClassesWithNewWrappedGlobal(mContext,
|
||||
aNewInner, NS_GET_IID(nsISupports),
|
||||
InitClassesWithNewWrappedGlobal(mContext, aNewInner,
|
||||
aIsChrome ? systemPrincipal.get() : aPrincipal,
|
||||
nsnull, flags,
|
||||
getter_AddRefs(jsholder));
|
||||
flags, getter_AddRefs(jsholder));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2324,7 +2326,7 @@ nsJSContext::SetOuterObject(JSObject* aOuterObject)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
|
||||
|
||||
wrapper->RefreshPrototype();
|
||||
wrapper->FinishInitForWrappedGlobal();
|
||||
JS_SetPrototype(mContext, aOuterObject, JS_GetPrototype(inner));
|
||||
|
||||
return NS_OK;
|
||||
|
@ -3286,46 +3288,70 @@ ShrinkGCBuffersTimerFired(nsITimer *aTimer, void *aClosure)
|
|||
nsJSContext::ShrinkGCBuffersNow();
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
static bool
|
||||
ShouldTriggerCC(PRUint32 aSuspected)
|
||||
{
|
||||
return sNeedsFullCC ||
|
||||
aSuspected > NS_CC_PURPLE_LIMIT ||
|
||||
sLastCCEndTime + NS_CC_FORCED < PR_Now();
|
||||
}
|
||||
|
||||
static void
|
||||
TimerFireForgetSkippable(PRUint32 aSuspected, bool aRemoveChildless)
|
||||
{
|
||||
PRTime startTime = PR_Now();
|
||||
nsCycleCollector_forgetSkippable(aRemoveChildless);
|
||||
sPreviousSuspectedCount = nsCycleCollector_suspectedCount();
|
||||
sCleanupSinceLastGC = true;
|
||||
PRTime delta = PR_Now() - startTime;
|
||||
if (sMinForgetSkippableTime > delta) {
|
||||
sMinForgetSkippableTime = delta;
|
||||
}
|
||||
if (sMaxForgetSkippableTime < delta) {
|
||||
sMaxForgetSkippableTime = delta;
|
||||
}
|
||||
sTotalForgetSkippableTime += delta;
|
||||
sRemovedPurples += (aSuspected - sPreviousSuspectedCount);
|
||||
++sForgetSkippableBeforeCC;
|
||||
}
|
||||
|
||||
static void
|
||||
CCTimerFired(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
if (sDidShutdown) {
|
||||
return;
|
||||
}
|
||||
if (sCCLockedOut) {
|
||||
if (sDidShutdown || sCCLockedOut) {
|
||||
return;
|
||||
}
|
||||
++sCCTimerFireCount;
|
||||
if (sCCTimerFireCount < (NS_CC_DELAY / NS_CC_SKIPPABLE_DELAY)) {
|
||||
PRUint32 suspected = nsCycleCollector_suspectedCount();
|
||||
if ((sPreviousSuspectedCount + 100) > suspected) {
|
||||
// Just few new suspected objects, return early.
|
||||
return;
|
||||
}
|
||||
|
||||
PRTime startTime = PR_Now();
|
||||
nsCycleCollector_forgetSkippable();
|
||||
sPreviousSuspectedCount = nsCycleCollector_suspectedCount();
|
||||
sCleanupSinceLastGC = true;
|
||||
PRTime delta = PR_Now() - startTime;
|
||||
if (sMinForgetSkippableTime > delta) {
|
||||
sMinForgetSkippableTime = delta;
|
||||
}
|
||||
if (sMaxForgetSkippableTime < delta) {
|
||||
sMaxForgetSkippableTime = delta;
|
||||
}
|
||||
sTotalForgetSkippableTime += delta;
|
||||
sRemovedPurples += (suspected - sPreviousSuspectedCount);
|
||||
++sForgetSkippableBeforeCC;
|
||||
} else {
|
||||
sPreviousSuspectedCount = 0;
|
||||
nsJSContext::KillCCTimer();
|
||||
if (sNeedsFullCC ||
|
||||
nsCycleCollector_suspectedCount() > 500 ||
|
||||
sLastCCEndTime + NS_CC_FORCED < PR_Now()) {
|
||||
|
||||
// During early timer fires, we only run forgetSkippable. During the first
|
||||
// late timer fire, we decide if we are going to have a second and final
|
||||
// late timer fire, where we may run the CC.
|
||||
const PRUint32 numEarlyTimerFires = NS_CC_DELAY / NS_CC_SKIPPABLE_DELAY - 2;
|
||||
bool isLateTimerFire = sCCTimerFireCount > numEarlyTimerFires;
|
||||
PRUint32 suspected = nsCycleCollector_suspectedCount();
|
||||
if (isLateTimerFire && ShouldTriggerCC(suspected)) {
|
||||
if (sCCTimerFireCount == numEarlyTimerFires + 1) {
|
||||
TimerFireForgetSkippable(suspected, true);
|
||||
if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
|
||||
// Our efforts to avoid a CC have failed, so we return to let the
|
||||
// timer fire once more to trigger a CC.
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// We are in the final timer fire and still meet the conditions for
|
||||
// triggering a CC.
|
||||
nsJSContext::CycleCollectNow();
|
||||
}
|
||||
} else if ((sPreviousSuspectedCount + 100) <= suspected) {
|
||||
// Only do a forget skippable if there are more than a few new objects.
|
||||
TimerFireForgetSkippable(suspected, false);
|
||||
}
|
||||
|
||||
if (isLateTimerFire) {
|
||||
// We have either just run the CC or decided we don't want to run the CC
|
||||
// next time, so kill the timer.
|
||||
sPreviousSuspectedCount = 0;
|
||||
nsJSContext::KillCCTimer();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ ConvertCloneReadInfosToArrayInternal(
|
|||
}
|
||||
|
||||
if (!aReadInfos.IsEmpty()) {
|
||||
if (!JS_SetArrayLength(aCx, array, jsuint(aReadInfos.Length()))) {
|
||||
if (!JS_SetArrayLength(aCx, array, uint32_t(aReadInfos.Length()))) {
|
||||
NS_WARNING("Failed to set array length!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
|
|
@ -410,7 +410,7 @@ IDBDatabase::CreateObjectStore(const nsAString& aName,
|
|||
|
||||
JSObject* obj = JSVAL_TO_OBJECT(val);
|
||||
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!JS_GetArrayLength(aCx, obj, &length)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ IDBDatabase::CreateObjectStore(const nsAString& aName,
|
|||
|
||||
keyPathArray.SetCapacity(length);
|
||||
|
||||
for (jsuint index = 0; index < length; index++) {
|
||||
for (uint32_t index = 0; index < length; index++) {
|
||||
jsval val;
|
||||
JSString* jsstr;
|
||||
nsDependentJSString str;
|
||||
|
@ -566,7 +566,7 @@ IDBDatabase::Transaction(const jsval& aStoreNames,
|
|||
|
||||
// See if this is a JS array.
|
||||
if (JS_IsArrayObject(aCx, obj)) {
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!JS_GetArrayLength(aCx, obj, &length)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
@ -577,7 +577,7 @@ IDBDatabase::Transaction(const jsval& aStoreNames,
|
|||
|
||||
storesToOpen.SetCapacity(length);
|
||||
|
||||
for (jsuint index = 0; index < length; index++) {
|
||||
for (uint32_t index = 0; index < length; index++) {
|
||||
jsval val;
|
||||
JSString* jsstr;
|
||||
nsDependentJSString str;
|
||||
|
|
|
@ -904,7 +904,7 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
|
|||
}
|
||||
|
||||
if (!keys.IsEmpty()) {
|
||||
if (!JS_SetArrayLength(aCx, array, jsuint(keys.Length()))) {
|
||||
if (!JS_SetArrayLength(aCx, array, uint32_t(keys.Length()))) {
|
||||
NS_WARNING("Failed to set array length!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
|
|
@ -618,12 +618,12 @@ IDBObjectStore::AppendIndexUpdateInfo(PRInt64 aIndexID,
|
|||
if (aMultiEntry && !JSVAL_IS_PRIMITIVE(key) &&
|
||||
JS_IsArrayObject(aCx, JSVAL_TO_OBJECT(key))) {
|
||||
JSObject* array = JSVAL_TO_OBJECT(key);
|
||||
jsuint arrayLength;
|
||||
uint32_t arrayLength;
|
||||
if (!JS_GetArrayLength(aCx, array, &arrayLength)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
for (jsuint arrayIndex = 0; arrayIndex < arrayLength; arrayIndex++) {
|
||||
for (uint32_t arrayIndex = 0; arrayIndex < arrayLength; arrayIndex++) {
|
||||
jsval arrayItem;
|
||||
if (!JS_GetElement(aCx, array, arrayIndex, &arrayItem)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
|
@ -1700,7 +1700,7 @@ IDBObjectStore::CreateIndex(const nsAString& aName,
|
|||
|
||||
JSObject* obj = JSVAL_TO_OBJECT(aKeyPath);
|
||||
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!JS_GetArrayLength(aCx, obj, &length)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
@ -1711,7 +1711,7 @@ IDBObjectStore::CreateIndex(const nsAString& aName,
|
|||
|
||||
keyPathArray.SetCapacity(length);
|
||||
|
||||
for (jsuint index = 0; index < length; index++) {
|
||||
for (uint32_t index = 0; index < length; index++) {
|
||||
jsval val;
|
||||
JSString* jsstr;
|
||||
nsDependentJSString str;
|
||||
|
|
|
@ -170,12 +170,12 @@ Key::EncodeJSVal(JSContext* aCx, const jsval aVal, PRUint8 aTypeOffset)
|
|||
aTypeOffset < (eMaxType * MaxArrayCollapse),
|
||||
"Wrong typeoffset");
|
||||
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!JS_GetArrayLength(aCx, obj, &length)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
for (jsuint index = 0; index < length; index++) {
|
||||
for (uint32_t index = 0; index < length; index++) {
|
||||
jsval val;
|
||||
if (!JS_GetElement(aCx, obj, index, &val)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
|
@ -220,7 +220,7 @@ Key::DecodeJSVal(const unsigned char*& aPos, const unsigned char* aEnd,
|
|||
aTypeOffset = 0;
|
||||
}
|
||||
|
||||
jsuint index = 0;
|
||||
uint32_t index = 0;
|
||||
while (aPos < aEnd && *aPos - aTypeOffset != eTerminator) {
|
||||
jsval val;
|
||||
nsresult rv = DecodeJSVal(aPos, aEnd, aCx, aTypeOffset, &val);
|
||||
|
|
|
@ -36,104 +36,79 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "domstubs.idl"
|
||||
#include "nsIArray.idl"
|
||||
#include "nsIDOMEvent.idl"
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
|
||||
[scriptable, uuid(e0c271cb-266b-48c9-a7e4-96590b445c26)]
|
||||
interface mozIDOMApplicationRegistryError : nsISupports
|
||||
{
|
||||
const unsigned short DENIED = 1;
|
||||
const unsigned short PERMISSION_DENIED = 2;
|
||||
const unsigned short MANIFEST_URL_ERROR = 3;
|
||||
const unsigned short NETWORK_ERROR = 4;
|
||||
const unsigned short MANIFEST_PARSE_ERROR = 5;
|
||||
const unsigned short INVALID_MANIFEST = 6;
|
||||
interface nsIDOMDOMRequest;
|
||||
|
||||
readonly attribute short code;
|
||||
};
|
||||
|
||||
[scriptable, uuid(a6856a3d-dece-43ce-89b9-72dba07f4246)]
|
||||
interface mozIDOMApplication : nsISupports
|
||||
[scriptable, uuid(b70b84f1-7ac9-4a92-bc32-8b6a7eb7879e)]
|
||||
interface mozIDOMApplication : nsISupports
|
||||
{
|
||||
readonly attribute jsval manifest;
|
||||
readonly attribute DOMString receipt;
|
||||
readonly attribute DOMString manifestURL;
|
||||
readonly attribute nsIArray receipts; /* an array of strings */
|
||||
readonly attribute DOMString origin;
|
||||
readonly attribute DOMString installOrigin;
|
||||
readonly attribute unsigned long installTime;
|
||||
|
||||
/* startPoint will be used when several launch_path exists for an app */
|
||||
nsIDOMDOMRequest launch([optional] in DOMString startPoint);
|
||||
nsIDOMDOMRequest uninstall();
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(be170df5-9154-463b-9197-10a6195eba52)]
|
||||
interface mozIDOMApplicationRegistryEnumerateCallback : nsISupports
|
||||
[scriptable, uuid(870bfbdc-3e13-4042-99dd-18e25720782d)]
|
||||
interface mozIDOMApplicationEvent : nsIDOMEvent
|
||||
{
|
||||
void handleEvent([array, size_is(count)] in mozIDOMApplication apps,
|
||||
in unsigned long count);
|
||||
readonly attribute mozIDOMApplication application;
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(ae0ed33d-35cf-443a-837b-a6cebf16bd49)]
|
||||
interface mozIDOMApplicationRegistryErrorCallback : nsISupports
|
||||
[scriptable, uuid(a82771f6-ba46-4073-9e6e-f1ad3f42b1f6)]
|
||||
interface mozIDOMApplicationMgmt : nsIDOMEventTarget
|
||||
{
|
||||
void handleEvent(in mozIDOMApplicationRegistryError error);
|
||||
/**
|
||||
* the request will return the all the applications installed. Only accessible
|
||||
* to privileged callers.
|
||||
*/
|
||||
nsIDOMDOMRequest getAll();
|
||||
|
||||
/**
|
||||
* event listener to get notified of application installs. Only settable by
|
||||
* privileged callers.
|
||||
* the event will be a mozIDOMApplicationEvent
|
||||
*/
|
||||
attribute nsIDOMEventListener oninstall;
|
||||
|
||||
/**
|
||||
* event listener to get notified of application uninstalls. Only settable by
|
||||
* privileged callers.
|
||||
* the event will be a mozIDOMApplicationEvent
|
||||
*/
|
||||
attribute nsIDOMEventListener onuninstall;
|
||||
};
|
||||
|
||||
[scriptable, uuid(ac63c0ba-1f33-4e3e-b9aa-6a3243a9adba)]
|
||||
[scriptable, uuid(f6929871-288b-4613-9a37-9a150760ac50)]
|
||||
interface mozIDOMApplicationRegistry : nsISupports
|
||||
{
|
||||
/**
|
||||
* Install a web app. onerror can be used to report errors,
|
||||
* and oninstall if the caller is privileged.
|
||||
*
|
||||
* @param manifestUrl : the URL of the webapps manifest
|
||||
* @param receipt : An opaque string used to track payment status
|
||||
* @param manifestUrl : the URL of the webapps manifest.
|
||||
* @param parameters : A structure with optional information.
|
||||
* { receipts: ... } will be used to specify the payment receipts for this installation.
|
||||
*/
|
||||
void install(in DOMString manifestUrl,
|
||||
[optional] in DOMString receipt);
|
||||
nsIDOMDOMRequest install(in DOMString manifestUrl, [optional] in jsval parameters);
|
||||
|
||||
/**
|
||||
* This call is only accessible to privileged callers.
|
||||
*
|
||||
* @param origin : the origin of the application to uninstall.
|
||||
* the request will return the application currently installed, or null.
|
||||
*/
|
||||
void uninstall(in DOMString origin);
|
||||
nsIDOMDOMRequest getSelf();
|
||||
|
||||
/**
|
||||
* Enumerate apps : either return itself if caller is an app, or
|
||||
* apps installed from a store if caller is a store
|
||||
*
|
||||
* @param success: the callback that will get the array of applications
|
||||
* @param error: optional error callback
|
||||
* the request will return the applications installed from this origin, or null.
|
||||
*/
|
||||
void enumerate(in mozIDOMApplicationRegistryEnumerateCallback success,
|
||||
[optional] in mozIDOMApplicationRegistryErrorCallback error);
|
||||
nsIDOMDOMRequest getInstalled();
|
||||
|
||||
/**
|
||||
* Enumerate all apps installed from all stores.
|
||||
* Only usable by privileged callers.
|
||||
*
|
||||
* @param success: the callback that will get the array of applications
|
||||
* @param error: optional error callback
|
||||
*/
|
||||
void enumerateAll(in mozIDOMApplicationRegistryEnumerateCallback success,
|
||||
[optional] in mozIDOMApplicationRegistryErrorCallback error);
|
||||
|
||||
/**
|
||||
* launch a webapp. Behavior is application dependant.
|
||||
*
|
||||
* @param origin : the origin of the application to launch
|
||||
*/
|
||||
void launch(in DOMString origin);
|
||||
|
||||
/**
|
||||
* event listener to get notified of application installs. Only settable by
|
||||
* privileged callers
|
||||
*/
|
||||
attribute nsIDOMEventListener oninstall;
|
||||
|
||||
/**
|
||||
* event listener to get notified of application uninstalls. Only settable by
|
||||
* privileged callers
|
||||
*/
|
||||
attribute nsIDOMEventListener onuninstall;
|
||||
|
||||
/**
|
||||
* event listener to get notified of errors.
|
||||
*/
|
||||
attribute nsIDOMEventListener onerror;
|
||||
readonly attribute mozIDOMApplicationMgmt mgmt;
|
||||
};
|
||||
|
|
|
@ -190,12 +190,12 @@ SmsFilter::SetNumbers(JSContext* aCx, const jsval& aNumbers)
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
jsuint size;
|
||||
uint32_t size;
|
||||
JS_ALWAYS_TRUE(JS_GetArrayLength(aCx, &obj, &size));
|
||||
|
||||
nsTArray<nsString> numbers;
|
||||
|
||||
for (jsuint i=0; i<size; ++i) {
|
||||
for (uint32_t i=0; i<size; ++i) {
|
||||
jsval jsNumber;
|
||||
if (!JS_GetElement(aCx, &obj, i, &jsNumber)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
|
|
@ -199,12 +199,12 @@ SmsManager::Send(const jsval& aNumber, const nsAString& aMessage, jsval* aReturn
|
|||
// Must be an array then.
|
||||
JSObject& numbers = aNumber.toObject();
|
||||
|
||||
jsuint size;
|
||||
uint32_t size;
|
||||
JS_ALWAYS_TRUE(JS_GetArrayLength(cx, &numbers, &size));
|
||||
|
||||
jsval* requests = new jsval[size];
|
||||
|
||||
for (jsuint i=0; i<size; ++i) {
|
||||
for (uint32_t i=0; i<size; ++i) {
|
||||
jsval number;
|
||||
if (!JS_GetElement(cx, &numbers, i, &number)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
|
|
@ -11,41 +11,613 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
const RIL_SMSDATABASESERVICE_CONTRACTID = "@mozilla.org/sms/rilsmsdatabaseservice;1";
|
||||
const RIL_SMSDATABASESERVICE_CID = Components.ID("{a1fa610c-eb6c-4ac2-878f-b005d5e89249}");
|
||||
|
||||
const DEBUG = true;
|
||||
const DB_NAME = "sms";
|
||||
const DB_VERSION = 1;
|
||||
const STORE_NAME = "sms";
|
||||
|
||||
const DELIVERY_SENT = "sent";
|
||||
const DELIVERY_RECEIVED = "received";
|
||||
|
||||
const FILTER_TIMESTAMP = "timestamp";
|
||||
const FILTER_NUMBERS = "numbers";
|
||||
const FILTER_DELIVERY = "delivery";
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
|
||||
"@mozilla.org/sms/smsservice;1",
|
||||
"nsISmsService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSmsRequestManager",
|
||||
"@mozilla.org/sms/smsrequestmanager;1",
|
||||
"nsISmsRequestManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gIDBManager",
|
||||
"@mozilla.org/dom/indexeddb/manager;1",
|
||||
"nsIIndexedDatabaseManager");
|
||||
|
||||
const GLOBAL_SCOPE = this;
|
||||
|
||||
/**
|
||||
* SmsDatabaseService
|
||||
*/
|
||||
function SmsDatabaseService() {
|
||||
gIDBManager.initWindowless(GLOBAL_SCOPE);
|
||||
|
||||
let that = this;
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_ONLY, function(error, txn, store){
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
// In order to get the highest key value, we open a key cursor in reverse
|
||||
// order and get only the first pointed value.
|
||||
let request = store.openCursor(null, Ci.nsIIDBCursor.PREV);
|
||||
request.onsuccess = function onsuccess(event) {
|
||||
let cursor = event.target.result;
|
||||
if (!cursor) {
|
||||
if (DEBUG) {
|
||||
debug("Could not get the last key from sms database. " +
|
||||
"Probably empty database");
|
||||
}
|
||||
return;
|
||||
}
|
||||
that.lastKey = cursor.key || 0;
|
||||
if (DEBUG) debug("Last assigned message ID was " + that.lastKey);
|
||||
};
|
||||
request.onerror = function onerror(event) {
|
||||
if (DEBUG) {
|
||||
debug("Could not get the last key from sms database " +
|
||||
event.target.errorCode);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
this.messageLists = {};
|
||||
}
|
||||
SmsDatabaseService.prototype = {
|
||||
|
||||
classID: RIL_SMSDATABASESERVICE_CID,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISmsDatabaseService]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISmsDatabaseService,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
// nsISmsDatabaseService
|
||||
/**
|
||||
* Cache the DB here.
|
||||
*/
|
||||
db: null,
|
||||
|
||||
/**
|
||||
* This object keeps the message lists associated with each search. Each
|
||||
* message list is stored as an array of primary keys.
|
||||
*/
|
||||
messageLists: null,
|
||||
|
||||
lastMessageListId: 0,
|
||||
|
||||
/**
|
||||
* Last key value stored in the database.
|
||||
*/
|
||||
lastKey: 0,
|
||||
|
||||
/**
|
||||
* nsIObserver
|
||||
*/
|
||||
observe: function observe() {},
|
||||
|
||||
/**
|
||||
* Prepare the database. This may include opening the database and upgrading
|
||||
* it to the latest schema version.
|
||||
*
|
||||
* @param callback
|
||||
* Function that takes an error and db argument. It is called when
|
||||
* the database is ready to use or if an error occurs while preparing
|
||||
* the database.
|
||||
*
|
||||
* @return (via callback) a database ready for use.
|
||||
*/
|
||||
ensureDB: function ensureDB(callback) {
|
||||
if (this.db) {
|
||||
if (DEBUG) debug("ensureDB: already have a database, returning early.");
|
||||
callback(null, this.db);
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
function gotDB(db) {
|
||||
self.db = db;
|
||||
callback(null, db);
|
||||
}
|
||||
|
||||
let request = GLOBAL_SCOPE.mozIndexedDB.open(DB_NAME, DB_VERSION);
|
||||
request.onsuccess = function (event) {
|
||||
if (DEBUG) debug("Opened database:", DB_NAME, DB_VERSION);
|
||||
gotDB(event.target.result);
|
||||
};
|
||||
request.onupgradeneeded = function (event) {
|
||||
if (DEBUG) {
|
||||
debug("Database needs upgrade:", DB_NAME,
|
||||
event.oldVersion, event.newVersion);
|
||||
debug("Correct new database version:", event.newVersion == DB_VERSION);
|
||||
}
|
||||
|
||||
let db = event.target.result;
|
||||
|
||||
switch (event.oldVersion) {
|
||||
case 0:
|
||||
if (DEBUG) debug("New database");
|
||||
self.createSchema(db);
|
||||
break;
|
||||
|
||||
default:
|
||||
event.target.transaction.abort();
|
||||
callback("Old database version: " + event.oldVersion, null);
|
||||
break;
|
||||
}
|
||||
};
|
||||
request.onerror = function (event) {
|
||||
//TODO look at event.target.Code and change error constant accordingly
|
||||
callback("Error opening database!", null);
|
||||
};
|
||||
request.onblocked = function (event) {
|
||||
callback("Opening database request is blocked.", null);
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Start a new transaction.
|
||||
*
|
||||
* @param txn_type
|
||||
* Type of transaction (e.g. IDBTransaction.READ_WRITE)
|
||||
* @param callback
|
||||
* Function to call when the transaction is available. It will
|
||||
* be invoked with the transaction and the 'sms' object store.
|
||||
*/
|
||||
newTxn: function newTxn(txn_type, callback) {
|
||||
this.ensureDB(function (error, db) {
|
||||
if (error) {
|
||||
if (DEBUG) debug("Could not open database: " + error);
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
let txn = db.transaction([STORE_NAME], txn_type);
|
||||
if (DEBUG) debug("Started transaction " + txn + " of type " + txn_type);
|
||||
if (DEBUG) {
|
||||
txn.oncomplete = function oncomplete(event) {
|
||||
debug("Transaction " + txn + " completed.");
|
||||
};
|
||||
txn.onerror = function onerror(event) {
|
||||
//TODO check event.target.errorCode and show an appropiate error
|
||||
// message according to it.
|
||||
debug("Error occurred during transaction: " + event.target.errorCode);
|
||||
};
|
||||
}
|
||||
if (DEBUG) debug("Retrieving object store", STORE_NAME);
|
||||
let store = txn.objectStore(STORE_NAME);
|
||||
callback(null, txn, store);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Create the initial database schema.
|
||||
*
|
||||
* TODO need to worry about number normalization somewhere...
|
||||
* TODO full text search on body???
|
||||
* TODO We probably want to add a 'read' index
|
||||
*/
|
||||
createSchema: function createSchema(db) {
|
||||
let objectStore = db.createObjectStore(STORE_NAME, { keyPath: "id" });
|
||||
objectStore.createIndex("id", "id", { unique: true });
|
||||
objectStore.createIndex("delivery", "delivery", { unique: false });
|
||||
objectStore.createIndex("sender", "sender", { unique: false });
|
||||
objectStore.createIndex("receiver", "receiver", { unique: false });
|
||||
objectStore.createIndex("timestamp", "timestamp", { unique:false });
|
||||
if (DEBUG) debug("Created object stores and indexes");
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function to make the intersection of the partial result arrays
|
||||
* obtained within createMessageList.
|
||||
*
|
||||
* @param keys
|
||||
* Object containing the partial result arrays.
|
||||
* @param fiter
|
||||
* Object containing the filter search criteria used to retrieved the
|
||||
* partial results.
|
||||
*
|
||||
* return Array of keys containing the final result of createMessageList.
|
||||
*/
|
||||
keyIntersection: function keyIntersection(keys, filter) {
|
||||
let result = keys[FILTER_TIMESTAMP];
|
||||
if (keys[FILTER_NUMBERS].length || filter.numbers) {
|
||||
result = keys[FILTER_NUMBERS].filter(function(i) {
|
||||
return result.indexOf(i) != -1;
|
||||
});
|
||||
}
|
||||
if (keys[FILTER_DELIVERY].length || filter.delivery) {
|
||||
result = keys[FILTER_DELIVERY].filter(function(i) {
|
||||
return result.indexOf(i) != -1;
|
||||
});
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function called after createMessageList gets the final result array
|
||||
* containing the list of primary keys of records that matches the provided
|
||||
* search criteria. This function retrieves from the store the message with
|
||||
* the primary key matching the first one in the message list array and keeps
|
||||
* the rest of this array in memory. It also notifies via gSmsRequestManager.
|
||||
*
|
||||
* @param messageList
|
||||
* Array of primary keys retrieved within createMessageList.
|
||||
* @param requestId
|
||||
* Id used by the SmsRequestManager
|
||||
*/
|
||||
onMessageListCreated: function onMessageListCreated(messageList, requestId) {
|
||||
if (DEBUG) debug("Message list created: " + messageList);
|
||||
let self = this;
|
||||
self.newTxn(Ci.nsIIDBTransaction.READ_ONLY, function (error, txn, store) {
|
||||
if (error) {
|
||||
gSmsRequestManager.notifyReadMessageListFailed(
|
||||
requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
let messageId = messageList.shift();
|
||||
if (DEBUG) debug ("Fetching message " + messageId);
|
||||
let request = store.get(messageId);
|
||||
let message;
|
||||
request.onsuccess = function (event) {
|
||||
message = request.result;
|
||||
};
|
||||
|
||||
txn.oncomplete = function oncomplete(event) {
|
||||
if (DEBUG) debug("Transaction " + txn + " completed.");
|
||||
if (!message) {
|
||||
gSmsRequestManager.notifyReadMessageListFailed(
|
||||
requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
self.lastMessageListId += 1;
|
||||
self.messageLists[self.lastMessageListId] = messageList;
|
||||
let sms = gSmsService.createSmsMessage(message.id,
|
||||
message.delivery,
|
||||
message.sender,
|
||||
message.receiver,
|
||||
message.body,
|
||||
message.timestamp);
|
||||
gSmsRequestManager.notifyCreateMessageList(requestId,
|
||||
self.lastMessageListId,
|
||||
sms);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
saveMessage: function saveMessage(message) {
|
||||
this.lastKey += 1;
|
||||
message.id = this.lastKey;
|
||||
if (DEBUG) debug("Going to store " + JSON.stringify(message));
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function(error, txn, store) {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
let request = store.put(message);
|
||||
});
|
||||
// We return the key that we expect to store in the db
|
||||
return message.id;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* nsISmsDatabaseService API
|
||||
*/
|
||||
|
||||
saveReceivedMessage: function saveReceivedMessage(sender, body, date) {
|
||||
return -1;
|
||||
let message = {delivery: DELIVERY_RECEIVED,
|
||||
sender: sender,
|
||||
receiver: null, //TODO see bug 733266
|
||||
body: body,
|
||||
timestamp: date};
|
||||
return this.saveMessage(message);
|
||||
},
|
||||
|
||||
saveSentMessage: function saveSentMessage(receiver, body, date) {
|
||||
return -1;
|
||||
let message = {delivery: DELIVERY_SENT,
|
||||
sender: null, //TODO see bug 733266
|
||||
receiver: receiver,
|
||||
body: body,
|
||||
timestamp: date};
|
||||
return this.saveMessage(message);
|
||||
},
|
||||
|
||||
getMessage: function getMessage(messageId, requestId) {
|
||||
if (DEBUG) debug("Retrieving message with ID " + messageId);
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_ONLY, function (error, txn, store) {
|
||||
if (error) {
|
||||
if (DEBUG) debug(error);
|
||||
gSmsRequestManager.notifyGetSmsFailed(
|
||||
requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
let request = store.getAll(messageId);
|
||||
|
||||
txn.oncomplete = function oncomplete() {
|
||||
if (DEBUG) debug("Transaction " + txn + " completed.");
|
||||
if (request.result.length > 1) {
|
||||
if (DEBUG) debug("Got too many results for id " + messageId);
|
||||
gSmsRequestManager.notifyGetSmsFailed(
|
||||
requestId, Ci.nsISmsRequestManager.UNKNOWN_ERROR);
|
||||
return;
|
||||
}
|
||||
let data = request.result[0];
|
||||
if (!data) {
|
||||
if (DEBUG) debug("Message ID " + messageId + " not found");
|
||||
gSmsRequestManager.notifyGetSmsFailed(
|
||||
requestId, Ci.nsISmsRequestManager.NOT_FOUND_ERROR);
|
||||
return;
|
||||
}
|
||||
if (data.id != messageId) {
|
||||
if (DEBUG) {
|
||||
debug("Requested message ID (" + messageId + ") is " +
|
||||
"different from the one we got");
|
||||
}
|
||||
gSmsRequestManager.notifyGetSmsFailed(
|
||||
requestId, Ci.nsISmsRequestManager.UNKNOWN_ERROR);
|
||||
return;
|
||||
}
|
||||
let message = gSmsService.createSmsMessage(data.id,
|
||||
data.delivery,
|
||||
data.sender,
|
||||
data.receiver,
|
||||
data.body,
|
||||
data.timestamp);
|
||||
gSmsRequestManager.notifyGotSms(requestId, message);
|
||||
};
|
||||
|
||||
txn.onerror = function onerror(event) {
|
||||
if (DEBUG) debug("Caught error on transaction", event.target.errorCode);
|
||||
//TODO look at event.target.errorCode, pick appropriate error constant
|
||||
gSmsRequestManager.notifyGetSmsFailed(
|
||||
requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
deleteMessage: function deleteMessage(messageId, requestId) {
|
||||
let self = this;
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (error, txn, store) {
|
||||
if (error) {
|
||||
gSmsRequestManager.notifySmsDeleteFailed(
|
||||
requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
let request = store.delete(messageId);
|
||||
|
||||
request.onerror = function onerror(event) {
|
||||
if (DEBUG) debug("Caught error on request ", event.target.errorCode);
|
||||
//TODO look at event.target.errorCode
|
||||
gSmsRequestManager.notifySmsDeleteFailed(
|
||||
requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
|
||||
};
|
||||
|
||||
txn.oncomplete = function oncomplete(event) {
|
||||
if (DEBUG) debug("Transaction " + txn + " completed.");
|
||||
// Once we transaction is done, we need to check if we actually deleted
|
||||
// the message. As IndexedDB does not provide the affected records info,
|
||||
// we need to try to get the message from the database again to check
|
||||
// that it is actually gone.
|
||||
self.newTxn(Ci.nsIIDBTransaction.READ_ONLY, function (error, txn, store) {
|
||||
let request = store.getAll(messageId);
|
||||
request.onsuccess = function onsuccess(event) {
|
||||
let deleted = (event.target.result.length == 0);
|
||||
gSmsRequestManager.notifySmsDeleted(requestId, deleted);
|
||||
};
|
||||
request.onerror = function onerror(event) {
|
||||
if (DEBUG) {
|
||||
debug("Error checking the message deletion " +
|
||||
event.target.errorCode);
|
||||
}
|
||||
//TODO should we notify here as an internal error? The failed check
|
||||
// does not mean that the deletion has failed, so maybe we
|
||||
// should notify successfully.
|
||||
gSmsRequestManager.notifySmsDeleteFailed(
|
||||
requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
txn.onerror = function onerror(event) {
|
||||
if (DEBUG) debug("Caught error on transaction", event.target.errorCode);
|
||||
//TODO look at event.target.errorCode, pick appropriate error constant
|
||||
gSmsRequestManager.notifySmsDeleteFailed(
|
||||
requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
createMessageList: function createMessageList(filter, reverse, requestId) {
|
||||
if (DEBUG) {
|
||||
debug("Creating a message list. Filters:" +
|
||||
" startDate: " + filter.startDate +
|
||||
" endDate: " + filter.endDate +
|
||||
" delivery: " + filter.delivery +
|
||||
" numbers: " + filter.numbers +
|
||||
" reverse: " + reverse);
|
||||
}
|
||||
// This object keeps the lists of keys retrieved by the search specific to
|
||||
// each nsIMozSmsFilter. Once all the keys have been retrieved from the
|
||||
// store, the final intersection of this arrays will contain all the
|
||||
// keys for the message list that we are creating.
|
||||
let filteredKeys = {};
|
||||
filteredKeys[FILTER_TIMESTAMP] = [];
|
||||
filteredKeys[FILTER_NUMBERS] = [];
|
||||
filteredKeys[FILTER_DELIVERY] = [];
|
||||
|
||||
// Callback function to iterate through request results via IDBCursor.
|
||||
let successCb = function onsuccess(result, filter) {
|
||||
// Once the cursor has retrieved all keys that matches its key range,
|
||||
// the filter search is done.
|
||||
if (!result) {
|
||||
if (DEBUG) {
|
||||
debug("These messages match the " + filter + " filter: " +
|
||||
filteredKeys[filter]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// The cursor primaryKey is stored in its corresponding partial array
|
||||
// according to the filter parameter.
|
||||
let primaryKey = result.primaryKey;
|
||||
filteredKeys[filter].push(primaryKey);
|
||||
result.continue();
|
||||
};
|
||||
|
||||
let errorCb = function onerror(event) {
|
||||
//TODO look at event.target.errorCode, pick appropriate error constant.
|
||||
if (DEBUG) debug("IDBRequest error " + event.target.errorCode);
|
||||
gSmsRequestManager.notifyReadMessageListFailed(
|
||||
requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
|
||||
return;
|
||||
};
|
||||
|
||||
let self = this;
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_ONLY, function (error, txn, store) {
|
||||
if (error) {
|
||||
errorCb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// In first place, we retrieve the keys that match the filter.startDate
|
||||
// and filter.endDate search criteria.
|
||||
let timeKeyRange = null;
|
||||
if (!filter.startDate != null && filter.endDate != null) {
|
||||
timeKeyRange = IDBKeyRange.bound(filter.startDate.getTime(),
|
||||
filter.endDate.getTime());
|
||||
} else if (filter.startDate != null) {
|
||||
timeKeyRange = IDBKeyRange.lowerBound(filter.startDate.getTime());
|
||||
} else if (filter.endDate != null) {
|
||||
timeKeyRange = IDBKeyRange.upperBound(filter.endDate.getTime());
|
||||
}
|
||||
let direction = reverse ? Ci.nsIIDBCursor.PREV : Ci.nsIIDBCursor.NEXT;
|
||||
let timeRequest = store.index("timestamp").openKeyCursor(timeKeyRange,
|
||||
direction);
|
||||
|
||||
timeRequest.onsuccess = function onsuccess(event) {
|
||||
successCb(event.target.result, FILTER_TIMESTAMP);
|
||||
};
|
||||
timeRequest.onerror = errorCb;
|
||||
|
||||
// Retrieve the keys from the 'delivery' index that matches the
|
||||
// value of filter.delivery.
|
||||
if (filter.delivery) {
|
||||
let deliveryKeyRange = IDBKeyRange.only(filter.delivery);
|
||||
let deliveryRequest = store.index("delivery")
|
||||
.openKeyCursor(deliveryKeyRange);
|
||||
deliveryRequest.onsuccess = function onsuccess(event) {
|
||||
successCb(event.target.result, FILTER_DELIVERY);
|
||||
};
|
||||
deliveryRequest.onerror = errorCb;
|
||||
}
|
||||
|
||||
// Retrieve the keys from the 'sender' and 'receiver' indexes that
|
||||
// match the values of filter.numbers
|
||||
if (filter.numbers) {
|
||||
for (let i = 0; i < filter.numbers.length; i++) {
|
||||
let numberKeyRange = IDBKeyRange.only(filter.numbers[i]);
|
||||
let senderRequest = store.index("sender")
|
||||
.openKeyCursor(numberKeyRange);
|
||||
let receiverRequest = store.index("receiver")
|
||||
.openKeyCursor(numberKeyRange);
|
||||
senderRequest.onsuccess = receiverRequest.onsuccess =
|
||||
function onsuccess(event){
|
||||
successCb(event.target.result, FILTER_NUMBERS);
|
||||
};
|
||||
senderRequest.onerror = receiverRequest.onerror = errorCb;
|
||||
}
|
||||
}
|
||||
|
||||
txn.oncomplete = function oncomplete(event) {
|
||||
if (DEBUG) debug("Transaction " + txn + " completed.");
|
||||
// We need to get the intersection of all the partial searches to
|
||||
// get the final result array.
|
||||
let result = self.keyIntersection(filteredKeys, filter);
|
||||
if (!result.length) {
|
||||
if (DEBUG) debug("No messages matching the filter criteria");
|
||||
gSmsRequestManager.notifyNoMessageInList(requestId);
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point, filteredKeys should have all the keys that matches
|
||||
// all the search filters. So we take the first key and retrieve the
|
||||
// corresponding message. The rest of the keys are added to the
|
||||
// messageLists object as a new list.
|
||||
self.onMessageListCreated(result, requestId);
|
||||
};
|
||||
|
||||
txn.onerror = function onerror(event) {
|
||||
errorCb(event);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
getNextMessageInList: function getNextMessageInList(listId, requestId) {
|
||||
if (DEBUG) debug("Getting next message in list " + listId);
|
||||
let messageId;
|
||||
let list = this.messageLists[listId];
|
||||
if (!list) {
|
||||
if (DEBUG) debug("Wrong list id");
|
||||
gSmsRequestManager.notifyReadMessageListFailed(
|
||||
requestId, Ci.nsISmsRequestManager.NOT_FOUND_ERROR);
|
||||
return;
|
||||
}
|
||||
messageId = list.shift();
|
||||
if (messageId == null) {
|
||||
if (DEBUG) debug("Reached the end of the list!");
|
||||
gSmsRequestManager.notifyNoMessageInList(requestId);
|
||||
return;
|
||||
}
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_ONLY, function (error, txn, store) {
|
||||
if (DEBUG) debug("Fetching message " + messageId);
|
||||
let request = store.get(messageId);
|
||||
let message;
|
||||
request.onsuccess = function onsuccess(event) {
|
||||
message = request.result;
|
||||
};
|
||||
|
||||
txn.oncomplete = function oncomplete(event) {
|
||||
if (DEBUG) debug("Transaction " + txn + " completed.");
|
||||
if (!message) {
|
||||
if (DEBUG) debug("Could not get message id " + messageId);
|
||||
gSmsRequestManager.notifyReadMessageListFailed(
|
||||
requestId, Ci.nsISmsRequestManager.NOT_FOUND_ERROR);
|
||||
}
|
||||
let sms = gSmsService.createSmsMessage(message.id,
|
||||
message.delivery,
|
||||
message.sender,
|
||||
message.receiver,
|
||||
message.body,
|
||||
message.timestamp);
|
||||
gSmsRequestManager.notifyGotNextMessage(requestId, sms);
|
||||
};
|
||||
|
||||
txn.onerror = function onerror(event) {
|
||||
//TODO check event.target.errorCode
|
||||
if (DEBUG) {
|
||||
debug("Error retrieving message id: " + messageId +
|
||||
". Error code: " + event.target.errorCode);
|
||||
}
|
||||
gSmsRequestManager.notifyReadMessageListFailed(
|
||||
requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
clearMessageList: function clearMessageList(listId) {
|
||||
if (DEBUG) debug("Clearing message list: " + listId);
|
||||
delete this.messageLists[listId];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([SmsDatabaseService]);
|
||||
|
||||
function debug() {
|
||||
dump("SmsDatabaseService: " + Array.slice(arguments).join(" ") + "\n");
|
||||
}
|
||||
|
|
|
@ -69,6 +69,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSmsRequestManager",
|
|||
"@mozilla.org/sms/smsrequestmanager;1",
|
||||
"nsISmsRequestManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSmsDatabaseService",
|
||||
"@mozilla.org/sms/rilsmsdatabaseservice;1",
|
||||
"nsISmsDatabaseService");
|
||||
|
||||
function convertRILCallState(state) {
|
||||
switch (state) {
|
||||
case RIL.CALL_STATE_ACTIVE:
|
||||
|
@ -308,8 +312,11 @@ RadioInterfaceLayer.prototype = {
|
|||
},
|
||||
|
||||
handleSmsReceived: function handleSmsReceived(message) {
|
||||
//TODO: put the sms into a database, assign it a proper id, yada yada
|
||||
let sms = gSmsService.createSmsMessage(-1,
|
||||
debug("handleSmsReceived: " + JSON.stringify(message));
|
||||
let id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
|
||||
message.body || null,
|
||||
message.timestamp);
|
||||
let sms = gSmsService.createSmsMessage(id,
|
||||
DOM_SMS_DELIVERY_RECEIVED,
|
||||
message.sender || null,
|
||||
message.receiver || null,
|
||||
|
@ -319,13 +326,15 @@ RadioInterfaceLayer.prototype = {
|
|||
},
|
||||
|
||||
handleSmsSent: function handleSmsSent(message) {
|
||||
let sms = gSmsService.createSmsMessage(-1,
|
||||
debug("handleSmsSent: " + JSON.stringify(message));
|
||||
let timestamp = Date.now();
|
||||
let id = gSmsDatabaseService.saveSentMessage(message.number, message.body, timestamp);
|
||||
let sms = gSmsService.createSmsMessage(id,
|
||||
DOM_SMS_DELIVERY_SENT,
|
||||
null,
|
||||
message.number,
|
||||
message.body,
|
||||
Date.now());
|
||||
//TODO At this point we should save the sms into the DB (bug 712809)
|
||||
timestamp);
|
||||
//TODO handle errors (bug 727319)
|
||||
gSmsRequestManager.notifySmsSent(message.requestId, sms);
|
||||
},
|
||||
|
|
|
@ -336,80 +336,667 @@ const PDU_DCS_MSG_CLASS_TE_SPECIFIC = 0xF3;
|
|||
// Because service center timestamp omit the century. Yay.
|
||||
const PDU_TIMESTAMP_YEAR_OFFSET = 2000;
|
||||
|
||||
// 7bit Default Alphabet
|
||||
//TODO: maybe convert this to a string? might be faster/cheaper
|
||||
const PDU_ALPHABET_7BIT_DEFAULT = [
|
||||
"@", // COMMERCIAL AT
|
||||
"\xa3", // POUND SIGN
|
||||
"$", // DOLLAR SIGN
|
||||
"\xa5", // YEN SIGN
|
||||
"\xe8", // LATIN SMALL LETTER E WITH GRAVE
|
||||
"\xe9", // LATIN SMALL LETTER E WITH ACUTE
|
||||
"\xf9", // LATIN SMALL LETTER U WITH GRAVE
|
||||
"\xec", // LATIN SMALL LETTER I WITH GRAVE
|
||||
"\xf2", // LATIN SMALL LETTER O WITH GRAVE
|
||||
"\xc7", // LATIN CAPITAL LETTER C WITH CEDILLA
|
||||
"\n", // LINE FEED
|
||||
"\xd8", // LATIN CAPITAL LETTER O WITH STROKE
|
||||
"\xf8", // LATIN SMALL LETTER O WITH STROKE
|
||||
"\r", // CARRIAGE RETURN
|
||||
"\xc5", // LATIN CAPITAL LETTER A WITH RING ABOVE
|
||||
"\xe5", // LATIN SMALL LETTER A WITH RING ABOVE
|
||||
"\u0394", // GREEK CAPITAL LETTER DELTA
|
||||
"_", // LOW LINE
|
||||
"\u03a6", // GREEK CAPITAL LETTER PHI
|
||||
"\u0393", // GREEK CAPITAL LETTER GAMMA
|
||||
"\u039b", // GREEK CAPITAL LETTER LAMBDA
|
||||
"\u03a9", // GREEK CAPITAL LETTER OMEGA
|
||||
"\u03a0", // GREEK CAPITAL LETTER PI
|
||||
"\u03a8", // GREEK CAPITAL LETTER PSI
|
||||
"\u03a3", // GREEK CAPITAL LETTER SIGMA
|
||||
"\u0398", // GREEK CAPITAL LETTER THETA
|
||||
"\u039e", // GREEK CAPITAL LETTER XI
|
||||
"\u20ac", // (escape to extension table)
|
||||
"\xc6", // LATIN CAPITAL LETTER AE
|
||||
"\xe6", // LATIN SMALL LETTER AE
|
||||
"\xdf", // LATIN SMALL LETTER SHARP S (German)
|
||||
"\xc9", // LATIN CAPITAL LETTER E WITH ACUTE
|
||||
" ", // SPACE
|
||||
"!", // EXCLAMATION MARK
|
||||
"\"", // QUOTATION MARK
|
||||
"#", // NUMBER SIGN
|
||||
"\xa4", // CURRENCY SIGN
|
||||
"%", // PERCENT SIGN
|
||||
"&", // AMPERSAND
|
||||
"'", // APOSTROPHE
|
||||
"(", // LEFT PARENTHESIS
|
||||
")", // RIGHT PARENTHESIS
|
||||
"*", // ASTERISK
|
||||
"+", // PLUS SIGN
|
||||
",", // COMMA
|
||||
"-", // HYPHEN-MINUS
|
||||
".", // FULL STOP
|
||||
"/", // SOLIDUS (SLASH)
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
":", // COLON
|
||||
";", // SEMICOLON
|
||||
"<", // LESS-THAN SIGN
|
||||
"=", // EQUALS SIGN
|
||||
">", // GREATER-THAN SIGN
|
||||
"?", // QUESTION MARK
|
||||
"\xa1", // INVERTED EXCLAMATION MARK
|
||||
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
|
||||
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
||||
"\xc4", // LATIN CAPITAL LETTER A WITH DIAERESIS
|
||||
"\xd6", // LATIN CAPITAL LETTER O WITH DIAERESIS
|
||||
"\xd1", // LATIN CAPITAL LETTER N WITH TILDE
|
||||
"\xdc", // LATIN CAPITAL LETTER U WITH DIAERESIS
|
||||
"\xa7", // SECTION SIGN
|
||||
"\xbf", // INVERTED QUESTION MARK
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
|
||||
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||
"\xe4", // LATIN SMALL LETTER A WITH DIAERESIS
|
||||
"\xf6", // LATIN SMALL LETTER O WITH DIAERESIS
|
||||
"\xf1", // LATIN SMALL LETTER N WITH TILDE
|
||||
"\xfc", // LATIN SMALL LETTER U WITH DIAERESIS
|
||||
"\xe0" // LATIN SMALL LETTER A WITH GRAVE
|
||||
// See 9.2.3.24 TP‑User Data (TP‑UD)
|
||||
const PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT = 0x00;
|
||||
const PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION = 0x01;
|
||||
const PDU_IEI_APPLICATION_PORT_ADDREESING_SCHEME_8BIT = 0x04;
|
||||
const PDU_IEI_APPLICATION_PORT_ADDREESING_SCHEME_16BIT = 0x05;
|
||||
const PDU_IEI_SMSC_CONTROL_PARAMS = 0x06;
|
||||
const PDU_IEI_UDH_SOURCE_INDICATOR = 0x07;
|
||||
const PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT = 0x08;
|
||||
const PDU_IEI_WIRELESS_CONTROL_MESSAGE_PROTOCOL = 0x09;
|
||||
const PDU_IEI_TEXT_FORMATING = 0x0A;
|
||||
const PDU_IEI_PREDEFINED_SOUND = 0x0B;
|
||||
const PDU_IEI_USER_DATA_SOUND = 0x0C;
|
||||
const PDU_IEI_PREDEFINED_ANIMATION = 0x0D;
|
||||
const PDU_IEI_LARGE_ANIMATION = 0x0E;
|
||||
const PDU_IEI_SMALL_ANIMATION = 0x0F;
|
||||
const PDU_IEI_LARGE_PICTURE = 0x10;
|
||||
const PDU_IEI_SMALL_PICTURE = 0x11;
|
||||
const PDU_IEI_VARIABLE_PICTURE = 0x12;
|
||||
const PDU_IEI_USER_PROMPT_INDICATOR = 0x13;
|
||||
const PDU_IEI_EXTENDED_OBJECT = 0x14;
|
||||
const PDU_IEI_REUSED_EXTENDED_OBJECT = 0x15;
|
||||
const PDU_IEI_COMPRESS_CONTROL = 0x16;
|
||||
const PDU_IEI_OBJECT_DISTRIBUTION_INDICATOR = 0x17;
|
||||
const PDU_IEI_STANDARD_WVG_OBJECT = 0x18;
|
||||
const PDU_IEI_CHARACTER_SIZE_WVG_OBJECT = 0x19;
|
||||
const PDU_IEI_EXTENDED_OBJECT_DATA_REQUEST_COMMAND = 0x1A;
|
||||
const PDU_IEI_RFC822_EMAIL_HEADER = 0x20;
|
||||
const PDU_IEI_HYPERLINK_FORMAT_ELEMENT = 0x21;
|
||||
const PDU_IEI_REPLY_ADDRESS_ELEMENT = 0x22;
|
||||
const PDU_IEI_ENHANCED_VOICE_MAIL_INFORMATION = 0x23;
|
||||
const PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT = 0x24;
|
||||
const PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT = 0x25;
|
||||
|
||||
// 7bit alphabet escape character. The encoded value of this code point is left
|
||||
// undefined in official spec. Its code value is internally assigned to \uffff,
|
||||
// <noncharacter-FFFF> in Unicode basic multilingual plane.
|
||||
const PDU_NL_EXTENDED_ESCAPE = 0x1B;
|
||||
|
||||
// <SP>, <LF>, <CR> are only defined in locking shift tables.
|
||||
const PDU_NL_SPACE = 0x20;
|
||||
const PDU_NL_LINE_FEED = 0x0A;
|
||||
const PDU_NL_CARRIAGE_RETURN = 0x0D;
|
||||
|
||||
// 7bit alphabet page break character, only defined in single shift tables.
|
||||
// The encoded value of this code point is left undefined in official spec, but
|
||||
// the code point itself maybe be used for example in compressed CBS messages.
|
||||
// Its code value is internally assigned to \u000c, ASCII form feed, or new page.
|
||||
const PDU_NL_PAGE_BREAK = 0x0A;
|
||||
// 7bit alphabet reserved control character, only defined in single shift
|
||||
// tables. The encoded value of this code point is left undefined in official
|
||||
// spec. Its code value is internally assigned to \ufffe, <noncharacter-FFFE>
|
||||
// in Unicode basic multilingual plane.
|
||||
const PDU_NL_RESERVED_CONTROL = 0x0D;
|
||||
|
||||
const PDU_NL_IDENTIFIER_DEFAULT = 0;
|
||||
const PDU_NL_IDENTIFIER_TURKISH = 1;
|
||||
const PDU_NL_IDENTIFIER_SPANISH = 2;
|
||||
const PDU_NL_IDENTIFIER_PORTUGUESE = 3;
|
||||
const PDU_NL_IDENTIFIER_BENGALI = 4;
|
||||
const PDU_NL_IDENTIFIER_GUJARATI = 5;
|
||||
const PDU_NL_IDENTIFIER_HINDI = 6;
|
||||
const PDU_NL_IDENTIFIER_KANNADA = 7;
|
||||
const PDU_NL_IDENTIFIER_MALAYALAM = 8;
|
||||
const PDU_NL_IDENTIFIER_ORIYA = 9;
|
||||
const PDU_NL_IDENTIFIER_PUNJABI = 10;
|
||||
const PDU_NL_IDENTIFIER_TAMIL = 11;
|
||||
const PDU_NL_IDENTIFIER_TELUGU = 12;
|
||||
const PDU_NL_IDENTIFIER_URDU = 13;
|
||||
|
||||
// National Language Locking Shift Tables, see 3GPP TS 23.038
|
||||
const PDU_NL_LOCKING_SHIFT_TABLES = [
|
||||
/**
|
||||
* National Language Identifier: 0x00
|
||||
* 6.2.1 GSM 7 bit Default Alphabet
|
||||
*/
|
||||
// 01.....23.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
|
||||
"@\u00a3$\u00a5\u00e8\u00e9\u00f9\u00ec\u00f2\u00c7\n\u00d8\u00f8\r\u00c5\u00e5"
|
||||
// 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0394_\u03a6\u0393\u039b\u03a9\u03a0\u03a8\u03a3\u0398\u039e\uffff\u00c6\u00e6\u00df\u00c9"
|
||||
// 012.34.....56789ABCDEF
|
||||
+ " !\"#\u00a4%&'()*+,-./"
|
||||
// 0123456789ABCDEF
|
||||
+ "0123456789:;<=>?"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u00a1ABCDEFGHIJKLMNO"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "PQRSTUVWXYZ\u00c4\u00d6\u00d1\u00dc\u00a7"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u00bfabcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u00e4\u00f6\u00f1\u00fc\u00e0",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x01
|
||||
* A.3.1 Turkish National Language Locking Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
|
||||
"@\u00a3$\u00a5\u20ac\u00e9\u00f9\u0131\u00f2\u00c7\n\u011e\u011f\r\u00c5\u00e5"
|
||||
// 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0394_\u03a6\u0393\u039b\u03a9\u03a0\u03a8\u03a3\u0398\u039e\uffff\u015e\u015f\u00df\u00c9"
|
||||
// 012.34.....56789ABCDEF
|
||||
+ " !\"#\u00a4%&'()*+,-./"
|
||||
// 0123456789ABCDEF
|
||||
+ "0123456789:;<=>?"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u0130ABCDEFGHIJKLMNO"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "PQRSTUVWXYZ\u00c4\u00d6\u00d1\u00dc\u00a7"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u00e7abcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u00e4\u00f6\u00f1\u00fc\u00e0",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x02
|
||||
* A.3.2 Void
|
||||
*/
|
||||
// 0123456789A.BCD.EF
|
||||
" \n \r "
|
||||
// 0123456789AB.....CDEF
|
||||
+ " \uffff "
|
||||
// 0123456789ABCDEF
|
||||
+ " "
|
||||
// 0123456789ABCDEF
|
||||
+ " "
|
||||
// 0123456789ABCDEF
|
||||
+ " "
|
||||
// 0123456789ABCDEF
|
||||
+ " "
|
||||
// 0123456789ABCDEF
|
||||
+ " "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x03
|
||||
* A.3.3 Portuguese National Language Locking Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
|
||||
"@\u00a3$\u00a5\u00ea\u00e9\u00fa\u00ed\u00f3\u00e7\n\u00d4\u00f4\r\u00c1\u00e1"
|
||||
// 0.....12.....3.....4.....5.....67.8.....9.....AB.....C.....D.....E.....F.....
|
||||
+ "\u0394_\u00aa\u00c7\u00c0\u221e^\\\u20ac\u00d3|\uffff\u00c2\u00e2\u00ca\u00c9"
|
||||
// 012.34.....56789ABCDEF
|
||||
+ " !\"#\u00ba%&'()*+,-./"
|
||||
// 0123456789ABCDEF
|
||||
+ "0123456789:;<=>?"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u00cdABCDEFGHIJKLMNO"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "PQRSTUVWXYZ\u00c3\u00d5\u00da\u00dc\u00a7"
|
||||
// 0123456789ABCDEF
|
||||
+ "~abcdefghijklmno"
|
||||
// 0123456789AB.....C.....DE.....F.....
|
||||
+ "pqrstuvwxyz\u00e3\u00f5`\u00fc\u00e0",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x04
|
||||
* A.3.4 Bengali National Language Locking Shift Table
|
||||
*/
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.EF.....
|
||||
"\u0981\u0982\u0983\u0985\u0986\u0987\u0988\u0989\u098a\u098b\n\u098c \r \u098f"
|
||||
// 0.....123.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0990 \u0993\u0994\u0995\u0996\u0997\u0998\u0999\u099a\uffff\u099b\u099c\u099d\u099e"
|
||||
// 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
|
||||
+ " !\u099f\u09a0\u09a1\u09a2\u09a3\u09a4)(\u09a5\u09a6,\u09a7.\u09a8"
|
||||
// 0123456789ABCD.....E.....F
|
||||
+ "0123456789:; \u09aa\u09ab?"
|
||||
// 0.....1.....2.....3.....4.....56.....789A.....B.....C.....D.....E.....F.....
|
||||
+ "\u09ac\u09ad\u09ae\u09af\u09b0 \u09b2 \u09b6\u09b7\u09b8\u09b9\u09bc\u09bd"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....789.....A.....BCD.....E.....F.....
|
||||
+ "\u09be\u09bf\u09c0\u09c1\u09c2\u09c3\u09c4 \u09c7\u09c8 \u09cb\u09cc\u09cd"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u09ceabcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u09d7\u09dc\u09dd\u09f0\u09f1",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x05
|
||||
* A.3.5 Gujarati National Language Locking Shift Table
|
||||
*/
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.EF.....
|
||||
"\u0a81\u0a82\u0a83\u0a85\u0a86\u0a87\u0a88\u0a89\u0a8a\u0a8b\n\u0a8c\u0a8d\r \u0a8f"
|
||||
// 0.....1.....23.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0a90\u0a91 \u0a93\u0a94\u0a95\u0a96\u0a97\u0a98\u0a99\u0a9a\uffff\u0a9b\u0a9c\u0a9d\u0a9e"
|
||||
// 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
|
||||
+ " !\u0a9f\u0aa0\u0aa1\u0aa2\u0aa3\u0aa4)(\u0aa5\u0aa6,\u0aa7.\u0aa8"
|
||||
// 0123456789ABCD.....E.....F
|
||||
+ "0123456789:; \u0aaa\u0aab?"
|
||||
// 0.....1.....2.....3.....4.....56.....7.....89.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0aac\u0aad\u0aae\u0aaf\u0ab0 \u0ab2\u0ab3 \u0ab5\u0ab6\u0ab7\u0ab8\u0ab9\u0abc\u0abd"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89.....A.....B.....CD.....E.....F.....
|
||||
+ "\u0abe\u0abf\u0ac0\u0ac1\u0ac2\u0ac3\u0ac4\u0ac5 \u0ac7\u0ac8\u0ac9 \u0acb\u0acc\u0acd"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u0ad0abcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u0ae0\u0ae1\u0ae2\u0ae3\u0af1",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x06
|
||||
* A.3.6 Hindi National Language Locking Shift Table
|
||||
*/
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
|
||||
"\u0901\u0902\u0903\u0905\u0906\u0907\u0908\u0909\u090a\u090b\n\u090c\u090d\r\u090e\u090f"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0910\u0911\u0912\u0913\u0914\u0915\u0916\u0917\u0918\u0919\u091a\uffff\u091b\u091c\u091d\u091e"
|
||||
// 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
|
||||
+ " !\u091f\u0920\u0921\u0922\u0923\u0924)(\u0925\u0926,\u0927.\u0928"
|
||||
// 0123456789ABC.....D.....E.....F
|
||||
+ "0123456789:;\u0929\u092a\u092b?"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u092c\u092d\u092e\u092f\u0930\u0931\u0932\u0933\u0934\u0935\u0936\u0937\u0938\u0939\u093c\u093d"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u093e\u093f\u0940\u0941\u0942\u0943\u0944\u0945\u0946\u0947\u0948\u0949\u094a\u094b\u094c\u094d"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u0950abcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u0972\u097b\u097c\u097e\u097f",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x07
|
||||
* A.3.7 Kannada National Language Locking Shift Table
|
||||
*/
|
||||
// 01.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.E.....F.....
|
||||
" \u0c82\u0c83\u0c85\u0c86\u0c87\u0c88\u0c89\u0c8a\u0c8b\n\u0c8c \r\u0c8e\u0c8f"
|
||||
// 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0c90 \u0c92\u0c93\u0c94\u0c95\u0c96\u0c97\u0c98\u0c99\u0c9a\uffff\u0c9b\u0c9c\u0c9d\u0c9e"
|
||||
// 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
|
||||
+ " !\u0c9f\u0ca0\u0ca1\u0ca2\u0ca3\u0ca4)(\u0ca5\u0ca6,\u0ca7.\u0ca8"
|
||||
// 0123456789ABCD.....E.....F
|
||||
+ "0123456789:; \u0caa\u0cab?"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0cac\u0cad\u0cae\u0caf\u0cb0\u0cb1\u0cb2\u0cb3 \u0cb5\u0cb6\u0cb7\u0cb8\u0cb9\u0cbc\u0cbd"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....78.....9.....A.....BC.....D.....E.....F.....
|
||||
+ "\u0cbe\u0cbf\u0cc0\u0cc1\u0cc2\u0cc3\u0cc4 \u0cc6\u0cc7\u0cc8 \u0cca\u0ccb\u0ccc\u0ccd"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u0cd5abcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u0cd6\u0ce0\u0ce1\u0ce2\u0ce3",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x08
|
||||
* A.3.8 Malayalam National Language Locking Shift Table
|
||||
*/
|
||||
// 01.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.E.....F.....
|
||||
" \u0d02\u0d03\u0d05\u0d06\u0d07\u0d08\u0d09\u0d0a\u0d0b\n\u0d0c \r\u0d0e\u0d0f"
|
||||
// 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0d10 \u0d12\u0d13\u0d14\u0d15\u0d16\u0d17\u0d18\u0d19\u0d1a\uffff\u0d1b\u0d1c\u0d1d\u0d1e"
|
||||
// 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
|
||||
+ " !\u0d1f\u0d20\u0d21\u0d22\u0d23\u0d24)(\u0d25\u0d26,\u0d27.\u0d28"
|
||||
// 0123456789ABCD.....E.....F
|
||||
+ "0123456789:; \u0d2a\u0d2b?"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....EF.....
|
||||
+ "\u0d2c\u0d2d\u0d2e\u0d2f\u0d30\u0d31\u0d32\u0d33\u0d34\u0d35\u0d36\u0d37\u0d38\u0d39 \u0d3d"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....78.....9.....A.....BC.....D.....E.....F.....
|
||||
+ "\u0d3e\u0d3f\u0d40\u0d41\u0d42\u0d43\u0d44 \u0d46\u0d47\u0d48 \u0d4a\u0d4b\u0d4c\u0d4d"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u0d57abcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u0d60\u0d61\u0d62\u0d63\u0d79",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x09
|
||||
* A.3.9 Oriya National Language Locking Shift Table
|
||||
*/
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.EF.....
|
||||
"\u0b01\u0b02\u0b03\u0b05\u0b06\u0b07\u0b08\u0b09\u0b0a\u0b0b\n\u0b0c \r \u0b0f"
|
||||
// 0.....123.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0b10 \u0b13\u0b14\u0b15\u0b16\u0b17\u0b18\u0b19\u0b1a\uffff\u0b1b\u0b1c\u0b1d\u0b1e"
|
||||
// 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
|
||||
+ " !\u0b1f\u0b20\u0b21\u0b22\u0b23\u0b24)(\u0b25\u0b26,\u0b27.\u0b28"
|
||||
// 0123456789ABCD.....E.....F
|
||||
+ "0123456789:; \u0b2a\u0b2b?"
|
||||
// 0.....1.....2.....3.....4.....56.....7.....89.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0b2c\u0b2d\u0b2e\u0b2f\u0b30 \u0b32\u0b33 \u0b35\u0b36\u0b37\u0b38\u0b39\u0b3c\u0b3d"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....789.....A.....BCD.....E.....F.....
|
||||
+ "\u0b3e\u0b3f\u0b40\u0b41\u0b42\u0b43\u0b44 \u0b47\u0b48 \u0b4b\u0b4c\u0b4d"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u0b56abcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u0b57\u0b60\u0b61\u0b62\u0b63",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x0A
|
||||
* A.3.10 Punjabi National Language Locking Shift Table
|
||||
*/
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9A.BCD.EF.....
|
||||
"\u0a01\u0a02\u0a03\u0a05\u0a06\u0a07\u0a08\u0a09\u0a0a \n \r \u0a0f"
|
||||
// 0.....123.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0a10 \u0a13\u0a14\u0a15\u0a16\u0a17\u0a18\u0a19\u0a1a\uffff\u0a1b\u0a1c\u0a1d\u0a1e"
|
||||
// 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
|
||||
+ " !\u0a1f\u0a20\u0a21\u0a22\u0a23\u0a24)(\u0a25\u0a26,\u0a27.\u0a28"
|
||||
// 0123456789ABCD.....E.....F
|
||||
+ "0123456789:; \u0a2a\u0a2b?"
|
||||
// 0.....1.....2.....3.....4.....56.....7.....89.....A.....BC.....D.....E.....F
|
||||
+ "\u0a2c\u0a2d\u0a2e\u0a2f\u0a30 \u0a32\u0a33 \u0a35\u0a36 \u0a38\u0a39\u0a3c "
|
||||
// 0.....1.....2.....3.....4.....56789.....A.....BCD.....E.....F.....
|
||||
+ "\u0a3e\u0a3f\u0a40\u0a41\u0a42 \u0a47\u0a48 \u0a4b\u0a4c\u0a4d"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u0a51abcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u0a70\u0a71\u0a72\u0a73\u0a74",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x0B
|
||||
* A.3.11 Tamil National Language Locking Shift Table
|
||||
*/
|
||||
// 01.....2.....3.....4.....5.....6.....7.....8.....9A.BCD.E.....F.....
|
||||
" \u0b82\u0b83\u0b85\u0b86\u0b87\u0b88\u0b89\u0b8a \n \r\u0b8e\u0b8f"
|
||||
// 0.....12.....3.....4.....5.....6789.....A.....B.....CD.....EF.....
|
||||
+ "\u0b90 \u0b92\u0b93\u0b94\u0b95 \u0b99\u0b9a\uffff \u0b9c \u0b9e"
|
||||
// 012.....3456.....7.....89ABCDEF.....
|
||||
+ " !\u0b9f \u0ba3\u0ba4)( , .\u0ba8"
|
||||
// 0123456789ABC.....D.....EF
|
||||
+ "0123456789:;\u0ba9\u0baa ?"
|
||||
// 012.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....EF
|
||||
+ " \u0bae\u0baf\u0bb0\u0bb1\u0bb2\u0bb3\u0bb4\u0bb5\u0bb6\u0bb7\u0bb8\u0bb9 "
|
||||
// 0.....1.....2.....3.....4.....5678.....9.....A.....BC.....D.....E.....F.....
|
||||
+ "\u0bbe\u0bbf\u0bc0\u0bc1\u0bc2 \u0bc6\u0bc7\u0bc8 \u0bca\u0bcb\u0bcc\u0bcd"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u0bd0abcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u0bd7\u0bf0\u0bf1\u0bf2\u0bf9",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x0C
|
||||
* A.3.12 Telugu National Language Locking Shift Table
|
||||
*/
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.E.....F.....
|
||||
"\u0c01\u0c02\u0c03\u0c05\u0c06\u0c07\u0c08\u0c09\u0c0a\u0c0b\n\u0c0c \r\u0c0e\u0c0f"
|
||||
// 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0c10 \u0c12\u0c13\u0c14\u0c15\u0c16\u0c17\u0c18\u0c19\u0c1a\uffff\u0c1b\u0c1c\u0c1d\u0c1e"
|
||||
// 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
|
||||
+ " !\u0c1f\u0c20\u0c21\u0c22\u0c23\u0c24)(\u0c25\u0c26,\u0c27.\u0c28"
|
||||
// 0123456789ABCD.....E.....F
|
||||
+ "0123456789:; \u0c2a\u0c2b?"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89.....A.....B.....C.....D.....EF.....
|
||||
+ "\u0c2c\u0c2d\u0c2e\u0c2f\u0c30\u0c31\u0c32\u0c33 \u0c35\u0c36\u0c37\u0c38\u0c39 \u0c3d"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....78.....9.....A.....BC.....D.....E.....F.....
|
||||
+ "\u0c3e\u0c3f\u0c40\u0c41\u0c42\u0c43\u0c44 \u0c46\u0c47\u0c48 \u0c4a\u0c4b\u0c4c\u0c4d"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u0c55abcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u0c56\u0c60\u0c61\u0c62\u0c63",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x0D
|
||||
* A.3.13 Urdu National Language Locking Shift Table
|
||||
*/
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
|
||||
"\u0627\u0622\u0628\u067b\u0680\u067e\u06a6\u062a\u06c2\u067f\n\u0679\u067d\r\u067a\u067c"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u062b\u062c\u0681\u0684\u0683\u0685\u0686\u0687\u062d\u062e\u062f\uffff\u068c\u0688\u0689\u068a"
|
||||
// 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
|
||||
+ " !\u068f\u068d\u0630\u0631\u0691\u0693)(\u0699\u0632,\u0696.\u0698"
|
||||
// 0123456789ABC.....D.....E.....F
|
||||
+ "0123456789:;\u069a\u0633\u0634?"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u0635\u0636\u0637\u0638\u0639\u0641\u0642\u06a9\u06aa\u06ab\u06af\u06b3\u06b1\u0644\u0645\u0646"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
|
||||
+ "\u06ba\u06bb\u06bc\u0648\u06c4\u06d5\u06c1\u06be\u0621\u06cc\u06d0\u06d2\u064d\u0650\u064f\u0657"
|
||||
// 0.....123456789ABCDEF
|
||||
+ "\u0654abcdefghijklmno"
|
||||
// 0123456789AB.....C.....D.....E.....F.....
|
||||
+ "pqrstuvwxyz\u0655\u0651\u0653\u0656\u0670"
|
||||
];
|
||||
|
||||
// National Language Single Shift Tables, see 3GPP TS 23.038
|
||||
const PDU_NL_SINGLE_SHIFT_TABLES = [
|
||||
/**
|
||||
* National Language Identifier: 0x00
|
||||
* 6.2.1.1 GSM 7 bit default alphabet extension table
|
||||
*/
|
||||
// 0123456789A.....BCD.....EF
|
||||
" \u000c \ufffe "
|
||||
// 0123456789AB.....CDEF
|
||||
+ " ^ \uffff "
|
||||
// 0123456789ABCDEF.
|
||||
+ " {} \\"
|
||||
// 0123456789ABCDEF
|
||||
+ " [~] "
|
||||
// 0123456789ABCDEF
|
||||
+ "| "
|
||||
// 0123456789ABCDEF
|
||||
+ " "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x01
|
||||
* A.2.1 Turkish National Language Single Shift Table
|
||||
*/
|
||||
// 0123456789A.....BCD.....EF
|
||||
" \u000c \ufffe "
|
||||
// 0123456789AB.....CDEF
|
||||
+ " ^ \uffff "
|
||||
// 0123456789ABCDEF.
|
||||
+ " {} \\"
|
||||
// 0123456789ABCDEF
|
||||
+ " [~] "
|
||||
// 01234567.....89.....ABCDEF
|
||||
+ "| \u011e \u0130 "
|
||||
// 0123.....456789ABCDEF
|
||||
+ " \u015e "
|
||||
// 0123.....45.....67.....89.....ABCDEF
|
||||
+ " \u00e7 \u20ac \u011f \u0131 "
|
||||
// 0123.....456789ABCDEF
|
||||
+ " \u015f ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x02
|
||||
* A.2.2 Spanish National Language Single Shift Table
|
||||
*/
|
||||
// 0123456789.....A.....BCD.....EF
|
||||
" \u00e7\u000c \ufffe "
|
||||
// 0123456789AB.....CDEF
|
||||
+ " ^ \uffff "
|
||||
// 0123456789ABCDEF.
|
||||
+ " {} \\"
|
||||
// 0123456789ABCDEF
|
||||
+ " [~] "
|
||||
// 01.....23456789.....ABCDEF.....
|
||||
+ "|\u00c1 \u00cd \u00d3"
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u00da "
|
||||
// 01.....2345.....6789.....ABCDEF.....
|
||||
+ " \u00e1 \u20ac \u00ed \u00f3"
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u00fa ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x03
|
||||
* A.2.3 Portuguese National Language Single Shift Table
|
||||
*/
|
||||
// 012345.....6789.....A.....B.....C.....D.....E.....F.....
|
||||
" \u00ea \u00e7\u000c\u00d4\u00f4\ufffe\u00c1\u00e1"
|
||||
// 012.....3.....45.....6.....7.....8.....9.....AB.....CDEF.....
|
||||
+ " \u03a6\u0393^\u03a9\u03a0\u03a8\u03a3\u0398 \uffff \u00ca"
|
||||
// 0123456789ABCDEF.
|
||||
+ " {} \\"
|
||||
// 0123456789ABCDEF
|
||||
+ " [~] "
|
||||
// 01.....23456789.....ABCDEF.....
|
||||
+ "|\u00c0 \u00cd \u00d3"
|
||||
// 012345.....6789AB.....C.....DEF
|
||||
+ " \u00da \u00c3\u00d5 "
|
||||
// 01.....2345.....6789.....ABCDEF.....
|
||||
+ " \u00c2 \u20ac \u00ed \u00f3"
|
||||
// 012345.....6789AB.....C.....DEF.....
|
||||
+ " \u00fa \u00e3\u00f5 \u00e2",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x04
|
||||
* A.2.4 Bengali National Language Single Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.6.....789A.....BCD.....EF
|
||||
"@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
|
||||
// 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
|
||||
+ "<=>\u00a1^\u00a1_#*\u09e6\u09e7\uffff\u09e8\u09e9\u09ea\u09eb"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
|
||||
+ "\u09ec\u09ed\u09ee\u09ef\u09df\u09e0\u09e1\u09e2{}\u09e3\u09f2\u09f3\u09f4\u09f5\\"
|
||||
// 0.....1.....2.....3.....4.....56789ABCDEF
|
||||
+ "\u09f6\u09f7\u09f8\u09f9\u09fa [~] "
|
||||
// 0123456789ABCDEF
|
||||
+ "|ABCDEFGHIJKLMNO"
|
||||
// 0123456789ABCDEF
|
||||
+ "PQRSTUVWXYZ "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x05
|
||||
* A.2.5 Gujarati National Language Single Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.6.....789A.....BCD.....EF
|
||||
"@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
|
||||
// 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
|
||||
+ "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0ae6\u0ae7\u0ae8\u0ae9"
|
||||
// 0.....1.....2.....3.....4.....5.....6789ABCDEF.
|
||||
+ "\u0aea\u0aeb\u0aec\u0aed\u0aee\u0aef {} \\"
|
||||
// 0123456789ABCDEF
|
||||
+ " [~] "
|
||||
// 0123456789ABCDEF
|
||||
+ "|ABCDEFGHIJKLMNO"
|
||||
// 0123456789ABCDEF
|
||||
+ "PQRSTUVWXYZ "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x06
|
||||
* A.2.6 Hindi National Language Single Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.6.....789A.....BCD.....EF
|
||||
"@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
|
||||
// 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
|
||||
+ "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0966\u0967\u0968\u0969"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
|
||||
+ "\u096a\u096b\u096c\u096d\u096e\u096f\u0951\u0952{}\u0953\u0954\u0958\u0959\u095a\\"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....BCDEF
|
||||
+ "\u095b\u095c\u095d\u095e\u095f\u0960\u0961\u0962\u0963\u0970\u0971 [~] "
|
||||
// 0123456789ABCDEF
|
||||
+ "|ABCDEFGHIJKLMNO"
|
||||
// 0123456789ABCDEF
|
||||
+ "PQRSTUVWXYZ "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x07
|
||||
* A.2.7 Kannada National Language Single Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.6.....789A.....BCD.....EF
|
||||
"@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
|
||||
// 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
|
||||
+ "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0ce6\u0ce7\u0ce8\u0ce9"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89A.....BCDEF.
|
||||
+ "\u0cea\u0ceb\u0cec\u0ced\u0cee\u0cef\u0cde\u0cf1{}\u0cf2 \\"
|
||||
// 0123456789ABCDEF
|
||||
+ " [~] "
|
||||
// 0123456789ABCDEF
|
||||
+ "|ABCDEFGHIJKLMNO"
|
||||
// 0123456789ABCDEF
|
||||
+ "PQRSTUVWXYZ "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x08
|
||||
* A.2.8 Malayalam National Language Single Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.6.....789A.....BCD.....EF
|
||||
"@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
|
||||
// 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
|
||||
+ "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0d66\u0d67\u0d68\u0d69"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
|
||||
+ "\u0d6a\u0d6b\u0d6c\u0d6d\u0d6e\u0d6f\u0d70\u0d71{}\u0d72\u0d73\u0d74\u0d75\u0d7a\\"
|
||||
// 0.....1.....2.....3.....4.....56789ABCDEF
|
||||
+ "\u0d7b\u0d7c\u0d7d\u0d7e\u0d7f [~] "
|
||||
// 0123456789ABCDEF
|
||||
+ "|ABCDEFGHIJKLMNO"
|
||||
// 0123456789ABCDEF
|
||||
+ "PQRSTUVWXYZ "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x09
|
||||
* A.2.9 Oriya National Language Single Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.6.....789A.....BCD.....EF
|
||||
"@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
|
||||
// 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
|
||||
+ "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0b66\u0b67\u0b68\u0b69"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....DEF.
|
||||
+ "\u0b6a\u0b6b\u0b6c\u0b6d\u0b6e\u0b6f\u0b5c\u0b5d{}\u0b5f\u0b70\u0b71 \\"
|
||||
// 0123456789ABCDEF
|
||||
+ " [~] "
|
||||
// 0123456789ABCDEF
|
||||
+ "|ABCDEFGHIJKLMNO"
|
||||
// 0123456789ABCDEF
|
||||
+ "PQRSTUVWXYZ "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x0A
|
||||
* A.2.10 Punjabi National Language Single Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.6.....789A.....BCD.....EF
|
||||
"@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
|
||||
// 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
|
||||
+ "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0a66\u0a67\u0a68\u0a69"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....EF.
|
||||
+ "\u0a6a\u0a6b\u0a6c\u0a6d\u0a6e\u0a6f\u0a59\u0a5a{}\u0a5b\u0a5c\u0a5e\u0a75 \\"
|
||||
// 0123456789ABCDEF
|
||||
+ " [~] "
|
||||
// 0123456789ABCDEF
|
||||
+ "|ABCDEFGHIJKLMNO"
|
||||
// 0123456789ABCDEF
|
||||
+ "PQRSTUVWXYZ "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x0B
|
||||
* A.2.11 Tamil National Language Single Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.6.....789A.....BCD.....EF
|
||||
"@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
|
||||
// 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
|
||||
+ "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0be6\u0be7\u0be8\u0be9"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
|
||||
+ "\u0bea\u0beb\u0bec\u0bed\u0bee\u0bef\u0bf3\u0bf4{}\u0bf5\u0bf6\u0bf7\u0bf8\u0bfa\\"
|
||||
// 0123456789ABCDEF
|
||||
+ " [~] "
|
||||
// 0123456789ABCDEF
|
||||
+ "|ABCDEFGHIJKLMNO"
|
||||
// 0123456789ABCDEF
|
||||
+ "PQRSTUVWXYZ "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x0C
|
||||
* A.2.12 Telugu National Language Single Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.6.....789A.....BCD.....EF
|
||||
"@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
|
||||
// 0123.....45.....6789AB.....C.....D.....E.....F.....
|
||||
+ "<=>\u00a1^\u00a1_#* \uffff\u0c66\u0c67\u0c68\u0c69"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
|
||||
+ "\u0c6a\u0c6b\u0c6c\u0c6d\u0c6e\u0c6f\u0c58\u0c59{}\u0c78\u0c79\u0c7a\u0c7b\u0c7c\\"
|
||||
// 0.....1.....2.....3456789ABCDEF
|
||||
+ "\u0c7d\u0c7e\u0c7f [~] "
|
||||
// 0123456789ABCDEF
|
||||
+ "|ABCDEFGHIJKLMNO"
|
||||
// 0123456789ABCDEF
|
||||
+ "PQRSTUVWXYZ "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " ",
|
||||
|
||||
/**
|
||||
* National Language Identifier: 0x0D
|
||||
* A.2.13 Urdu National Language Single Shift Table
|
||||
*/
|
||||
// 01.....23.....4.....5.6.....789A.....BCD.....EF
|
||||
"@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
|
||||
// 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
|
||||
+ "<=>\u00a1^\u00a1_#*\u0600\u0601\uffff\u06f0\u06f1\u06f2\u06f3"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
|
||||
+ "\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u060c\u060d{}\u060e\u060f\u0610\u0611\u0612\\"
|
||||
// 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....CDEF.....
|
||||
+ "\u0613\u0614\u061b\u061f\u0640\u0652\u0658\u066b\u066c\u0672\u0673\u06cd[~]\u06d4"
|
||||
// 0123456789ABCDEF
|
||||
+ "|ABCDEFGHIJKLMNO"
|
||||
// 0123456789ABCDEF
|
||||
+ "PQRSTUVWXYZ "
|
||||
// 012345.....6789ABCDEF
|
||||
+ " \u20ac "
|
||||
// 0123456789ABCDEF
|
||||
+ " "
|
||||
];
|
||||
|
||||
const DATACALL_RADIOTECHNOLOGY_CDMA = 0;
|
||||
|
|
|
@ -790,8 +790,16 @@ let RIL = {
|
|||
* @param dcs
|
||||
* Data coding scheme. One of the PDU_DCS_MSG_CODING_*BITS_ALPHABET
|
||||
* constants.
|
||||
* @param bodyLengthInOctets
|
||||
* Byte length of the message body when encoded with the given DCS.
|
||||
* @param userDataHeaderLength
|
||||
* Length of embedded user data header, in bytes. The whole header
|
||||
* size will be userDataHeaderLength + 1; 0 for no header.
|
||||
* @param encodedBodyLength
|
||||
* Length of the message body when encoded with the given DCS. For
|
||||
* UCS2, in bytes; for 7-bit, in septets.
|
||||
* @param langIndex
|
||||
* Table index used for normal 7-bit encoded character lookup.
|
||||
* @param langShiftIndex
|
||||
* Table index used for escaped 7-bit encoded character lookup.
|
||||
*/
|
||||
sendSMS: function sendSMS(options) {
|
||||
let token = Buf.newParcel(REQUEST_SEND_SMS, options);
|
||||
|
@ -801,10 +809,7 @@ let RIL = {
|
|||
// handle it within tokenRequestMap[].
|
||||
Buf.writeUint32(2);
|
||||
Buf.writeString(options.SMSC);
|
||||
GsmPDUHelper.writeMessage(options.number,
|
||||
options.body,
|
||||
options.dcs,
|
||||
options.bodyLengthInOctets);
|
||||
GsmPDUHelper.writeMessage(options);
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
|
@ -2164,6 +2169,13 @@ let Phone = {
|
|||
*/
|
||||
let GsmPDUHelper = {
|
||||
|
||||
/**
|
||||
* List of tuples of national language identifier pairs.
|
||||
*/
|
||||
enabledGsmTableTuples: [
|
||||
[PDU_NL_IDENTIFIER_DEFAULT, PDU_NL_IDENTIFIER_DEFAULT],
|
||||
],
|
||||
|
||||
/**
|
||||
* Read one character (2 bytes) from a RIL string and decode as hex.
|
||||
*
|
||||
|
@ -2283,66 +2295,126 @@ let GsmPDUHelper = {
|
|||
*
|
||||
* @param length
|
||||
* Number of septets to read (*not* octets)
|
||||
* @param paddingBits
|
||||
* Number of padding bits in the first byte of user data.
|
||||
* @param langIndex
|
||||
* Table index used for normal 7-bit encoded character lookup.
|
||||
* @param langShiftIndex
|
||||
* Table index used for escaped 7-bit encoded character lookup.
|
||||
*
|
||||
* @return a string.
|
||||
*
|
||||
* TODO: support other alphabets
|
||||
* TODO: support escape chars
|
||||
*/
|
||||
readSeptetsToString: function readSeptetsToString(length) {
|
||||
readSeptetsToString: function readSeptetsToString(length, paddingBits, langIndex, langShiftIndex) {
|
||||
let ret = "";
|
||||
let byteLength = Math.ceil(length * 7 / 8);
|
||||
let byteLength = Math.ceil((length * 7 + paddingBits) / 8);
|
||||
|
||||
let leftOver = 0;
|
||||
for (let i = 0; i < byteLength; i++) {
|
||||
let octet = this.readHexOctet();
|
||||
let shift = (i % 7);
|
||||
let leftOver_mask = (0xff << (7 - shift)) & 0xff;
|
||||
let septet_mask = (0xff >> (shift + 1));
|
||||
|
||||
let septet = ((octet & septet_mask) << shift) | leftOver;
|
||||
ret += PDU_ALPHABET_7BIT_DEFAULT[septet];
|
||||
leftOver = (octet & leftOver_mask) >> (7 - shift);
|
||||
|
||||
// Every 7th byte we have a whole septet left over that we can apply.
|
||||
if (shift == 6) {
|
||||
ret += PDU_ALPHABET_7BIT_DEFAULT[leftOver];
|
||||
leftOver = 0;
|
||||
}
|
||||
/**
|
||||
* |<- last byte in header ->|
|
||||
* |<- incompleteBits ->|<- last header septet->|
|
||||
* +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
|
||||
*
|
||||
* |<- 1st byte in user data ->|
|
||||
* |<- data septet 1 ->|<-paddingBits->|
|
||||
* +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
|
||||
*
|
||||
* |<- 2nd byte in user data ->|
|
||||
* |<- data spetet 2 ->|<-ds1->|
|
||||
* +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
|
||||
*/
|
||||
let data = 0;
|
||||
let dataBits = 0;
|
||||
if (paddingBits) {
|
||||
data = this.readHexOctet() >> paddingBits;
|
||||
dataBits = 8 - paddingBits;
|
||||
--byteLength;
|
||||
}
|
||||
|
||||
let escapeFound = false;
|
||||
const langTable = PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
|
||||
const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
|
||||
do {
|
||||
// Read as much as fits in 32bit word
|
||||
let bytesToRead = Math.min(byteLength, dataBits ? 3 : 4);
|
||||
for (let i = 0; i < bytesToRead; i++) {
|
||||
data |= this.readHexOctet() << dataBits;
|
||||
dataBits += 8;
|
||||
--byteLength;
|
||||
}
|
||||
|
||||
// Consume available full septets
|
||||
for (; dataBits >= 7; dataBits -= 7) {
|
||||
let septet = data & 0x7F;
|
||||
data >>>= 7;
|
||||
|
||||
if (escapeFound) {
|
||||
escapeFound = false;
|
||||
if (septet == PDU_NL_EXTENDED_ESCAPE) {
|
||||
// According to 3GPP TS 23.038, section 6.2.1.1, NOTE 1, "On
|
||||
// receipt of this code, a receiving entity shall display a space
|
||||
// until another extensiion table is defined."
|
||||
ret += " ";
|
||||
} else if (septet == PDU_NL_RESERVED_CONTROL) {
|
||||
// According to 3GPP TS 23.038 B.2, "This code represents a control
|
||||
// character and therefore must not be used for language specific
|
||||
// characters."
|
||||
ret += " ";
|
||||
} else {
|
||||
ret += langShiftTable[septet];
|
||||
}
|
||||
} else if (septet == PDU_NL_EXTENDED_ESCAPE) {
|
||||
escapeFound = true;
|
||||
} else {
|
||||
ret += langTable[septet];
|
||||
}
|
||||
}
|
||||
} while (byteLength);
|
||||
|
||||
if (ret.length != length) {
|
||||
ret = ret.slice(0, length);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
writeStringAsSeptets: function writeStringAsSeptets(message) {
|
||||
let right = 0;
|
||||
for (let i = 0; i < message.length + 1; i++) {
|
||||
let shift = (i % 8);
|
||||
let septet;
|
||||
if (i < message.length) {
|
||||
septet = PDU_ALPHABET_7BIT_DEFAULT.indexOf(message[i]);
|
||||
} else {
|
||||
septet = 0;
|
||||
}
|
||||
if (septet == -1) {
|
||||
if (DEBUG) debug("Fffff, " + message[i] + " not in 7 bit alphabet!");
|
||||
septet = 0;
|
||||
}
|
||||
if (shift == 0) {
|
||||
// We're at the beginning of a cycle, but we need two septet values
|
||||
// to make an octet. So we're going to have to sit this one out.
|
||||
right = septet;
|
||||
writeStringAsSeptets: function writeStringAsSeptets(message, paddingBits, langIndex, langShiftIndex) {
|
||||
const langTable = PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
|
||||
const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
|
||||
|
||||
let dataBits = paddingBits;
|
||||
let data = 0;
|
||||
for (let i = 0; i < message.length; i++) {
|
||||
let septet = langTable.indexOf(message[i]);
|
||||
if (septet == PDU_NL_EXTENDED_ESCAPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let left_mask = 0xff >> (8 - shift);
|
||||
let right_mask = (0xff << shift) & 0xff;
|
||||
let left = (septet & left_mask) << (8 - shift);
|
||||
let octet = left | right;
|
||||
this.writeHexOctet(left | right);
|
||||
right = (septet & right_mask) >> shift;
|
||||
if (septet >= 0) {
|
||||
data |= septet << dataBits;
|
||||
dataBits += 7;
|
||||
} else {
|
||||
septet = langShiftTable.indexOf(message[i]);
|
||||
if (septet == -1) {
|
||||
throw new Error(message[i] + " not in 7 bit alphabet "
|
||||
+ langIndex + ":" + langShiftIndex + "!");
|
||||
}
|
||||
|
||||
if (septet == PDU_NL_RESERVED_CONTROL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data |= PDU_NL_EXTENDED_ESCAPE << dataBits;
|
||||
dataBits += 7;
|
||||
data |= septet << dataBits;
|
||||
dataBits += 7;
|
||||
}
|
||||
|
||||
for (; dataBits >= 8; dataBits -= 8) {
|
||||
this.writeHexOctet(data & 0xFF);
|
||||
data >>>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (dataBits != 0) {
|
||||
this.writeHexOctet(data & 0xFF);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2381,37 +2453,231 @@ let GsmPDUHelper = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate encoded length using specified locking/single shift table
|
||||
*
|
||||
* @param message
|
||||
* message string to be encoded.
|
||||
* @param langTable
|
||||
* locking shift table string.
|
||||
* @param langShiftTable
|
||||
* single shift table string.
|
||||
*
|
||||
* @note that the algorithm used in this function must match exactly with
|
||||
* #writeStringAsSeptets.
|
||||
*/
|
||||
_calculateLangEncodedLength: function _calculateLangEncodedLength(message, langTable, langShiftTable) {
|
||||
let length = 0;
|
||||
for (let msgIndex = 0; msgIndex < message.length; msgIndex++) {
|
||||
let septet = langTable.indexOf(message.charAt(msgIndex));
|
||||
|
||||
// According to 3GPP TS 23.038, section 6.1.1 General notes, "The
|
||||
// characters marked '1)' are not used but are displayed as a space."
|
||||
if (septet == PDU_NL_EXTENDED_ESCAPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (septet >= 0) {
|
||||
length++;
|
||||
continue;
|
||||
}
|
||||
|
||||
septet = langShiftTable.indexOf(message.charAt(msgIndex));
|
||||
if (septet == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// According to 3GPP TS 23.038 B.2, "This code represents a control
|
||||
// character and therefore must not be used for language specific
|
||||
// characters."
|
||||
if (septet == PDU_NL_RESERVED_CONTROL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The character is not found in locking shfit table, but could be
|
||||
// encoded as <escape><char> with single shift table. Note that it's
|
||||
// still possible for septet to has the value of PDU_NL_EXTENDED_ESCAPE,
|
||||
// but we can display it as a space in this case as said in previous
|
||||
// comment.
|
||||
length += 2;
|
||||
}
|
||||
|
||||
return length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate user data length and its encoding.
|
||||
*
|
||||
* The `options` parameter object should contain the `body` attribute, and
|
||||
* the `dcs`, `bodyLengthInOctets` attributes will be set as return:
|
||||
* the `dcs`, `userDataHeaderLength`, `encodedBodyLength`, `langIndex`,
|
||||
* `langShiftIndex` attributes will be set as return:
|
||||
*
|
||||
* @param body
|
||||
* String containing the message body.
|
||||
* @param dcs
|
||||
* Data coding scheme. One of the PDU_DCS_MSG_CODING_*BITS_ALPHABET
|
||||
* constants.
|
||||
* @param bodyLengthInOctets
|
||||
* Byte length of the message body when encoded with the given DCS.
|
||||
* @param userDataHeaderLength
|
||||
* Length of embedded user data header, in bytes. The whole header
|
||||
* size will be userDataHeaderLength + 1; 0 for no header.
|
||||
* @param encodedBodyLength
|
||||
* Length of the message body when encoded with the given DCS. For
|
||||
* UCS2, in bytes; for 7-bit, in septets.
|
||||
* @param langIndex
|
||||
* Table index used for normal 7-bit encoded character lookup.
|
||||
* @param langShiftIndex
|
||||
* Table index used for escaped 7-bit encoded character lookup.
|
||||
*/
|
||||
calculateUserDataLength: function calculateUserDataLength(options) {
|
||||
//TODO: support language tables, see bug 729876
|
||||
//TODO: support multipart SMS, see bug 712933
|
||||
let needUCS2 = false;
|
||||
for (let i = 0; i < options.body.length; ++i) {
|
||||
if (options.body.charCodeAt(i) >= 128) {
|
||||
needUCS2 = true;
|
||||
break;
|
||||
options.dcs = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
|
||||
options.langIndex = PDU_NL_IDENTIFIER_DEFAULT;
|
||||
options.langShiftIndex = PDU_NL_IDENTIFIER_DEFAULT;
|
||||
options.encodedBodyLength = 0;
|
||||
options.userDataHeaderLength = 0;
|
||||
|
||||
let needUCS2 = true;
|
||||
let minUserDataLength = Number.MAX_VALUE;
|
||||
for (let i = 0; i < this.enabledGsmTableTuples.length; i++) {
|
||||
let [langIndex, langShiftIndex] = this.enabledGsmTableTuples[i];
|
||||
|
||||
const langTable = PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
|
||||
const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
|
||||
|
||||
let length = this._calculateLangEncodedLength(options.body,
|
||||
langTable,
|
||||
langShiftTable);
|
||||
if (length < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let headerLen = 0;
|
||||
if (langIndex != PDU_NL_IDENTIFIER_DEFAULT) {
|
||||
headerLen += 3; // IEI + len + langIndex
|
||||
}
|
||||
if (langShiftIndex != PDU_NL_IDENTIFIER_DEFAULT) {
|
||||
headerLen += 3; // IEI + len + langShiftIndex
|
||||
}
|
||||
|
||||
// Calculate full user data length, note the extra byte is for header len
|
||||
let userDataLength = length + (headerLen ? headerLen + 1 : 0);
|
||||
if (userDataLength >= minUserDataLength) {
|
||||
continue;
|
||||
}
|
||||
|
||||
needUCS2 = false;
|
||||
minUserDataLength = userDataLength;
|
||||
|
||||
options.encodedBodyLength = length;
|
||||
options.userDataHeaderLength = headerLen;
|
||||
options.langIndex = langIndex;
|
||||
options.langShiftIndex = langShiftIndex;
|
||||
|
||||
if (userDataLength <= options.body.length) {
|
||||
// Found minimum user data length already
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (needUCS2) {
|
||||
options.dcs = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
|
||||
options.bodyLengthInOctets = options.body.length * 2;
|
||||
} else {
|
||||
options.dcs = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
|
||||
options.bodyLengthInOctets = Math.ceil(options.body.length * 7 / 8);
|
||||
options.encodedBodyLength = options.body.length * 2;
|
||||
options.userDataHeaderLength = 0;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Read 1 + UDHL octets and construct user data header at return.
|
||||
*
|
||||
* @return A header object with properties contained in received message.
|
||||
* The properties set include:
|
||||
* <ul>
|
||||
* <li>length: totoal length of the header, default 0.
|
||||
* <li>langIndex: used locking shift table index, default
|
||||
* PDU_NL_IDENTIFIER_DEFAULT.
|
||||
* <li>langShiftIndex: used locking shift table index, default
|
||||
* PDU_NL_IDENTIFIER_DEFAULT.
|
||||
* </ul>
|
||||
*/
|
||||
readUserDataHeader: function readUserDataHeader() {
|
||||
let header = {
|
||||
length: 0,
|
||||
langIndex: PDU_NL_IDENTIFIER_DEFAULT,
|
||||
langShiftIndex: PDU_NL_IDENTIFIER_DEFAULT
|
||||
};
|
||||
|
||||
header.length = this.readHexOctet();
|
||||
let dataAvailable = header.length;
|
||||
while (dataAvailable >= 2) {
|
||||
let id = this.readHexOctet();
|
||||
let length = this.readHexOctet();
|
||||
dataAvailable -= 2;
|
||||
|
||||
switch (id) {
|
||||
case PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT:
|
||||
let langShiftIndex = this.readHexOctet();
|
||||
--dataAvailable;
|
||||
if (langShiftIndex < PDU_NL_SINGLE_SHIFT_TABLES.length) {
|
||||
header.langShiftIndex = langShiftIndex;
|
||||
}
|
||||
break;
|
||||
case PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT:
|
||||
let langIndex = this.readHexOctet();
|
||||
--dataAvailable;
|
||||
if (langIndex < PDU_NL_LOCKING_SHIFT_TABLES.length) {
|
||||
header.langIndex = langIndex;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (DEBUG) {
|
||||
debug("readUserDataHeader: unsupported IEI(" + id
|
||||
+ "), " + length + " bytes.");
|
||||
}
|
||||
|
||||
// Read out unsupported data
|
||||
if (length) {
|
||||
let octets;
|
||||
if (DEBUG) octets = new Uint8Array(length);
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
let octet = this.readHexOctet();
|
||||
if (DEBUG) octets[i] = octet;
|
||||
}
|
||||
dataAvailable -= length;
|
||||
|
||||
if (DEBUG) debug("readUserDataHeader: " + Array.slice(octets));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dataAvailable != 0) {
|
||||
throw new Error("Illegal user data header found!");
|
||||
}
|
||||
|
||||
return header;
|
||||
},
|
||||
|
||||
/**
|
||||
* Write out user data header.
|
||||
*
|
||||
* @param options
|
||||
* Options containing information for user data header write-out. The
|
||||
* `userDataHeaderLength` property must be correctly pre-calculated.
|
||||
*/
|
||||
writeUserDataHeader: function writeUserDataHeader(options) {
|
||||
this.writeHexOctet(options.userDataHeaderLength);
|
||||
|
||||
if (options.langIndex != PDU_NL_IDENTIFIER_DEFAULT) {
|
||||
this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT);
|
||||
this.writeHexOctet(1);
|
||||
this.writeHexOctet(options.langIndex);
|
||||
}
|
||||
|
||||
if (options.langShiftIndex != PDU_NL_IDENTIFIER_DEFAULT) {
|
||||
this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT);
|
||||
this.writeHexOctet(1);
|
||||
this.writeHexOctet(options.langShiftIndex);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2419,7 +2685,7 @@ let GsmPDUHelper = {
|
|||
* User data can be 7 bit (default alphabet) data, 8 bit data, or 16 bit
|
||||
* (UCS2) data.
|
||||
*/
|
||||
readUserData: function readUserData(length, codingScheme) {
|
||||
readUserData: function readUserData(length, codingScheme, hasHeader) {
|
||||
if (DEBUG) {
|
||||
debug("Reading " + length + " bytes of user data.");
|
||||
debug("Coding scheme: " + codingScheme);
|
||||
|
@ -2456,6 +2722,22 @@ let GsmPDUHelper = {
|
|||
break;
|
||||
}
|
||||
|
||||
let header;
|
||||
let paddingBits = 0;
|
||||
if (hasHeader) {
|
||||
header = this.readUserDataHeader();
|
||||
|
||||
if (encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
|
||||
let headerBits = (header.length + 1) * 8;
|
||||
let headerSeptets = Math.ceil(headerBits / 7);
|
||||
|
||||
length -= headerSeptets;
|
||||
paddingBits = headerSeptets * 7 - headerBits;
|
||||
} else {
|
||||
length -= (header.length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) debug("PDU: message encoding is " + encoding + " bit.");
|
||||
switch (encoding) {
|
||||
case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
|
||||
|
@ -2465,7 +2747,11 @@ let GsmPDUHelper = {
|
|||
if (DEBUG) debug("PDU error: user data is too long: " + length);
|
||||
return null;
|
||||
}
|
||||
return this.readSeptetsToString(length);
|
||||
|
||||
return this.readSeptetsToString(length,
|
||||
paddingBits,
|
||||
hasHeader ? header.langIndex : PDU_NL_IDENTIFIER_DEFAULT,
|
||||
hasHeader ? header.langShiftIndex : PDU_NL_IDENTIFIER_DEFAULT);
|
||||
case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
|
||||
// Unsupported.
|
||||
return null;
|
||||
|
@ -2505,6 +2791,10 @@ let GsmPDUHelper = {
|
|||
|
||||
// First octet of this SMS-DELIVER or SMS-SUBMIT message
|
||||
let firstOctet = this.readHexOctet();
|
||||
|
||||
// User data header indicator
|
||||
let hasUserDataHeader = firstOctet & PDU_UDHI;
|
||||
|
||||
// if the sms is of SMS-SUBMIT type it would contain a TP-MR
|
||||
let isSmsSubmit = firstOctet & PDU_MTI_SMS_SUBMIT;
|
||||
if (isSmsSubmit) {
|
||||
|
@ -2582,7 +2872,9 @@ let GsmPDUHelper = {
|
|||
|
||||
// - TP-User-Data -
|
||||
if (userDataLength > 0) {
|
||||
msg.body = this.readUserData(userDataLength, dataCodingScheme);
|
||||
msg.body = this.readUserData(userDataLength,
|
||||
dataCodingScheme,
|
||||
hasUserDataHeader);
|
||||
}
|
||||
|
||||
return msg;
|
||||
|
@ -2602,13 +2894,29 @@ let GsmPDUHelper = {
|
|||
* @param dcs
|
||||
* Data coding scheme. One of the PDU_DCS_MSG_CODING_*BITS_ALPHABET
|
||||
* constants.
|
||||
* @param userDataLengthInOctets
|
||||
* Byte length of the user data when encoded with the given DCS.
|
||||
* @param userDataHeaderLength
|
||||
* Length of embedded user data header, in bytes. The whole header
|
||||
* size will be userDataHeaderLength + 1; 0 for no header.
|
||||
* @param encodedBodyLength
|
||||
* Length of the user data when encoded with the given DCS. For UCS2,
|
||||
* in bytes; for 7-bit, in septets.
|
||||
* @param langIndex
|
||||
* Table index used for normal 7-bit encoded character lookup.
|
||||
* @param langShiftIndex
|
||||
* Table index used for escaped 7-bit encoded character lookup.
|
||||
*/
|
||||
writeMessage: function writeMessage(address,
|
||||
userData,
|
||||
dcs,
|
||||
userDataLengthInOctets) {
|
||||
writeMessage: function writeMessage(options) {
|
||||
if (DEBUG) {
|
||||
debug("writeMessage: " + JSON.stringify(options));
|
||||
}
|
||||
let address = options.number;
|
||||
let body = options.body;
|
||||
let dcs = options.dcs;
|
||||
let userDataHeaderLength = options.userDataHeaderLength;
|
||||
let encodedBodyLength = options.encodedBodyLength;
|
||||
let langIndex = options.langIndex;
|
||||
let langShiftIndex = options.langShiftIndex;
|
||||
|
||||
// SMS-SUBMIT Format:
|
||||
//
|
||||
// PDU Type - 1 octet
|
||||
|
@ -2628,6 +2936,20 @@ let GsmPDUHelper = {
|
|||
//TODO validity is unsupported for now
|
||||
let validity = 0;
|
||||
|
||||
let headerOctets = (userDataHeaderLength ? userDataHeaderLength + 1 : 0);
|
||||
let paddingBits;
|
||||
let userDataLengthInSeptets;
|
||||
let userDataLengthInOctets;
|
||||
if (dcs == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
|
||||
let headerSeptets = Math.ceil(headerOctets * 8 / 7);
|
||||
userDataLengthInSeptets = headerSeptets + encodedBodyLength;
|
||||
userDataLengthInOctets = Math.ceil(userDataLengthInSeptets * 7 / 8);
|
||||
paddingBits = headerSeptets * 7 - headerOctets * 8;
|
||||
} else {
|
||||
userDataLengthInOctets = headerOctets + encodedBodyLength;
|
||||
paddingBits = 0;
|
||||
}
|
||||
|
||||
let pduOctetLength = 4 + // PDU Type, Message Ref, address length + format
|
||||
Math.ceil(address.length / 2) +
|
||||
3 + // PID, DCS, UDL
|
||||
|
@ -2672,8 +2994,8 @@ let GsmPDUHelper = {
|
|||
if (validity) {
|
||||
//TODO: not supported yet, OR with one of PDU_VPF_*
|
||||
}
|
||||
let udhi = ""; //TODO: for now this is unsupported
|
||||
if (udhi) {
|
||||
// User data header indicator
|
||||
if (headerOctets) {
|
||||
firstOctet |= PDU_UDHI;
|
||||
}
|
||||
this.writeHexOctet(firstOctet);
|
||||
|
@ -2699,20 +3021,25 @@ let GsmPDUHelper = {
|
|||
}
|
||||
|
||||
// - User Data -
|
||||
let userDataLength = userData.length;
|
||||
if (dcs == PDU_DCS_MSG_CODING_16BITS_ALPHABET) {
|
||||
userDataLength = userData.length * 2;
|
||||
if (dcs == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
|
||||
this.writeHexOctet(userDataLengthInSeptets);
|
||||
} else {
|
||||
this.writeHexOctet(userDataLengthInOctets);
|
||||
}
|
||||
this.writeHexOctet(userDataLength);
|
||||
|
||||
if (headerOctets) {
|
||||
this.writeUserDataHeader(options);
|
||||
}
|
||||
|
||||
switch (dcs) {
|
||||
case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
|
||||
this.writeStringAsSeptets(userData);
|
||||
this.writeStringAsSeptets(body, paddingBits, langIndex, langShiftIndex);
|
||||
break;
|
||||
case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
|
||||
// Unsupported.
|
||||
break;
|
||||
case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
|
||||
this.writeUCS2String(userData);
|
||||
this.writeUCS2String(body);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -528,8 +528,8 @@ private:
|
|||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_INFO, "Gecko", buffer.ptr());
|
||||
#endif
|
||||
fputs(buffer.ptr(), stderr);
|
||||
fflush(stderr);
|
||||
fputs(buffer.ptr(), stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -49,6 +49,7 @@ function clickEventHnalder(aEvent)
|
|||
// are a lot of functions and SimpleTest.executeSoon()s.
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SpecialPowers.setBoolPref("middlemouse.contentLoadURL", false);
|
||||
SpecialPowers.setBoolPref("middlemouse.paste", true);
|
||||
|
||||
frameWindow = iframe.contentWindow;
|
||||
|
@ -384,7 +385,9 @@ function runBodyEditableDocumentTests2()
|
|||
|
||||
function cleanup()
|
||||
{
|
||||
SpecialPowers.clearUserPref("middlemouse.contentLoadURL");
|
||||
SpecialPowers.clearUserPref("middlemouse.paste");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -1157,7 +1157,17 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
|
|||
surface->dc,
|
||||
area.left, area.top,
|
||||
SRCCOPY | NOMIRRORBITMAP);
|
||||
HRESULT hr = rt->DrawGlyphRun(0, 0, DWRITE_MEASURING_MODE_NATURAL, run, params, color);
|
||||
DWRITE_MEASURING_MODE measureMode;
|
||||
switch (scaled_font->rendering_mode) {
|
||||
case cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC:
|
||||
case cairo_d2d_surface_t::TEXT_RENDERING_NO_CLEARTYPE:
|
||||
measureMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
|
||||
break;
|
||||
default:
|
||||
measureMode = DWRITE_MEASURING_MODE_NATURAL;
|
||||
break;
|
||||
}
|
||||
HRESULT hr = rt->DrawGlyphRun(0, 0, measureMode, run, params, color);
|
||||
BitBlt(surface->dc,
|
||||
area.left, area.top,
|
||||
area.right - area.left, area.bottom - area.top,
|
||||
|
|
|
@ -1302,6 +1302,8 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c
|
|||
fBindTexture(LOCAL_GL_TEXTURE_2D, newOffscreenTexture);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (alpha) {
|
||||
fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
|
|
|
@ -232,25 +232,25 @@ _resume:
|
|||
#line 62 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ found_consonant_syllable (map, buffer, mask_array, last, p); }
|
||||
#line 67 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ set_cluster (buffer, p, last); last = p; }
|
||||
{ set_cluster (buffer, last, p); last = p; }
|
||||
break;
|
||||
case 3:
|
||||
#line 63 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ found_vowel_syllable (map, buffer, mask_array, last, p); }
|
||||
#line 67 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ set_cluster (buffer, p, last); last = p; }
|
||||
{ set_cluster (buffer, last, p); last = p; }
|
||||
break;
|
||||
case 4:
|
||||
#line 64 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ found_standalone_cluster (map, buffer, mask_array, last, p); }
|
||||
#line 67 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ set_cluster (buffer, p, last); last = p; }
|
||||
{ set_cluster (buffer, last, p); last = p; }
|
||||
break;
|
||||
case 1:
|
||||
#line 65 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ found_non_indic (map, buffer, mask_array, last, p); }
|
||||
#line 67 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ set_cluster (buffer, p, last); last = p; }
|
||||
{ set_cluster (buffer, last, p); last = p; }
|
||||
break;
|
||||
#line 256 "hb-ot-shape-complex-indic-machine.hh"
|
||||
}
|
||||
|
@ -268,25 +268,25 @@ _again:
|
|||
#line 62 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ found_consonant_syllable (map, buffer, mask_array, last, p); }
|
||||
#line 67 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ set_cluster (buffer, p, last); last = p; }
|
||||
{ set_cluster (buffer, last, p); last = p; }
|
||||
break;
|
||||
case 3:
|
||||
#line 63 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ found_vowel_syllable (map, buffer, mask_array, last, p); }
|
||||
#line 67 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ set_cluster (buffer, p, last); last = p; }
|
||||
{ set_cluster (buffer, last, p); last = p; }
|
||||
break;
|
||||
case 4:
|
||||
#line 64 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ found_standalone_cluster (map, buffer, mask_array, last, p); }
|
||||
#line 67 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ set_cluster (buffer, p, last); last = p; }
|
||||
{ set_cluster (buffer, last, p); last = p; }
|
||||
break;
|
||||
case 1:
|
||||
#line 65 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ found_non_indic (map, buffer, mask_array, last, p); }
|
||||
#line 67 "hb-ot-shape-complex-indic-machine.rl"
|
||||
{ set_cluster (buffer, p, last); last = p; }
|
||||
{ set_cluster (buffer, last, p); last = p; }
|
||||
break;
|
||||
#line 292 "hb-ot-shape-complex-indic-machine.hh"
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ action found_vowel_syllable { found_vowel_syllable (map, buffer, mask_array, las
|
|||
action found_standalone_cluster { found_standalone_cluster (map, buffer, mask_array, last, p); }
|
||||
action found_non_indic { found_non_indic (map, buffer, mask_array, last, p); }
|
||||
|
||||
action next_syllable { set_cluster (buffer, p, last); last = p; }
|
||||
action next_syllable { set_cluster (buffer, last, p); last = p; }
|
||||
|
||||
consonant_syllable = (c.N? (z.H|H.z?))* c.N? A? (H.z? | matra_group*)? syllable_tail %(found_consonant_syllable);
|
||||
vowel_syllable = (Ra H)? V N? (z.H.c | ZWJ.c)? matra_group* syllable_tail %(found_vowel_syllable);
|
||||
|
|
|
@ -48,18 +48,18 @@ namespace layers {
|
|||
static int colorId = 0;
|
||||
|
||||
static gfx3DMatrix GetRootTransform(Layer *aLayer) {
|
||||
gfx3DMatrix layerTrans = aLayer->GetTransform();
|
||||
gfx3DMatrix layerTrans = aLayer->GetTransform().ProjectTo2D();
|
||||
if (aLayer->GetParent() != NULL) {
|
||||
return GetRootTransform(aLayer->GetParent()) * layerTrans.ProjectTo2D();
|
||||
return GetRootTransform(aLayer->GetParent()) * layerTrans;
|
||||
}
|
||||
return layerTrans.ProjectTo2D();
|
||||
return layerTrans;
|
||||
}
|
||||
|
||||
void RenderTraceLayers(Layer *aLayer, const char *aColor, const gfx3DMatrix aRootTransform, bool aReset) {
|
||||
if (!aLayer)
|
||||
return;
|
||||
|
||||
gfx3DMatrix trans = aRootTransform * aLayer->GetTransform();
|
||||
gfx3DMatrix trans = aRootTransform * aLayer->GetTransform().ProjectTo2D();
|
||||
nsIntRect clipRect = aLayer->GetEffectiveVisibleRegion().GetBounds();
|
||||
gfxRect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
|
||||
trans.TransformBounds(rect);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "CompositorParent.h"
|
||||
#include "RenderTrace.h"
|
||||
#include "ShadowLayersParent.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "nsIWidget.h"
|
||||
|
|
|
@ -378,7 +378,6 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
|
|||
newBack));
|
||||
|
||||
RenderTraceInvalidateEnd(image, "FF00FF");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,8 +96,8 @@ private:
|
|||
};
|
||||
|
||||
gfxContext::gfxContext(gfxASurface *surface)
|
||||
: mSurface(surface)
|
||||
, mRefCairo(NULL)
|
||||
: mRefCairo(NULL)
|
||||
, mSurface(surface)
|
||||
{
|
||||
MOZ_COUNT_CTOR(gfxContext);
|
||||
|
||||
|
@ -1266,8 +1266,6 @@ gfxContext::ClipContainsRect(const gfxRect& aRect)
|
|||
}
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
// Since we always return false when the clip list contains a
|
||||
// non-rectangular clip or a non-rectilinear transform, our 'total' clip
|
||||
// is always a rectangle if we hit the end of this function.
|
||||
|
|
|
@ -402,9 +402,11 @@ StoreUserFontData(gfxFontEntry* aFontEntry, gfxProxyFontEntry* aProxy,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CopyWOFFMetadata(const PRUint8* aFontData, PRUint32 aLength,
|
||||
nsTArray<PRUint8>* aMetadata, PRUint32* aMetaOrigLen)
|
||||
void
|
||||
gfxUserFontSet::CopyWOFFMetadata(const PRUint8* aFontData,
|
||||
PRUint32 aLength,
|
||||
nsTArray<PRUint8>* aMetadata,
|
||||
PRUint32* aMetaOrigLen)
|
||||
{
|
||||
// This function may be called with arbitrary, unvalidated "font" data
|
||||
// from @font-face, so it needs to be careful to bounds-check, etc.,
|
||||
|
|
|
@ -281,6 +281,12 @@ protected:
|
|||
PRUint64 mGeneration;
|
||||
|
||||
static PRLogModuleInfo *sUserFontsLog;
|
||||
|
||||
private:
|
||||
static void CopyWOFFMetadata(const PRUint8* aFontData,
|
||||
PRUint32 aLength,
|
||||
nsTArray<PRUint8>* aMetadata,
|
||||
PRUint32* aMetaOrigLen);
|
||||
};
|
||||
|
||||
// acts a placeholder until the real font is downloaded
|
||||
|
|
|
@ -1169,9 +1169,7 @@ XPCShellEnvironment::Init()
|
|||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
|
||||
NS_GET_IID(nsISupports),
|
||||
principal,
|
||||
nsnull,
|
||||
nsIXPConnect::
|
||||
FLAG_SYSTEM_GLOBAL_OBJECT,
|
||||
getter_AddRefs(holder));
|
||||
|
|
|
@ -506,11 +506,11 @@ ObjectWrapperChild::AnswerNewEnumerateNext(const JSVariant& in_state,
|
|||
|
||||
jsval v = JS_GetReservedSlot(state, sNextIdIndexSlot);
|
||||
|
||||
jsuint i = JSVAL_TO_INT(v);
|
||||
int32_t i = JSVAL_TO_INT(v);
|
||||
NS_ASSERTION(i >= 0, "Index of next jsid negative?");
|
||||
NS_ASSERTION(i <= strIds->Length(), "Index of next jsid too large?");
|
||||
|
||||
if (jsuint(i) == strIds->Length()) {
|
||||
if (size_t(i) == strIds->Length()) {
|
||||
*status = JS_TRUE;
|
||||
return JSObject_to_JSVariant(cx, NULL, statep);
|
||||
}
|
||||
|
|
|
@ -165,6 +165,7 @@ CPPSRCS = \
|
|||
Parser.cpp \
|
||||
SemanticAnalysis.cpp \
|
||||
TokenStream.cpp \
|
||||
TestingFunctions.cpp \
|
||||
LifoAlloc.cpp \
|
||||
MapObject.cpp \
|
||||
MemoryMetrics.cpp \
|
||||
|
@ -173,6 +174,7 @@ CPPSRCS = \
|
|||
RegExp.cpp \
|
||||
Memory.cpp \
|
||||
Statistics.cpp \
|
||||
StringBuffer.cpp \
|
||||
Unicode.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "vm/MethodGuard-inl.h"
|
||||
#include "vm/RegExpObject-inl.h"
|
||||
#include "vm/RegExpStatics-inl.h"
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
|
|
@ -0,0 +1,570 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsbool.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jscompartment.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsprf.h"
|
||||
#include "jswrapper.h"
|
||||
|
||||
#include "methodjit/MethodJIT.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace JS;
|
||||
|
||||
static JSBool
|
||||
GC(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JSCompartment *comp = NULL;
|
||||
if (argc == 1) {
|
||||
Value arg = vp[2];
|
||||
if (arg.isObject())
|
||||
comp = UnwrapObject(&arg.toObject())->compartment();
|
||||
}
|
||||
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
size_t preBytes = cx->runtime->gcBytes;
|
||||
#endif
|
||||
|
||||
JS_CompartmentGC(cx, comp);
|
||||
|
||||
char buf[256] = { '\0' };
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
JS_snprintf(buf, sizeof(buf), "before %lu, after %lu\n",
|
||||
(unsigned long)preBytes, (unsigned long)cx->runtime->gcBytes);
|
||||
#endif
|
||||
JSString *str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
return false;
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct ParamPair {
|
||||
const char *name;
|
||||
JSGCParamKey param;
|
||||
} paramMap[] = {
|
||||
{"maxBytes", JSGC_MAX_BYTES },
|
||||
{"maxMallocBytes", JSGC_MAX_MALLOC_BYTES},
|
||||
{"gcBytes", JSGC_BYTES},
|
||||
{"gcNumber", JSGC_NUMBER},
|
||||
{"sliceTimeBudget", JSGC_SLICE_TIME_BUDGET}
|
||||
};
|
||||
|
||||
static JSBool
|
||||
GCParameter(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
if (argc == 0) {
|
||||
str = JS_ValueToString(cx, JSVAL_VOID);
|
||||
JS_ASSERT(str);
|
||||
} else {
|
||||
str = JS_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
vp[2] = STRING_TO_JSVAL(str);
|
||||
}
|
||||
|
||||
JSFlatString *flatStr = JS_FlattenString(cx, str);
|
||||
if (!flatStr)
|
||||
return false;
|
||||
|
||||
size_t paramIndex = 0;
|
||||
for (;; paramIndex++) {
|
||||
if (paramIndex == ArrayLength(paramMap)) {
|
||||
JS_ReportError(cx,
|
||||
"the first argument argument must be maxBytes, "
|
||||
"maxMallocBytes, gcStackpoolLifespan, gcBytes or "
|
||||
"gcNumber");
|
||||
return false;
|
||||
}
|
||||
if (JS_FlatStringEqualsAscii(flatStr, paramMap[paramIndex].name))
|
||||
break;
|
||||
}
|
||||
JSGCParamKey param = paramMap[paramIndex].param;
|
||||
|
||||
if (argc == 1) {
|
||||
uint32_t value = JS_GetGCParameter(cx->runtime, param);
|
||||
return JS_NewNumberValue(cx, value, &vp[0]);
|
||||
}
|
||||
|
||||
if (param == JSGC_NUMBER ||
|
||||
param == JSGC_BYTES) {
|
||||
JS_ReportError(cx, "Attempt to change read-only parameter %s",
|
||||
paramMap[paramIndex].name);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t value;
|
||||
if (!JS_ValueToECMAUint32(cx, vp[3], &value)) {
|
||||
JS_ReportError(cx,
|
||||
"the second argument must be convertable to uint32_t "
|
||||
"with non-zero value");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (param == JSGC_MAX_BYTES) {
|
||||
uint32_t gcBytes = JS_GetGCParameter(cx->runtime, JSGC_BYTES);
|
||||
if (value < gcBytes) {
|
||||
JS_ReportError(cx,
|
||||
"attempt to set maxBytes to the value less than the current "
|
||||
"gcBytes (%u)",
|
||||
gcBytes);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
JS_SetGCParameter(cx->runtime, param, value);
|
||||
*vp = JSVAL_VOID;
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
InternalConst(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
if (argc != 1) {
|
||||
JS_ReportError(cx, "the function takes exactly one argument");
|
||||
return false;
|
||||
}
|
||||
|
||||
JSString *str = JS_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return false;
|
||||
JSFlatString *flat = JS_FlattenString(cx, str);
|
||||
if (!flat)
|
||||
return false;
|
||||
|
||||
if (JS_FlatStringEqualsAscii(flat, "MARK_STACK_LENGTH")) {
|
||||
vp[0] = UINT_TO_JSVAL(js::MARK_STACK_LENGTH);
|
||||
} else {
|
||||
JS_ReportError(cx, "unknown const name");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
static JSBool
|
||||
GCZeal(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
uint32_t zeal, frequency = JS_DEFAULT_ZEAL_FREQ;
|
||||
JSBool compartment = JS_FALSE;
|
||||
|
||||
if (argc > 3) {
|
||||
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Too many arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!JS_ValueToECMAUint32(cx, argc < 1 ? JSVAL_VOID : vp[2], &zeal))
|
||||
return JS_FALSE;
|
||||
if (argc >= 2)
|
||||
if (!JS_ValueToECMAUint32(cx, vp[3], &frequency))
|
||||
return JS_FALSE;
|
||||
if (argc >= 3)
|
||||
compartment = js_ValueToBoolean(vp[3]);
|
||||
|
||||
JS_SetGCZeal(cx, (uint8_t)zeal, frequency, compartment);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ScheduleGC(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
uint32_t count;
|
||||
bool compartment = false;
|
||||
|
||||
if (argc != 1 && argc != 2) {
|
||||
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!JS_ValueToECMAUint32(cx, vp[2], &count))
|
||||
return JS_FALSE;
|
||||
if (argc == 2)
|
||||
compartment = js_ValueToBoolean(vp[3]);
|
||||
|
||||
JS_ScheduleGC(cx, count, compartment);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
VerifyBarriers(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
if (argc) {
|
||||
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Too many arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
gc::VerifyBarriers(cx);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GCSlice(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
uint32_t budget;
|
||||
|
||||
if (argc != 1) {
|
||||
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!JS_ValueToECMAUint32(cx, vp[2], &budget))
|
||||
return JS_FALSE;
|
||||
|
||||
GCDebugSlice(cx, budget);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
DeterministicGC(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
if (argc != 1) {
|
||||
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
gc::SetDeterministicGC(cx, js_ValueToBoolean(vp[2]));
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif /* JS_GC_ZEAL */
|
||||
|
||||
typedef struct JSCountHeapNode JSCountHeapNode;
|
||||
|
||||
struct JSCountHeapNode {
|
||||
void *thing;
|
||||
JSGCTraceKind kind;
|
||||
JSCountHeapNode *next;
|
||||
};
|
||||
|
||||
typedef struct JSCountHeapTracer {
|
||||
JSTracer base;
|
||||
JSDHashTable visited;
|
||||
bool ok;
|
||||
JSCountHeapNode *traceList;
|
||||
JSCountHeapNode *recycleList;
|
||||
} JSCountHeapTracer;
|
||||
|
||||
static void
|
||||
CountHeapNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
{
|
||||
JSCountHeapTracer *countTracer;
|
||||
JSDHashEntryStub *entry;
|
||||
JSCountHeapNode *node;
|
||||
void *thing = *thingp;
|
||||
|
||||
JS_ASSERT(trc->callback == CountHeapNotify);
|
||||
countTracer = (JSCountHeapTracer *)trc;
|
||||
if (!countTracer->ok)
|
||||
return;
|
||||
|
||||
entry = (JSDHashEntryStub *)
|
||||
JS_DHashTableOperate(&countTracer->visited, thing, JS_DHASH_ADD);
|
||||
if (!entry) {
|
||||
countTracer->ok = false;
|
||||
return;
|
||||
}
|
||||
if (entry->key)
|
||||
return;
|
||||
entry->key = thing;
|
||||
|
||||
node = countTracer->recycleList;
|
||||
if (node) {
|
||||
countTracer->recycleList = node->next;
|
||||
} else {
|
||||
node = (JSCountHeapNode *) js_malloc(sizeof *node);
|
||||
if (!node) {
|
||||
countTracer->ok = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
node->thing = thing;
|
||||
node->kind = kind;
|
||||
node->next = countTracer->traceList;
|
||||
countTracer->traceList = node;
|
||||
}
|
||||
|
||||
static const struct TraceKindPair {
|
||||
const char *name;
|
||||
int32_t kind;
|
||||
} traceKindNames[] = {
|
||||
{ "all", -1 },
|
||||
{ "object", JSTRACE_OBJECT },
|
||||
{ "string", JSTRACE_STRING },
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
{ "xml", JSTRACE_XML },
|
||||
#endif
|
||||
};
|
||||
|
||||
static JSBool
|
||||
CountHeap(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
void* startThing;
|
||||
JSGCTraceKind startTraceKind;
|
||||
jsval v;
|
||||
int32_t traceKind;
|
||||
JSString *str;
|
||||
JSCountHeapTracer countTracer;
|
||||
JSCountHeapNode *node;
|
||||
size_t counter;
|
||||
|
||||
startThing = NULL;
|
||||
startTraceKind = JSTRACE_OBJECT;
|
||||
if (argc > 0) {
|
||||
v = JS_ARGV(cx, vp)[0];
|
||||
if (JSVAL_IS_TRACEABLE(v)) {
|
||||
startThing = JSVAL_TO_TRACEABLE(v);
|
||||
startTraceKind = JSVAL_TRACE_KIND(v);
|
||||
} else if (!JSVAL_IS_NULL(v)) {
|
||||
JS_ReportError(cx,
|
||||
"the first argument is not null or a heap-allocated "
|
||||
"thing");
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
traceKind = -1;
|
||||
if (argc > 1) {
|
||||
str = JS_ValueToString(cx, JS_ARGV(cx, vp)[1]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
JSFlatString *flatStr = JS_FlattenString(cx, str);
|
||||
if (!flatStr)
|
||||
return JS_FALSE;
|
||||
for (size_t i = 0; ;) {
|
||||
if (JS_FlatStringEqualsAscii(flatStr, traceKindNames[i].name)) {
|
||||
traceKind = traceKindNames[i].kind;
|
||||
break;
|
||||
}
|
||||
if (++i == ArrayLength(traceKindNames)) {
|
||||
JSAutoByteString bytes(cx, str);
|
||||
if (!!bytes)
|
||||
JS_ReportError(cx, "trace kind name '%s' is unknown", bytes.ptr());
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JS_TracerInit(&countTracer.base, JS_GetRuntime(cx), CountHeapNotify);
|
||||
if (!JS_DHashTableInit(&countTracer.visited, JS_DHashGetStubOps(),
|
||||
NULL, sizeof(JSDHashEntryStub),
|
||||
JS_DHASH_DEFAULT_CAPACITY(100))) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
countTracer.ok = true;
|
||||
countTracer.traceList = NULL;
|
||||
countTracer.recycleList = NULL;
|
||||
|
||||
if (!startThing) {
|
||||
JS_TraceRuntime(&countTracer.base);
|
||||
} else {
|
||||
JS_SET_TRACING_NAME(&countTracer.base, "root");
|
||||
JS_CallTracer(&countTracer.base, startThing, startTraceKind);
|
||||
}
|
||||
|
||||
counter = 0;
|
||||
while ((node = countTracer.traceList) != NULL) {
|
||||
if (traceKind == -1 || node->kind == traceKind)
|
||||
counter++;
|
||||
countTracer.traceList = node->next;
|
||||
node->next = countTracer.recycleList;
|
||||
countTracer.recycleList = node;
|
||||
JS_TraceChildren(&countTracer.base, node->thing, node->kind);
|
||||
}
|
||||
while ((node = countTracer.recycleList) != NULL) {
|
||||
countTracer.recycleList = node->next;
|
||||
js_free(node);
|
||||
}
|
||||
JS_DHashTableFinish(&countTracer.visited);
|
||||
if (!countTracer.ok) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return JS_NewNumberValue(cx, (double) counter, vp);
|
||||
}
|
||||
|
||||
static unsigned finalizeCount = 0;
|
||||
|
||||
static void
|
||||
finalize_counter_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ATOMIC_INCREMENT(&finalizeCount);
|
||||
}
|
||||
|
||||
static JSClass FinalizeCounterClass = {
|
||||
"FinalizeCounter", JSCLASS_IS_ANONYMOUS,
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
finalize_counter_finalize
|
||||
};
|
||||
|
||||
static JSBool
|
||||
MakeFinalizeObserver(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj = JS_NewObjectWithGivenProto(cx, &FinalizeCounterClass, NULL,
|
||||
JS_GetGlobalObject(cx));
|
||||
if (!obj)
|
||||
return false;
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
FinalizeCount(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
*vp = INT_TO_JSVAL(finalizeCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
MJitCodeStats(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
JSRuntime *rt = cx->runtime;
|
||||
AutoLockGC lock(rt);
|
||||
size_t n = 0;
|
||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) {
|
||||
n += (*c)->sizeOfMjitCode();
|
||||
}
|
||||
JS_SET_RVAL(cx, vp, INT_TO_JSVAL(n));
|
||||
#else
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
MJitChunkLimit(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
if (argc != 1) {
|
||||
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
double t;
|
||||
if (!JS_ValueToNumber(cx, JS_ARGV(cx, vp)[0], &t))
|
||||
return JS_FALSE;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
mjit::SetChunkLimit((uint32_t) t);
|
||||
#endif
|
||||
|
||||
// Clear out analysis information which might refer to code compiled with
|
||||
// the previous chunk limit.
|
||||
JS_GC(cx);
|
||||
|
||||
vp->setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Terminate(JSContext *cx, unsigned arg, jsval *vp)
|
||||
{
|
||||
JS_ClearPendingException(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSFunctionSpecWithHelp TestingFunctions[] = {
|
||||
JS_FN_HELP("gc", ::GC, 0, 0,
|
||||
"gc([obj])",
|
||||
" Run the garbage collector. When obj is given, GC only its compartment."),
|
||||
|
||||
JS_FN_HELP("gcparam", GCParameter, 2, 0,
|
||||
"gcparam(name [, value])",
|
||||
" Wrapper for JS_[GS]etGCParameter. The name is either maxBytes,\n"
|
||||
" maxMallocBytes, gcBytes, gcNumber, or sliceTimeBudget."),
|
||||
|
||||
JS_FN_HELP("countHeap", CountHeap, 0, 0,
|
||||
"countHeap([start[, kind]])",
|
||||
" Count the number of live GC things in the heap or things reachable from\n"
|
||||
" start when it is given and is not null. kind is either 'all' (default) to\n"
|
||||
" count all things or one of 'object', 'double', 'string', 'function',\n"
|
||||
" 'qname', 'namespace', 'xml' to count only things of that kind."),
|
||||
|
||||
JS_FN_HELP("makeFinalizeObserver", MakeFinalizeObserver, 0, 0,
|
||||
"makeFinalizeObserver()",
|
||||
" Get a special object whose finalization increases the counter returned\n"
|
||||
" by the finalizeCount function."),
|
||||
|
||||
JS_FN_HELP("finalizeCount", FinalizeCount, 0, 0,
|
||||
"finalizeCount()",
|
||||
" Return the current value of the finalization counter that is incremented\n"
|
||||
" each time an object returned by the makeFinalizeObserver is finalized."),
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
JS_FN_HELP("gczeal", GCZeal, 2, 0,
|
||||
"gczeal(level, [period], [compartmentGC?])",
|
||||
" Specifies how zealous the garbage collector should be. Values for level:\n"
|
||||
" 0: Normal amount of collection\n"
|
||||
" 1: Collect when roots are added or removed\n"
|
||||
" 2: Collect when memory is allocated\n"
|
||||
" 3: Collect when the window paints (browser only)\n"
|
||||
" 4: Verify write barriers between instructions\n"
|
||||
" 5: Verify write barriers between paints\n"
|
||||
" Period specifies that collection happens every n allocations.\n"
|
||||
" If compartmentGC is true, the collections will be compartmental."),
|
||||
|
||||
JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,
|
||||
"schedulegc(num, [compartmentGC?])",
|
||||
" Schedule a GC to happen after num allocations."),
|
||||
|
||||
JS_FN_HELP("verifybarriers", VerifyBarriers, 0, 0,
|
||||
"verifybarriers()",
|
||||
" Start or end a run of the write barrier verifier."),
|
||||
|
||||
JS_FN_HELP("gcslice", GCSlice, 1, 0,
|
||||
"gcslice(n)",
|
||||
" Run an incremental GC slice that marks about n objects."),
|
||||
|
||||
JS_FN_HELP("deterministicgc", DeterministicGC, 1, 0,
|
||||
"deterministicgc(true|false)",
|
||||
" If true, only allow determinstic GCs to run."),
|
||||
#endif
|
||||
|
||||
JS_FN_HELP("internalConst", InternalConst, 1, 0,
|
||||
"internalConst(name)",
|
||||
" Query an internal constant for the engine. See InternalConst source for\n"
|
||||
" the list of constant names."),
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
JS_FN_HELP("mjitcodestats", MJitCodeStats, 0, 0,
|
||||
"mjitcodestats()",
|
||||
"Return stats on mjit code memory usage."),
|
||||
#endif
|
||||
|
||||
JS_FN_HELP("mjitChunkLimit", MJitChunkLimit, 1, 0,
|
||||
"mjitChunkLimit(N)",
|
||||
" Specify limit on compiled chunk size during mjit compilation."),
|
||||
|
||||
JS_FN_HELP("terminate", Terminate, 0, 0,
|
||||
"terminate()",
|
||||
" Terminate JavaScript execution, as if we had run out of\n"
|
||||
" memory or been terminated by the slow script dialog."),
|
||||
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
namespace js {
|
||||
|
||||
bool
|
||||
DefineTestingFunctions(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return JS_DefineFunctionsWithHelp(cx, obj, TestingFunctions);
|
||||
}
|
||||
|
||||
} /* namespace js */
|
|
@ -0,0 +1,16 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef TestingFunctions_h__
|
||||
#define TestingFunctions_h__
|
||||
|
||||
namespace js {
|
||||
|
||||
bool
|
||||
DefineTestingFunctions(JSContext *cx, JSObject *obj);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* TestingFunctions_h__ */
|
|
@ -148,6 +148,9 @@ xpcshell-tests:
|
|||
$(testxpcsrcdir)/runxpcshelltests.py \
|
||||
--symbols-path=$(DIST)/crashreporter-symbols \
|
||||
--build-info-json=$(DEPTH)/mozinfo.json \
|
||||
--tests-root-dir=$(testxpcobjdir) \
|
||||
--xunit-file=$(testxpcobjdir)/$(relativesrcdir)/results.xml \
|
||||
--xunit-suite-name=xpcshell \
|
||||
$(EXTRA_TEST_ARGS) \
|
||||
$(LIBXUL_DIST)/bin/xpcshell \
|
||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
|
||||
|
|
|
@ -616,9 +616,10 @@ if test "$GXX" = "yes"; then
|
|||
GNU_CXX=1
|
||||
CXX_VERSION=`$CXX -v 2>&1 | grep 'gcc version'`
|
||||
fi
|
||||
if test "`echo | $AS -v 2>&1 | grep -c GNU`" != "0"; then
|
||||
if test "`echo | $AS -o conftest.out -v 2>&1 | grep -c GNU`" != "0"; then
|
||||
GNU_AS=1
|
||||
fi
|
||||
rm -f conftest.out
|
||||
if test "`echo | $LD -v 2>&1 | grep -c GNU`" != "0"; then
|
||||
GNU_LD=1
|
||||
fi
|
||||
|
|
|
@ -1574,7 +1574,7 @@ jsvalToPtrExplicit(JSContext* cx, jsval val, uintptr_t* result)
|
|||
|
||||
template<class IntegerType, class CharType, size_t N, class AP>
|
||||
void
|
||||
IntegerToString(IntegerType i, jsuint radix, Vector<CharType, N, AP>& result)
|
||||
IntegerToString(IntegerType i, int radix, Vector<CharType, N, AP>& result)
|
||||
{
|
||||
JS_STATIC_ASSERT(numeric_limits<IntegerType>::is_exact);
|
||||
|
||||
|
@ -1955,7 +1955,7 @@ ImplicitConvert(JSContext* cx,
|
|||
JS_IsArrayObject(cx, JSVAL_TO_OBJECT(val))) {
|
||||
// Convert each element of the array by calling ImplicitConvert.
|
||||
JSObject* sourceArray = JSVAL_TO_OBJECT(val);
|
||||
jsuint sourceLength;
|
||||
uint32_t sourceLength;
|
||||
if (!JS_GetArrayLength(cx, sourceArray, &sourceLength) ||
|
||||
targetLength != size_t(sourceLength)) {
|
||||
JS_ReportError(cx, "ArrayType length does not match source array length");
|
||||
|
@ -1971,7 +1971,7 @@ ImplicitConvert(JSContext* cx,
|
|||
return false;
|
||||
}
|
||||
|
||||
for (jsuint i = 0; i < sourceLength; ++i) {
|
||||
for (uint32_t i = 0; i < sourceLength; ++i) {
|
||||
js::AutoValueRooter item(cx);
|
||||
if (!JS_GetElement(cx, sourceArray, i, item.jsval_addr()))
|
||||
return false;
|
||||
|
@ -4112,7 +4112,7 @@ StructType::Create(JSContext* cx, unsigned argc, jsval* vp)
|
|||
JSBool
|
||||
StructType::DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj)
|
||||
{
|
||||
jsuint len;
|
||||
uint32_t len;
|
||||
ASSERT_OK(JS_GetArrayLength(cx, fieldsObj, &len));
|
||||
|
||||
// Get the common prototype for CData objects of this type from
|
||||
|
@ -4150,7 +4150,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj
|
|||
structSize = 0;
|
||||
structAlign = 0;
|
||||
|
||||
for (jsuint i = 0; i < len; ++i) {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
js::AutoValueRooter item(cx);
|
||||
if (!JS_GetElement(cx, fieldsObj, i, item.jsval_addr()))
|
||||
return JS_FALSE;
|
||||
|
@ -4925,7 +4925,7 @@ FunctionType::Create(JSContext* cx, unsigned argc, jsval* vp)
|
|||
}
|
||||
|
||||
arrayObj = JSVAL_TO_OBJECT(argv[2]);
|
||||
jsuint len;
|
||||
uint32_t len;
|
||||
ASSERT_OK(JS_GetArrayLength(cx, arrayObj, &len));
|
||||
|
||||
if (!argTypes.appendN(JSVAL_VOID, len)) {
|
||||
|
@ -4937,7 +4937,7 @@ FunctionType::Create(JSContext* cx, unsigned argc, jsval* vp)
|
|||
// Pull out the argument types from the array, if any.
|
||||
JS_ASSERT(!argTypes.length() || arrayObj);
|
||||
js::AutoArrayRooter items(cx, argTypes.length(), argTypes.begin());
|
||||
for (jsuint i = 0; i < argTypes.length(); ++i) {
|
||||
for (uint32_t i = 0; i < argTypes.length(); ++i) {
|
||||
if (!JS_GetElement(cx, arrayObj, i, &argTypes[i]))
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -4956,7 +4956,7 @@ FunctionType::CreateInternal(JSContext* cx,
|
|||
jsval abi,
|
||||
jsval rtype,
|
||||
jsval* argtypes,
|
||||
jsuint arglen)
|
||||
unsigned arglen)
|
||||
{
|
||||
// Determine and check the types, and prepare the function CIF.
|
||||
AutoPtr<FunctionInfo> fninfo(NewFunctionInfo(cx, abi, rtype, argtypes, arglen));
|
||||
|
@ -5109,7 +5109,7 @@ FunctionType::Call(JSContext* cx,
|
|||
}
|
||||
|
||||
jsval* argv = JS_ARGV(cx, vp);
|
||||
for (jsuint i = 0; i < argcFixed; ++i)
|
||||
for (unsigned i = 0; i < argcFixed; ++i)
|
||||
if (!ConvertArgument(cx, argv[i], fninfo->mArgTypes[i], &values[i], &strings))
|
||||
return false;
|
||||
|
||||
|
@ -6044,7 +6044,7 @@ Int64Base::ToString(JSContext* cx,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
jsuint radix = 10;
|
||||
int radix = 10;
|
||||
if (argc == 1) {
|
||||
jsval arg = JS_ARGV(cx, vp)[0];
|
||||
if (JSVAL_IS_INT(arg))
|
||||
|
|
|
@ -496,7 +496,7 @@ namespace StructType {
|
|||
|
||||
namespace FunctionType {
|
||||
JSObject* CreateInternal(JSContext* cx, jsval abi, jsval rtype,
|
||||
jsval* argtypes, jsuint arglen);
|
||||
jsval* argtypes, unsigned arglen);
|
||||
|
||||
JSObject* ConstructWithObject(JSContext* cx, JSObject* typeObj,
|
||||
JSObject* refObj, PRFuncPtr fnptr, JSObject* result);
|
||||
|
|
|
@ -1010,7 +1010,7 @@ BytecodeEmitter::shouldNoteClosedName(ParseNode *pn)
|
|||
static int
|
||||
AdjustBlockSlot(JSContext *cx, BytecodeEmitter *bce, int slot)
|
||||
{
|
||||
JS_ASSERT((jsuint) slot < bce->maxStackDepth);
|
||||
JS_ASSERT((unsigned) slot < bce->maxStackDepth);
|
||||
if (bce->inFunction()) {
|
||||
slot += bce->bindings.countVars();
|
||||
if ((unsigned) slot >= SLOTNO_LIMIT) {
|
||||
|
@ -2468,7 +2468,7 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
continue;
|
||||
}
|
||||
i = pn3->pn_pval->toInt32();
|
||||
if ((jsuint)(i + (int)JS_BIT(15)) >= (jsuint)JS_BIT(16)) {
|
||||
if ((unsigned)(i + (int)JS_BIT(15)) >= (unsigned)JS_BIT(16)) {
|
||||
switchOp = JSOP_LOOKUPSWITCH;
|
||||
continue;
|
||||
}
|
||||
|
@ -3068,7 +3068,7 @@ EmitDestructuringOpsHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
|||
{
|
||||
JS_ASSERT(emitOption != DefineVars);
|
||||
|
||||
jsuint index;
|
||||
unsigned index;
|
||||
ParseNode *pn2, *pn3;
|
||||
JSBool doElemOp;
|
||||
|
||||
|
@ -3303,7 +3303,7 @@ static JSBool
|
|||
EmitGroupAssignment(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp,
|
||||
ParseNode *lhs, ParseNode *rhs)
|
||||
{
|
||||
jsuint depth, limit, i, nslots;
|
||||
unsigned depth, limit, i, nslots;
|
||||
ParseNode *pn;
|
||||
|
||||
depth = limit = (unsigned) bce->stackDepth;
|
||||
|
@ -4931,6 +4931,9 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
jmp = EmitJump(cx, bce, JSOP_GOTO, 0);
|
||||
if (jmp < 0)
|
||||
return false;
|
||||
} else {
|
||||
if (op != JSOP_NOP && Emit1(cx, bce, JSOP_NOP) < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
top = bce->offset();
|
||||
|
|
|
@ -6810,7 +6810,7 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
|
|||
case TOK_LB:
|
||||
{
|
||||
JSBool matched;
|
||||
jsuint index;
|
||||
unsigned index;
|
||||
|
||||
pn = ListNode::create(PNK_RB, tc);
|
||||
if (!pn)
|
||||
|
|
|
@ -294,8 +294,10 @@ HeapId::pre()
|
|||
if (JS_UNLIKELY(JSID_IS_OBJECT(value))) {
|
||||
JSObject *obj = JSID_TO_OBJECT(value);
|
||||
JSCompartment *comp = obj->compartment();
|
||||
if (comp->needsBarrier())
|
||||
js::gc::MarkObjectUnbarriered(comp->barrierTracer(), obj, "write barrier");
|
||||
if (comp->needsBarrier()) {
|
||||
js::gc::MarkObjectUnbarriered(comp->barrierTracer(), &obj, "write barrier");
|
||||
JS_ASSERT(obj == JSID_TO_OBJECT(value));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
static JSGCCallback oldGCCallback;
|
||||
|
||||
static void **checkPointers;
|
||||
static jsuint checkPointersLength;
|
||||
static unsigned checkPointersLength;
|
||||
static size_t checkPointersStaticStrings;
|
||||
|
||||
static JSBool
|
||||
TestAboutToBeFinalizedCallback(JSContext *cx, JSGCStatus status)
|
||||
{
|
||||
if (status == JSGC_MARK_END && checkPointers) {
|
||||
for (jsuint i = 0; i != checkPointersLength; ++i) {
|
||||
for (unsigned i = 0; i != checkPointersLength; ++i) {
|
||||
void *p = checkPointers[i];
|
||||
JS_ASSERT(p);
|
||||
if (JS_IsAboutToBeFinalized(p))
|
||||
|
@ -52,7 +52,7 @@ BEGIN_TEST(testIsAboutToBeFinalized_bug528645)
|
|||
JS_GC(cx);
|
||||
|
||||
/* Everything is unrooted except unit strings. */
|
||||
for (jsuint i = 0; i != checkPointersLength; ++i) {
|
||||
for (unsigned i = 0; i != checkPointersLength; ++i) {
|
||||
void *p = checkPointers[i];
|
||||
if (p) {
|
||||
CHECK(JSString::isStatic(p));
|
||||
|
@ -97,7 +97,7 @@ cls_testIsAboutToBeFinalized_bug528645::createAndTestRooted()
|
|||
CHECK(checkPointers);
|
||||
|
||||
checkPointersStaticStrings = 0;
|
||||
for (jsuint i = 0; i != checkPointersLength; ++i) {
|
||||
for (unsigned i = 0; i != checkPointersLength; ++i) {
|
||||
jsval v;
|
||||
ok = JS_GetElement(cx, array, i, &v);
|
||||
CHECK(ok);
|
||||
|
@ -115,7 +115,7 @@ cls_testIsAboutToBeFinalized_bug528645::createAndTestRooted()
|
|||
* All GC things are rooted via the root holding the array containing them
|
||||
* and TestAboutToBeFinalizedCallback must keep them as is.
|
||||
*/
|
||||
for (jsuint i = 0; i != checkPointersLength; ++i)
|
||||
for (unsigned i = 0; i != checkPointersLength; ++i)
|
||||
CHECK(checkPointers[i]);
|
||||
|
||||
/*
|
||||
|
@ -127,7 +127,7 @@ cls_testIsAboutToBeFinalized_bug528645::createAndTestRooted()
|
|||
array = JSVAL_TO_OBJECT(root.value());
|
||||
JS_ASSERT(JS_IsArrayObject(cx, array));
|
||||
|
||||
jsuint tmp;
|
||||
uint32_t tmp;
|
||||
CHECK(JS_GetArrayLength(cx, array, &tmp));
|
||||
CHECK(ok);
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ BEGIN_TEST(testNewObject_1)
|
|||
CHECK(obj);
|
||||
jsvalRoot rt(cx, OBJECT_TO_JSVAL(obj));
|
||||
CHECK(JS_IsArrayObject(cx, obj));
|
||||
jsuint len;
|
||||
uint32_t len;
|
||||
CHECK(JS_GetArrayLength(cx, obj, &len));
|
||||
CHECK_EQUAL(len, 0);
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#include "jsatom.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
BEGIN_TEST(testStringBuffer_finishString)
|
||||
{
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
#include "vm/RegExpStatics-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
#include "assembler/jit/ExecutableAllocator.h"
|
||||
|
@ -752,6 +753,7 @@ JSRuntime::JSRuntime()
|
|||
gcZealFrequency(0),
|
||||
gcNextScheduled(0),
|
||||
gcDebugCompartmentGC(false),
|
||||
gcDeterministicOnly(false),
|
||||
#endif
|
||||
gcCallback(NULL),
|
||||
gcSliceCallback(NULL),
|
||||
|
@ -4264,7 +4266,9 @@ prop_iter_trace(JSTracer *trc, JSObject *obj)
|
|||
* barrier here because the pointer is updated via setPrivate, which
|
||||
* always takes a barrier.
|
||||
*/
|
||||
MarkShapeUnbarriered(trc, (Shape *)pdata, "prop iter shape");
|
||||
Shape *tmp = (Shape *)pdata;
|
||||
MarkShapeUnbarriered(trc, &tmp, "prop iter shape");
|
||||
JS_ASSERT(tmp == pdata);
|
||||
} else {
|
||||
/* Non-native case: mark each id in the JSIdArray private. */
|
||||
JSIdArray *ida = (JSIdArray *) pdata;
|
||||
|
@ -4404,9 +4408,9 @@ JS_NewArrayObject(JSContext *cx, int length, jsval *vector)
|
|||
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
/* NB: jsuint cast does ToUint32. */
|
||||
assertSameCompartment(cx, JSValueArray(vector, vector ? (jsuint)length : 0));
|
||||
return NewDenseCopiedArray(cx, (jsuint)length, vector);
|
||||
|
||||
assertSameCompartment(cx, JSValueArray(vector, vector ? (uint32_t)length : 0));
|
||||
return NewDenseCopiedArray(cx, (uint32_t)length, vector);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
@ -4417,7 +4421,7 @@ JS_IsArrayObject(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
||||
JS_GetArrayLength(JSContext *cx, JSObject *obj, uint32_t *lengthp)
|
||||
{
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
@ -4426,7 +4430,7 @@ JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length)
|
||||
JS_SetArrayLength(JSContext *cx, JSObject *obj, uint32_t length)
|
||||
{
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
@ -6463,23 +6467,10 @@ JS_ClearPendingException(JSContext *cx)
|
|||
JS_PUBLIC_API(JSBool)
|
||||
JS_ReportPendingException(JSContext *cx)
|
||||
{
|
||||
JSBool ok;
|
||||
bool save;
|
||||
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
/*
|
||||
* Set cx->generatingError to suppress the standard error-to-exception
|
||||
* conversion done by all {js,JS}_Report* functions except for OOM. The
|
||||
* cx->generatingError flag was added to suppress recursive divergence
|
||||
* under js_ErrorToException, but it serves for our purposes here too.
|
||||
*/
|
||||
save = cx->generatingError;
|
||||
cx->generatingError = JS_TRUE;
|
||||
ok = js_ReportUncaughtException(cx);
|
||||
cx->generatingError = save;
|
||||
return ok;
|
||||
return js_ReportUncaughtException(cx);
|
||||
}
|
||||
|
||||
struct JSExceptionState {
|
||||
|
|
|
@ -1896,8 +1896,8 @@ JSID_TO_INT(jsid id)
|
|||
static JS_ALWAYS_INLINE JSBool
|
||||
INT_FITS_IN_JSID(int32_t i)
|
||||
{
|
||||
return ((jsuint)(i) - (jsuint)JSID_INT_MIN <=
|
||||
(jsuint)(JSID_INT_MAX - JSID_INT_MIN));
|
||||
return ((uint32_t)(i) - (uint32_t)JSID_INT_MIN <=
|
||||
(uint32_t)(JSID_INT_MAX - JSID_INT_MIN));
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsid
|
||||
|
@ -3986,10 +3986,10 @@ extern JS_PUBLIC_API(JSBool)
|
|||
JS_IsArrayObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
||||
JS_GetArrayLength(JSContext *cx, JSObject *obj, uint32_t *lengthp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length);
|
||||
JS_SetArrayLength(JSContext *cx, JSObject *obj, uint32_t length);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, jsval value,
|
||||
|
|
|
@ -128,6 +128,7 @@
|
|||
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/MethodGuard.h"
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
#include "ds/Sort.h"
|
||||
|
||||
|
@ -147,7 +148,7 @@ using namespace js::gc;
|
|||
using namespace js::types;
|
||||
|
||||
JSBool
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, uint32_t *lengthp)
|
||||
{
|
||||
if (obj->isArray()) {
|
||||
*lengthp = obj->getArrayLength();
|
||||
|
@ -167,11 +168,11 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
|||
return false;
|
||||
|
||||
if (tvr.value().isInt32()) {
|
||||
*lengthp = jsuint(tvr.value().toInt32()); /* jsuint cast does ToUint32_t */
|
||||
*lengthp = uint32_t(tvr.value().toInt32()); /* uint32_t cast does ToUint32_t */
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(jsuint) == sizeof(uint32_t));
|
||||
|
||||
return ToUint32(cx, tvr.value(), (uint32_t *)lengthp);
|
||||
}
|
||||
|
||||
|
@ -197,7 +198,7 @@ namespace js {
|
|||
*
|
||||
*/
|
||||
JS_FRIEND_API(bool)
|
||||
StringIsArrayIndex(JSLinearString *str, jsuint *indexp)
|
||||
StringIsArrayIndex(JSLinearString *str, uint32_t *indexp)
|
||||
{
|
||||
const jschar *s = str->chars();
|
||||
uint32_t length = str->length();
|
||||
|
@ -236,10 +237,10 @@ StringIsArrayIndex(JSLinearString *str, jsuint *indexp)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom,
|
||||
BigIndexToId(JSContext *cx, JSObject *obj, uint32_t index, JSBool createAtom,
|
||||
jsid *idp)
|
||||
{
|
||||
JS_STATIC_ASSERT((jsuint)-1 == 4294967295U);
|
||||
|
||||
JS_ASSERT(index > JSID_INT_MAX);
|
||||
|
||||
jschar buf[10];
|
||||
|
@ -318,8 +319,8 @@ IndexToId(JSContext* cx, JSObject* obj, double index, JSBool* hole, jsid* idp,
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (index <= jsuint(-1)) {
|
||||
if (!BigIndexToId(cx, obj, jsuint(index), createAtom, idp))
|
||||
if (index <= uint32_t(-1)) {
|
||||
if (!BigIndexToId(cx, obj, uint32_t(index), createAtom, idp))
|
||||
return JS_FALSE;
|
||||
if (hole && JSID_IS_VOID(*idp))
|
||||
*hole = JS_TRUE;
|
||||
|
@ -437,7 +438,7 @@ GetElementsSlow(JSContext *cx, JSObject *aobj, uint32_t length, Value *vp)
|
|||
}
|
||||
|
||||
bool
|
||||
GetElements(JSContext *cx, JSObject *aobj, jsuint length, Value *vp)
|
||||
GetElements(JSContext *cx, JSObject *aobj, uint32_t length, Value *vp)
|
||||
{
|
||||
if (aobj->isDenseArray() && length <= aobj->getDenseArrayInitializedLength() &&
|
||||
!js_PrototypeHasIndexedProperties(cx, aobj)) {
|
||||
|
@ -475,9 +476,9 @@ SetArrayElement(JSContext *cx, JSObject *obj, double index, const Value &v)
|
|||
/* Predicted/prefetched code should favor the remains-dense case. */
|
||||
JSObject::EnsureDenseResult result = JSObject::ED_SPARSE;
|
||||
do {
|
||||
if (index > jsuint(-1))
|
||||
if (index > uint32_t(-1))
|
||||
break;
|
||||
jsuint idx = jsuint(index);
|
||||
uint32_t idx = uint32_t(index);
|
||||
result = obj->ensureDenseArrayElements(cx, idx, 1);
|
||||
if (result != JSObject::ED_OK)
|
||||
break;
|
||||
|
@ -629,8 +630,8 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value
|
|||
* us to disregard length when reading from arrays as long we are within
|
||||
* the initialized capacity.
|
||||
*/
|
||||
jsuint oldcap = obj->getDenseArrayCapacity();
|
||||
jsuint oldinit = obj->getDenseArrayInitializedLength();
|
||||
uint32_t oldcap = obj->getDenseArrayCapacity();
|
||||
uint32_t oldinit = obj->getDenseArrayInitializedLength();
|
||||
if (oldinit > newlen)
|
||||
obj->setDenseArrayInitializedLength(newlen);
|
||||
if (oldcap > newlen)
|
||||
|
@ -660,13 +661,13 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value
|
|||
if (!iter)
|
||||
return false;
|
||||
|
||||
jsuint gap = oldlen - newlen;
|
||||
uint32_t gap = oldlen - newlen;
|
||||
for (;;) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) || !JS_NextProperty(cx, iter, &id))
|
||||
return false;
|
||||
if (JSID_IS_VOID(id))
|
||||
break;
|
||||
jsuint index;
|
||||
uint32_t index;
|
||||
Value junk;
|
||||
if (js_IdIsIndex(id, &index) && index - newlen < gap &&
|
||||
!obj->deleteElement(cx, index, &junk, false)) {
|
||||
|
@ -863,7 +864,7 @@ array_getGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Valu
|
|||
static JSBool
|
||||
slowarray_addProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
jsuint index, length;
|
||||
uint32_t index, length;
|
||||
|
||||
if (!js_IdIsIndex(id, &index))
|
||||
return JS_TRUE;
|
||||
|
@ -1193,7 +1194,7 @@ array_trace(JSTracer *trc, JSObject *obj)
|
|||
JS_ASSERT(obj->isDenseArray());
|
||||
|
||||
uint32_t initLength = obj->getDenseArrayInitializedLength();
|
||||
MarkSlotRange(trc, initLength, obj->getDenseArrayElements(), "element");
|
||||
MarkArraySlots(trc, initLength, obj->getDenseArrayElements(), "element");
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -1488,11 +1489,11 @@ array_toSource(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (!sb.append('['))
|
||||
return false;
|
||||
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
return false;
|
||||
|
||||
for (jsuint index = 0; index < length; index++) {
|
||||
for (uint32_t index = 0; index < length; index++) {
|
||||
JSBool hole;
|
||||
Value elt;
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
|
||||
|
@ -1608,7 +1609,7 @@ array_toString_sub(JSContext *cx, JSObject *obj, JSBool locale,
|
|||
return true;
|
||||
}
|
||||
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
return false;
|
||||
|
||||
|
@ -1649,7 +1650,7 @@ array_toString_sub(JSContext *cx, JSObject *obj, JSBool locale,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (jsuint index = 0; index < length; index++) {
|
||||
for (uint32_t index = 0; index < length; index++) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx))
|
||||
return false;
|
||||
|
||||
|
@ -1793,7 +1794,7 @@ InitArrayElements(JSContext *cx, JSObject *obj, uint32_t start, uint32_t count,
|
|||
JS_ASSERT(result == JSObject::ED_SPARSE);
|
||||
break;
|
||||
}
|
||||
jsuint newlen = start + count;
|
||||
uint32_t newlen = start + count;
|
||||
if (newlen > obj->getArrayLength())
|
||||
obj->setDenseArrayLength(newlen);
|
||||
|
||||
|
@ -1836,7 +1837,7 @@ InitArrayElements(JSContext *cx, JSObject *obj, uint32_t start, uint32_t count,
|
|||
|
||||
#if 0
|
||||
static JSBool
|
||||
InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, const Value *vector)
|
||||
InitArrayObject(JSContext *cx, JSObject *obj, uint32_t length, const Value *vector)
|
||||
{
|
||||
JS_ASSERT(obj->isArray());
|
||||
|
||||
|
@ -1855,7 +1856,7 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, const Value *vector
|
|||
obj->setDenseArrayInitializedLength(length);
|
||||
|
||||
bool hole = false;
|
||||
for (jsuint i = 0; i < length; i++) {
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
obj->setDenseArrayElement(i, vector[i]);
|
||||
hole |= vector[i].isMagic(JS_ARRAY_HOLE);
|
||||
}
|
||||
|
@ -1898,7 +1899,7 @@ array_reverse(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (!obj)
|
||||
return false;
|
||||
|
||||
jsuint len;
|
||||
uint32_t len;
|
||||
if (!js_GetLengthProperty(cx, obj, &len))
|
||||
return false;
|
||||
|
||||
|
@ -1960,7 +1961,7 @@ array_reverse(JSContext *cx, unsigned argc, Value *vp)
|
|||
} while (false);
|
||||
|
||||
Value lowval, hival;
|
||||
for (jsuint i = 0, half = len / 2; i < half; i++) {
|
||||
for (uint32_t i = 0, half = len / 2; i < half; i++) {
|
||||
JSBool hole, hole2;
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
|
||||
!GetElement(cx, obj, i, &hole, &lowval) ||
|
||||
|
@ -2202,7 +2203,7 @@ js::array_sort(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (!obj)
|
||||
return false;
|
||||
|
||||
jsuint len;
|
||||
uint32_t len;
|
||||
if (!js_GetLengthProperty(cx, obj, &len))
|
||||
return false;
|
||||
if (len == 0) {
|
||||
|
@ -2249,7 +2250,7 @@ js::array_sort(JSContext *cx, unsigned argc, Value *vp)
|
|||
undefs = 0;
|
||||
bool allStrings = true;
|
||||
bool allInts = true;
|
||||
for (jsuint i = 0; i < len; i++) {
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx))
|
||||
return false;
|
||||
|
||||
|
@ -2340,7 +2341,7 @@ js::array_sort(JSContext *cx, unsigned argc, Value *vp)
|
|||
}
|
||||
}
|
||||
|
||||
if (!InitArrayElements(cx, obj, 0, jsuint(n), result, DontUpdateTypes))
|
||||
if (!InitArrayElements(cx, obj, 0, uint32_t(n), result, DontUpdateTypes))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2366,7 +2367,7 @@ js::array_sort(JSContext *cx, unsigned argc, Value *vp)
|
|||
static bool
|
||||
array_push_slowly(JSContext *cx, JSObject *obj, CallArgs &args)
|
||||
{
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
return false;
|
||||
|
@ -2450,7 +2451,7 @@ js::array_push(JSContext *cx, unsigned argc, Value *vp)
|
|||
static JSBool
|
||||
array_pop_slowly(JSContext *cx, JSObject* obj, CallArgs &args)
|
||||
{
|
||||
jsuint index;
|
||||
uint32_t index;
|
||||
if (!js_GetLengthProperty(cx, obj, &index))
|
||||
return false;
|
||||
|
||||
|
@ -2476,7 +2477,7 @@ array_pop_slowly(JSContext *cx, JSObject* obj, CallArgs &args)
|
|||
static JSBool
|
||||
array_pop_dense(JSContext *cx, JSObject* obj, CallArgs &args)
|
||||
{
|
||||
jsuint index = obj->getArrayLength();
|
||||
uint32_t index = obj->getArrayLength();
|
||||
if (index == 0) {
|
||||
args.rval().setUndefined();
|
||||
return JS_TRUE;
|
||||
|
@ -2537,7 +2538,7 @@ js::array_shift(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (!obj)
|
||||
return JS_FALSE;
|
||||
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -2566,7 +2567,7 @@ js::array_shift(JSContext *cx, unsigned argc, Value *vp)
|
|||
|
||||
/* Slide down the array above the first element. */
|
||||
AutoValueRooter tvr(cx);
|
||||
for (jsuint i = 0; i < length; i++) {
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
|
||||
!GetElement(cx, obj, i + 1, &hole, tvr.addr()) ||
|
||||
!SetOrDeleteArrayElement(cx, obj, i, hole, tvr.value())) {
|
||||
|
@ -2589,7 +2590,7 @@ array_unshift(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (!obj)
|
||||
return false;
|
||||
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -2935,11 +2936,11 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp)
|
|||
return false;
|
||||
|
||||
JSObject *nobj;
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (aobj->isDenseArray()) {
|
||||
length = aobj->getArrayLength();
|
||||
const Value *vector = aobj->getDenseArrayElements();
|
||||
jsuint initlen = aobj->getDenseArrayInitializedLength();
|
||||
uint32_t initlen = aobj->getDenseArrayInitializedLength();
|
||||
nobj = NewDenseCopiedArray(cx, initlen, vector);
|
||||
if (!nobj)
|
||||
return JS_FALSE;
|
||||
|
@ -2966,7 +2967,7 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (v.isObject()) {
|
||||
JSObject &obj = v.toObject();
|
||||
if (ObjectClassIs(obj, ESClass_Array, cx)) {
|
||||
jsuint alength;
|
||||
uint32_t alength;
|
||||
if (!js_GetLengthProperty(cx, &obj, &alength))
|
||||
return false;
|
||||
for (uint32_t slot = 0; slot < alength; slot++) {
|
||||
|
@ -2999,7 +3000,7 @@ static JSBool
|
|||
array_slice(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
JSObject *nobj;
|
||||
jsuint length, begin, end, slot;
|
||||
uint32_t length, begin, end, slot;
|
||||
JSBool hole;
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
@ -3024,7 +3025,7 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
|
|||
} else if (d > length) {
|
||||
d = length;
|
||||
}
|
||||
begin = (jsuint)d;
|
||||
begin = (uint32_t)d;
|
||||
|
||||
if (args.hasDefined(1)) {
|
||||
if (!ToInteger(cx, args[1], &d))
|
||||
|
@ -3036,7 +3037,7 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
|
|||
} else if (d > length) {
|
||||
d = length;
|
||||
}
|
||||
end = (jsuint)d;
|
||||
end = (uint32_t)d;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3080,7 +3081,7 @@ enum IndexOfKind {
|
|||
static JSBool
|
||||
array_indexOfHelper(JSContext *cx, IndexOfKind mode, CallArgs &args)
|
||||
{
|
||||
jsuint length, i, stop;
|
||||
uint32_t length, i, stop;
|
||||
Value tosearch;
|
||||
int direction;
|
||||
JSBool hole;
|
||||
|
@ -3109,14 +3110,14 @@ array_indexOfHelper(JSContext *cx, IndexOfKind mode, CallArgs &args)
|
|||
goto not_found;
|
||||
i = 0;
|
||||
} else {
|
||||
i = (jsuint)start;
|
||||
i = (uint32_t)start;
|
||||
}
|
||||
} else if (start >= length) {
|
||||
if (mode == IndexOf)
|
||||
goto not_found;
|
||||
i = length - 1;
|
||||
} else {
|
||||
i = (jsuint)start;
|
||||
i = (uint32_t)start;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3131,7 +3132,7 @@ array_indexOfHelper(JSContext *cx, IndexOfKind mode, CallArgs &args)
|
|||
for (;;) {
|
||||
Value elt;
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
|
||||
!GetElement(cx, obj, (jsuint)i, &hole, &elt)) {
|
||||
!GetElement(cx, obj, (uint32_t)i, &hole, &elt)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!hole) {
|
||||
|
@ -3735,7 +3736,7 @@ js_InitArrayClass(JSContext *cx, JSObject *obj)
|
|||
namespace js {
|
||||
|
||||
static inline bool
|
||||
EnsureNewArrayElements(JSContext *cx, JSObject *obj, jsuint length)
|
||||
EnsureNewArrayElements(JSContext *cx, JSObject *obj, uint32_t length)
|
||||
{
|
||||
/*
|
||||
* If ensureElements creates dynamically allocated slots, then having
|
||||
|
|
|
@ -57,13 +57,13 @@ const uint32_t MAX_ARRAY_INDEX = 4294967294u;
|
|||
}
|
||||
|
||||
inline JSBool
|
||||
js_IdIsIndex(jsid id, jsuint *indexp)
|
||||
js_IdIsIndex(jsid id, uint32_t *indexp)
|
||||
{
|
||||
if (JSID_IS_INT(id)) {
|
||||
int32_t i = JSID_TO_INT(id);
|
||||
if (i < 0)
|
||||
return JS_FALSE;
|
||||
*indexp = (jsuint)i;
|
||||
*indexp = (uint32_t)i;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,7 @@ NewSlowEmptyArray(JSContext *cx);
|
|||
} /* namespace js */
|
||||
|
||||
extern JSBool
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, uint32_t *lengthp);
|
||||
|
||||
extern JSBool
|
||||
js_SetLengthProperty(JSContext *cx, JSObject *obj, double length);
|
||||
|
@ -158,7 +158,7 @@ array_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, J
|
|||
* js_GetLengthProperty on aobj.
|
||||
*/
|
||||
extern bool
|
||||
GetElements(JSContext *cx, JSObject *aobj, jsuint length, js::Value *vp);
|
||||
GetElements(JSContext *cx, JSObject *aobj, uint32_t length, js::Value *vp);
|
||||
|
||||
/* Natives exposed for optimization by the interpreter and JITs. */
|
||||
|
||||
|
|
|
@ -712,9 +712,9 @@ js_CheckForStringIndex(jsid id)
|
|||
const jschar *cp = s;
|
||||
const jschar *end = s + n;
|
||||
|
||||
jsuint index = JS7_UNDEC(*cp++);
|
||||
jsuint oldIndex = 0;
|
||||
jsuint c = 0;
|
||||
uint32_t index = JS7_UNDEC(*cp++);
|
||||
uint32_t oldIndex = 0;
|
||||
uint32_t c = 0;
|
||||
|
||||
if (index != 0) {
|
||||
while (JS7_ISDEC(*cp)) {
|
||||
|
|
|
@ -57,10 +57,10 @@
|
|||
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/BooleanObject-inl.h"
|
||||
#include "vm/MethodGuard-inl.h"
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
|
|
@ -504,6 +504,37 @@ js_ReportErrorVA(JSContext *cx, unsigned flags, const char *format, va_list ap)
|
|||
return warning;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
/* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
|
||||
void
|
||||
ReportUsageError(JSContext *cx, JSObject *callee, const char *msg)
|
||||
{
|
||||
const char *usageStr = "usage";
|
||||
JSAtom *usageAtom = js_Atomize(cx, usageStr, strlen(usageStr));
|
||||
DebugOnly<const Shape *> shape = callee->nativeLookup(cx, ATOM_TO_JSID(usageAtom));
|
||||
JS_ASSERT(!shape->configurable());
|
||||
JS_ASSERT(!shape->writable());
|
||||
JS_ASSERT(shape->hasDefaultGetter());
|
||||
|
||||
jsval usage;
|
||||
if (!JS_LookupProperty(cx, callee, "usage", &usage))
|
||||
return;
|
||||
|
||||
if (JSVAL_IS_VOID(usage)) {
|
||||
JS_ReportError(cx, "%s", msg);
|
||||
} else {
|
||||
JSString *str = JSVAL_TO_STRING(usage);
|
||||
JS::Anchor<JSString *> a_str(str);
|
||||
const jschar *chars = JS_GetStringCharsZ(cx, str);
|
||||
if (!chars)
|
||||
return;
|
||||
JS_ReportError(cx, "%s. Usage: %hs", msg, chars);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* The arguments from ap need to be packaged up into an array and stored
|
||||
* into the report struct.
|
||||
|
|
|
@ -419,6 +419,7 @@ struct JSRuntime : js::RuntimeFriendFields
|
|||
int gcZealFrequency;
|
||||
int gcNextScheduled;
|
||||
bool gcDebugCompartmentGC;
|
||||
bool gcDeterministicOnly;
|
||||
|
||||
int gcZeal() { return gcZeal_; }
|
||||
|
||||
|
@ -829,11 +830,11 @@ struct JSContext : js::ContextFriendFields
|
|||
bool hasVersionOverride;
|
||||
|
||||
/* Exception state -- the exception member is a GC root by definition. */
|
||||
JSBool throwing; /* is there a pending exception? */
|
||||
js::Value exception; /* most-recently-thrown exception */
|
||||
JSBool throwing; /* is there a pending exception? */
|
||||
js::Value exception; /* most-recently-thrown exception */
|
||||
|
||||
/* Per-context run options. */
|
||||
unsigned runOptions; /* see jsapi.h for JSOPTION_* */
|
||||
unsigned runOptions; /* see jsapi.h for JSOPTION_* */
|
||||
|
||||
public:
|
||||
int32_t reportGranularity; /* see jsprobes.h */
|
||||
|
@ -843,11 +844,8 @@ struct JSContext : js::ContextFriendFields
|
|||
|
||||
js::AutoResolving *resolvingList;
|
||||
|
||||
/*
|
||||
* True if generating an error, to prevent runaway recursion.
|
||||
* NB: generatingError packs with throwing below.
|
||||
*/
|
||||
bool generatingError;
|
||||
/* True if generating an error, to prevent runaway recursion. */
|
||||
bool generatingError;
|
||||
|
||||
/* GC heap compartment. */
|
||||
JSCompartment *compartment;
|
||||
|
@ -1418,6 +1416,14 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
|
|||
bool charArgs, va_list ap);
|
||||
#endif
|
||||
|
||||
namespace js {
|
||||
|
||||
/* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
|
||||
extern void
|
||||
ReportUsageError(JSContext *cx, JSObject *callee, const char *msg);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
extern void
|
||||
js_ReportOutOfMemory(JSContext *cx);
|
||||
|
||||
|
|
|
@ -77,10 +77,10 @@
|
|||
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/MethodGuard-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace js;
|
||||
|
|
|
@ -68,10 +68,10 @@
|
|||
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/Stack-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace js;
|
||||
|
@ -1084,7 +1084,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
|
|||
*/
|
||||
JS_ASSERT(reportp);
|
||||
if (JSREPORT_IS_WARNING(reportp->flags))
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
|
||||
/* Find the exception index associated with this error. */
|
||||
errorNumber = (JSErrNum) reportp->errorNumber;
|
||||
|
@ -1107,19 +1107,12 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
|
|||
* with the given error number.
|
||||
*/
|
||||
if (exn == JSEXN_NONE)
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Prevent runaway recursion, via cx->generatingError. If an out-of-memory
|
||||
* error occurs, no exception object will be created, but we don't assume
|
||||
* that OOM is the only kind of error that subroutines of this function
|
||||
* called below might raise.
|
||||
*/
|
||||
/* Prevent infinite recursion. */
|
||||
if (cx->generatingError)
|
||||
return JS_FALSE;
|
||||
|
||||
MUST_FLOW_THROUGH("out");
|
||||
cx->generatingError = JS_TRUE;
|
||||
return false;
|
||||
AutoScopedAssign<bool> asa(&cx->generatingError, false);
|
||||
|
||||
/* Protect the newly-created strings below from nesting GCs. */
|
||||
PodArrayZero(tv);
|
||||
|
@ -1132,43 +1125,34 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
|
|||
*/
|
||||
ok = js_GetClassPrototype(cx, NULL, GetExceptionProtoKey(exn), &errProto);
|
||||
if (!ok)
|
||||
goto out;
|
||||
return false;
|
||||
tv[0] = OBJECT_TO_JSVAL(errProto);
|
||||
|
||||
errObject = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL);
|
||||
if (!errObject) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
if (!errObject)
|
||||
return false;
|
||||
tv[1] = OBJECT_TO_JSVAL(errObject);
|
||||
|
||||
messageStr = JS_NewStringCopyZ(cx, message);
|
||||
if (!messageStr) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
if (!messageStr)
|
||||
return false;
|
||||
tv[2] = STRING_TO_JSVAL(messageStr);
|
||||
|
||||
filenameStr = JS_NewStringCopyZ(cx, reportp->filename);
|
||||
if (!filenameStr) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
if (!filenameStr)
|
||||
return false;
|
||||
tv[3] = STRING_TO_JSVAL(filenameStr);
|
||||
|
||||
ok = InitExnPrivate(cx, errObject, messageStr, filenameStr,
|
||||
reportp->lineno, reportp, exn);
|
||||
if (!ok)
|
||||
goto out;
|
||||
return false;
|
||||
|
||||
JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject));
|
||||
|
||||
/* Flag the error report passed in to indicate an exception was raised. */
|
||||
reportp->flags |= JSREPORT_EXCEPTION;
|
||||
|
||||
out:
|
||||
cx->generatingError = JS_FALSE;
|
||||
return ok;
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
#include "jsweakmap.h"
|
||||
#include "jswatchpoint.h"
|
||||
|
||||
#include "builtin/TestingFunctions.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
|
@ -180,6 +182,51 @@ JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape)
|
|||
MarkCycleCollectorChildren(trc, (Shape *)shape);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefineHelpProperty(JSContext *cx, JSObject *obj, const char *prop, const char *value)
|
||||
{
|
||||
JSAtom *atom = js_Atomize(cx, value, strlen(value));
|
||||
if (!atom)
|
||||
return false;
|
||||
jsval v = STRING_TO_JSVAL(atom);
|
||||
return JS_DefineProperty(cx, obj, prop, v,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWithHelp *fs)
|
||||
{
|
||||
RootObject objRoot(cx, &obj);
|
||||
|
||||
JS_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
for (; fs->name; fs++) {
|
||||
JSAtom *atom = js_Atomize(cx, fs->name, strlen(fs->name));
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
JSFunction *fun = js_DefineFunction(cx, objRoot,
|
||||
ATOM_TO_JSID(atom), fs->call, fs->nargs, fs->flags);
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
if (fs->usage) {
|
||||
if (!DefineHelpProperty(cx, fun, "usage", fs->usage))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fs->help) {
|
||||
if (!DefineHelpProperty(cx, fun, "help", fs->help))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AutoPreserveCompartment::AutoPreserveCompartment(JSContext *cx
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT)
|
||||
: cx(cx), oldCompartment(cx->compartment)
|
||||
|
@ -789,4 +836,17 @@ IncrementalValueBarrier(const Value &v)
|
|||
HeapValue::writeBarrierPre(v);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
GetTestingFunctions(JSContext *cx)
|
||||
{
|
||||
JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (!DefineTestingFunctions(cx, obj))
|
||||
return NULL;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
|
|
@ -166,6 +166,21 @@ JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc);
|
|||
extern JS_FRIEND_API(JSBool)
|
||||
JS_EnumerateState(JSContext *cx, JSObject *obj, JSIterateOp enum_op, js::Value *statep, jsid *idp);
|
||||
|
||||
struct JSFunctionSpecWithHelp {
|
||||
const char *name;
|
||||
JSNative call;
|
||||
uint16_t nargs;
|
||||
uint16_t flags;
|
||||
const char *usage;
|
||||
const char *help;
|
||||
};
|
||||
|
||||
#define JS_FN_HELP(name,call,nargs,flags,usage,help) \
|
||||
{name, call, nargs, (flags) | JSPROP_ENUMERATE | JSFUN_STUB_GSOPS, usage, help}
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWithHelp *fs);
|
||||
|
||||
#endif
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
@ -498,7 +513,7 @@ JS_FRIEND_API(bool)
|
|||
GetPropertyNames(JSContext *cx, JSObject *obj, unsigned flags, js::AutoIdVector *props);
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
StringIsArrayIndex(JSLinearString *str, jsuint *indexp);
|
||||
StringIsArrayIndex(JSLinearString *str, uint32_t *indexp);
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
SetPreserveWrapperCallback(JSRuntime *rt, PreserveWrapperCallback callback);
|
||||
|
@ -658,7 +673,7 @@ SizeOfJSContext();
|
|||
D(LAST_DITCH) \
|
||||
D(TOO_MUCH_MALLOC) \
|
||||
D(ALLOC_TRIGGER) \
|
||||
D(UNUSED1) /* was CHUNK */ \
|
||||
D(DEBUG_GC) \
|
||||
D(UNUSED2) /* was SHAPE */ \
|
||||
D(UNUSED3) /* was REFILL */ \
|
||||
\
|
||||
|
@ -808,6 +823,9 @@ class ObjectPtr
|
|||
operator JSObject *() const { return value; }
|
||||
};
|
||||
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
GetTestingFunctions(JSContext *cx);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1094,13 +1094,13 @@ JSFunction::trace(JSTracer *trc)
|
|||
}
|
||||
|
||||
if (atom)
|
||||
MarkStringUnbarriered(trc, atom, "atom");
|
||||
MarkStringUnbarriered(trc, &atom, "atom");
|
||||
|
||||
if (isInterpreted()) {
|
||||
if (script())
|
||||
MarkScript(trc, &script(), "script");
|
||||
if (environment())
|
||||
MarkObjectUnbarriered(trc, environment(), "fun_callscope");
|
||||
if (u.i.script_)
|
||||
MarkScriptUnbarriered(trc, &u.i.script_, "script");
|
||||
if (u.i.env_)
|
||||
MarkObjectUnbarriered(trc, &u.i.env_, "fun_callscope");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1296,7 +1296,7 @@ js_fun_apply(JSContext *cx, unsigned argc, Value *vp)
|
|||
* original version of ES5).
|
||||
*/
|
||||
JSObject *aobj = &vp[3].toObject();
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!js_GetLengthProperty(cx, aobj, &length))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -664,7 +664,7 @@ Chunk::init()
|
|||
info.age = 0;
|
||||
|
||||
/* Initialize the arena header state. */
|
||||
for (jsuint i = 0; i < ArenasPerChunk; i++) {
|
||||
for (unsigned i = 0; i < ArenasPerChunk; i++) {
|
||||
arenas[i].aheader.setAsNotAllocated();
|
||||
arenas[i].aheader.next = (i + 1 < ArenasPerChunk)
|
||||
? &arenas[i + 1].aheader
|
||||
|
@ -724,14 +724,14 @@ Chunk::removeFromAvailableList()
|
|||
* it to the most recently freed arena when we free, and forcing it to
|
||||
* the last alloc + 1 when we allocate.
|
||||
*/
|
||||
jsuint
|
||||
uint32_t
|
||||
Chunk::findDecommittedArenaOffset()
|
||||
{
|
||||
/* Note: lastFreeArenaOffset can be past the end of the list. */
|
||||
for (jsuint i = info.lastDecommittedArenaOffset; i < ArenasPerChunk; i++)
|
||||
for (unsigned i = info.lastDecommittedArenaOffset; i < ArenasPerChunk; i++)
|
||||
if (decommittedArenas.get(i))
|
||||
return i;
|
||||
for (jsuint i = 0; i < info.lastDecommittedArenaOffset; i++)
|
||||
for (unsigned i = 0; i < info.lastDecommittedArenaOffset; i++)
|
||||
if (decommittedArenas.get(i))
|
||||
return i;
|
||||
JS_NOT_REACHED("No decommitted arenas found.");
|
||||
|
@ -744,7 +744,7 @@ Chunk::fetchNextDecommittedArena()
|
|||
JS_ASSERT(info.numArenasFreeCommitted == 0);
|
||||
JS_ASSERT(info.numArenasFree > 0);
|
||||
|
||||
jsuint offset = findDecommittedArenaOffset();
|
||||
unsigned offset = findDecommittedArenaOffset();
|
||||
info.lastDecommittedArenaOffset = offset + 1;
|
||||
--info.numArenasFree;
|
||||
decommittedArenas.unset(offset);
|
||||
|
@ -1708,13 +1708,13 @@ ArenaLists::finalizeScripts(JSContext *cx)
|
|||
}
|
||||
|
||||
static void
|
||||
RunLastDitchGC(JSContext *cx)
|
||||
RunLastDitchGC(JSContext *cx, gcreason::Reason reason)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
|
||||
/* The last ditch GC preserves all atoms. */
|
||||
AutoKeepAtoms keep(rt);
|
||||
GC(cx, rt->gcTriggerCompartment, GC_NORMAL, gcreason::LAST_DITCH);
|
||||
GC(cx, rt->gcTriggerCompartment, GC_NORMAL, reason);
|
||||
}
|
||||
|
||||
/* static */ void *
|
||||
|
@ -1729,7 +1729,7 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
|||
bool runGC = rt->gcIncrementalState != NO_INCREMENTAL && comp->gcBytes > comp->gcTriggerBytes;
|
||||
for (;;) {
|
||||
if (JS_UNLIKELY(runGC)) {
|
||||
RunLastDitchGC(cx);
|
||||
RunLastDitchGC(cx, gcreason::LAST_DITCH);
|
||||
|
||||
/*
|
||||
* The JSGC_END callback can legitimately allocate new GC
|
||||
|
@ -3662,6 +3662,20 @@ GCCycle(JSContext *cx, JSCompartment *comp, int64_t budget, JSGCInvocationKind g
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
static bool
|
||||
IsDeterministicGCReason(gcreason::Reason reason)
|
||||
{
|
||||
if (reason > gcreason::DEBUG_GC && reason != gcreason::CC_FORCED)
|
||||
return false;
|
||||
|
||||
if (reason == gcreason::MAYBEGC)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
Collect(JSContext *cx, JSCompartment *comp, int64_t budget,
|
||||
JSGCInvocationKind gckind, gcreason::Reason reason)
|
||||
|
@ -3669,6 +3683,11 @@ Collect(JSContext *cx, JSCompartment *comp, int64_t budget,
|
|||
JSRuntime *rt = cx->runtime;
|
||||
JS_AbortIfWrongThread(rt);
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (rt->gcDeterministicOnly && !IsDeterministicGCReason(reason))
|
||||
return;
|
||||
#endif
|
||||
|
||||
JS_ASSERT_IF(budget != SliceBudget::Unlimited, JSGC_INCREMENTAL);
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
|
@ -3947,7 +3966,16 @@ RunDebugGC(JSContext *cx)
|
|||
if (rt->gcTriggerCompartment == rt->atomsCompartment)
|
||||
rt->gcTriggerCompartment = NULL;
|
||||
|
||||
RunLastDitchGC(cx);
|
||||
RunLastDitchGC(cx, gcreason::DEBUG_GC);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SetDeterministicGC(JSContext *cx, bool enabled)
|
||||
{
|
||||
#ifdef JS_GC_ZEAL
|
||||
JSRuntime *rt = cx->runtime;
|
||||
rt->gcDeterministicOnly = enabled;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -808,7 +808,7 @@ struct Chunk {
|
|||
inline void init();
|
||||
|
||||
/* Search for a decommitted arena to allocate. */
|
||||
jsuint findDecommittedArenaOffset();
|
||||
unsigned findDecommittedArenaOffset();
|
||||
ArenaHeader* fetchNextDecommittedArena();
|
||||
|
||||
public:
|
||||
|
@ -1968,6 +1968,9 @@ NewCompartment(JSContext *cx, JSPrincipals *principals);
|
|||
void
|
||||
RunDebugGC(JSContext *cx);
|
||||
|
||||
void
|
||||
SetDeterministicGC(JSContext *cx, bool enabled);
|
||||
|
||||
#if defined(JSGC_ROOT_ANALYSIS) && defined(DEBUG) && !defined(JS_THREADSAFE)
|
||||
/* Overwrites stack references to GC things which have not been rooted. */
|
||||
void CheckStackRoots(JSContext *cx);
|
||||
|
|
|
@ -126,10 +126,10 @@ MarkInternal(JSTracer *trc, T *thing)
|
|||
|
||||
template <typename T>
|
||||
static void
|
||||
MarkUnbarriered(JSTracer *trc, T *thing, const char *name)
|
||||
MarkUnbarriered(JSTracer *trc, T **thingp, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkInternal(trc, thing);
|
||||
MarkInternal(trc, *thingp);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -186,9 +186,9 @@ Mark##base##Root(JSTracer *trc, type **thingp, const char *name)
|
|||
} \
|
||||
\
|
||||
void \
|
||||
Mark##base##Unbarriered(JSTracer *trc, type *thing, const char *name) \
|
||||
Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name) \
|
||||
{ \
|
||||
MarkUnbarriered<type>(trc, thing, name); \
|
||||
MarkUnbarriered<type>(trc, thingp, name); \
|
||||
} \
|
||||
\
|
||||
void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *vec, const char *name) \
|
||||
|
@ -202,6 +202,7 @@ void Mark##base##RootRange(JSTracer *trc, size_t len, type **vec, const char *na
|
|||
} \
|
||||
|
||||
DeclMarkerImpl(BaseShape, BaseShape)
|
||||
DeclMarkerImpl(BaseShape, UnownedBaseShape)
|
||||
DeclMarkerImpl(Object, ArgumentsObject)
|
||||
DeclMarkerImpl(Object, GlobalObject)
|
||||
DeclMarkerImpl(Object, JSObject)
|
||||
|
@ -366,7 +367,7 @@ MarkSlot(JSTracer *trc, HeapSlot *s, const char *name)
|
|||
}
|
||||
|
||||
void
|
||||
MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
|
||||
MarkArraySlots(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
JS_SET_TRACING_INDEX(trc, name, i);
|
||||
|
@ -374,6 +375,16 @@ MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkObjectSlots(JSTracer *trc, JSObject *obj, uint32_t start, uint32_t nslots)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
for (uint32_t i = start; i < (start + nslots); ++i) {
|
||||
JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
|
||||
MarkValueInternal(trc, obj->nativeGetSlotRef(i).unsafeGet());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name)
|
||||
{
|
||||
|
@ -393,15 +404,11 @@ MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name)
|
|||
|
||||
/*** Special Marking ***/
|
||||
|
||||
/*
|
||||
* The unioned HeapPtr stored in script->globalObj needs special treatment to
|
||||
* typecheck correctly.
|
||||
*/
|
||||
static void
|
||||
MarkObject(JSTracer *trc, const HeapPtr<GlobalObject, JSScript *> &thing, const char *name)
|
||||
void
|
||||
MarkObject(JSTracer *trc, HeapPtr<GlobalObject, JSScript *> *thingp, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkInternal(trc, thing.get());
|
||||
MarkInternal(trc, thingp->get());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -644,113 +651,34 @@ PushMarkStack(GCMarker *gcmarker, JSString *str)
|
|||
void
|
||||
MarkChildren(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
MarkTypeObject(trc, &obj->typeFromGC(), "type");
|
||||
|
||||
Shape *shape = obj->lastProperty();
|
||||
MarkShapeUnbarriered(trc, shape, "shape");
|
||||
|
||||
Class *clasp = shape->getObjectClass();
|
||||
if (clasp->trace)
|
||||
clasp->trace(trc, obj);
|
||||
|
||||
if (shape->isNative()) {
|
||||
uint32_t nslots = obj->slotSpan();
|
||||
for (uint32_t i = 0; i < nslots; i++) {
|
||||
JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
|
||||
MarkValueInternal(trc, obj->nativeGetSlotRef(i).unsafeGet());
|
||||
}
|
||||
}
|
||||
obj->markChildren(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
MarkChildren(JSTracer *trc, JSString *str)
|
||||
{
|
||||
/*
|
||||
* We use custom barriers in JSString, so it's safe to use unbarriered
|
||||
* marking here.
|
||||
*/
|
||||
if (str->isDependent()) {
|
||||
MarkStringUnbarriered(trc, str->asDependent().base(), "base");
|
||||
} else if (str->isRope()) {
|
||||
JSRope &rope = str->asRope();
|
||||
MarkStringUnbarriered(trc, rope.leftChild(), "left child");
|
||||
MarkStringUnbarriered(trc, rope.rightChild(), "right child");
|
||||
}
|
||||
if (str->isDependent())
|
||||
str->asDependent().markChildren(trc);
|
||||
else if (str->isRope())
|
||||
str->asRope().markChildren(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
MarkChildren(JSTracer *trc, JSScript *script)
|
||||
{
|
||||
CheckScript(script, NULL);
|
||||
|
||||
JS_ASSERT_IF(trc->runtime->gcCheckCompartment,
|
||||
script->compartment() == trc->runtime->gcCheckCompartment);
|
||||
|
||||
for (uint32_t i = 0; i < script->natoms; ++i) {
|
||||
if (JSAtom *p = script->atoms[i])
|
||||
MarkStringUnbarriered(trc, p, "atom");
|
||||
}
|
||||
|
||||
if (JSScript::isValidOffset(script->objectsOffset)) {
|
||||
JSObjectArray *objarray = script->objects();
|
||||
MarkObjectRange(trc, objarray->length, objarray->vector, "objects");
|
||||
}
|
||||
|
||||
if (JSScript::isValidOffset(script->regexpsOffset)) {
|
||||
JSObjectArray *objarray = script->regexps();
|
||||
MarkObjectRange(trc, objarray->length, objarray->vector, "objects");
|
||||
}
|
||||
|
||||
if (JSScript::isValidOffset(script->constOffset)) {
|
||||
JSConstArray *constarray = script->consts();
|
||||
MarkValueRange(trc, constarray->length, constarray->vector, "consts");
|
||||
}
|
||||
|
||||
if (script->function())
|
||||
MarkObjectUnbarriered(trc, script->function(), "function");
|
||||
|
||||
if (!script->isCachedEval && script->globalObject)
|
||||
MarkObject(trc, script->globalObject, "object");
|
||||
|
||||
if (IS_GC_MARKING_TRACER(trc) && script->filename)
|
||||
js_MarkScriptFilename(script->filename);
|
||||
|
||||
script->bindings.trace(trc);
|
||||
|
||||
if (script->types)
|
||||
script->types->trace(trc);
|
||||
|
||||
if (script->hasAnyBreakpointsOrStepMode())
|
||||
script->markTrapClosures(trc);
|
||||
script->markChildren(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
MarkChildren(JSTracer *trc, Shape *shape)
|
||||
{
|
||||
MarkBaseShapeUnbarriered(trc, shape->base(), "base");
|
||||
MarkId(trc, &shape->propidRef(), "propid");
|
||||
if (shape->previous())
|
||||
MarkShape(trc, &shape->previousRef(), "parent");
|
||||
}
|
||||
|
||||
static inline void
|
||||
MarkBaseShapeGetterSetter(JSTracer *trc, BaseShape *base)
|
||||
{
|
||||
if (base->hasGetterObject())
|
||||
MarkObjectUnbarriered(trc, base->getterObject(), "getter");
|
||||
if (base->hasSetterObject())
|
||||
MarkObjectUnbarriered(trc, base->setterObject(), "setter");
|
||||
shape->markChildren(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
MarkChildren(JSTracer *trc, BaseShape *base)
|
||||
{
|
||||
MarkBaseShapeGetterSetter(trc, base);
|
||||
if (base->isOwned())
|
||||
MarkBaseShapeUnbarriered(trc, base->baseUnowned(), "base");
|
||||
|
||||
if (JSObject *parent = base->getObjectParent())
|
||||
MarkObjectUnbarriered(trc, parent, "parent");
|
||||
base->markChildren(trc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -773,11 +701,22 @@ MarkCycleCollectorChildren(JSTracer *trc, BaseShape *base, JSObject **prevParent
|
|||
*/
|
||||
base->assertConsistency();
|
||||
|
||||
MarkBaseShapeGetterSetter(trc, base);
|
||||
if (base->hasGetterObject()) {
|
||||
JSObject *tmp = base->getterObject();
|
||||
MarkObjectUnbarriered(trc, &tmp, "getter");
|
||||
JS_ASSERT(tmp == base->getterObject());
|
||||
}
|
||||
|
||||
if (base->hasSetterObject()) {
|
||||
JSObject *tmp = base->setterObject();
|
||||
MarkObjectUnbarriered(trc, &tmp, "setter");
|
||||
JS_ASSERT(tmp == base->setterObject());
|
||||
}
|
||||
|
||||
JSObject *parent = base->getObjectParent();
|
||||
if (parent && parent != *prevParent) {
|
||||
MarkObjectUnbarriered(trc, parent, "parent");
|
||||
MarkObjectUnbarriered(trc, &parent, "parent");
|
||||
JS_ASSERT(parent == base->getObjectParent());
|
||||
*prevParent = parent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,11 +47,12 @@ namespace gc {
|
|||
#define DeclMarker(base, type) \
|
||||
void Mark##base(JSTracer *trc, HeapPtr<type> *thing, const char *name); \
|
||||
void Mark##base##Root(JSTracer *trc, type **thingp, const char *name); \
|
||||
void Mark##base##Unbarriered(JSTracer *trc, type *thing, const char *name); \
|
||||
void Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name); \
|
||||
void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *thing, const char *name); \
|
||||
void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name);
|
||||
|
||||
DeclMarker(BaseShape, BaseShape)
|
||||
DeclMarker(BaseShape, UnownedBaseShape)
|
||||
DeclMarker(Object, ArgumentsObject)
|
||||
DeclMarker(Object, GlobalObject)
|
||||
DeclMarker(Object, JSObject)
|
||||
|
@ -120,7 +121,10 @@ void
|
|||
MarkSlot(JSTracer *trc, HeapSlot *s, const char *name);
|
||||
|
||||
void
|
||||
MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name);
|
||||
MarkArraySlots(JSTracer *trc, size_t len, HeapSlot *vec, const char *name);
|
||||
|
||||
void
|
||||
MarkObjectSlots(JSTracer *trc, JSObject *obj, uint32_t start, uint32_t nslots);
|
||||
|
||||
/*
|
||||
* Mark a value that may be in a different compartment from the compartment
|
||||
|
@ -129,8 +133,16 @@ MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name);
|
|||
void
|
||||
MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name);
|
||||
|
||||
|
||||
/*** Special Cases ***/
|
||||
|
||||
/*
|
||||
* The unioned HeapPtr stored in script->globalObj needs special treatment to
|
||||
* typecheck correctly.
|
||||
*/
|
||||
void
|
||||
MarkObject(JSTracer *trc, HeapPtr<GlobalObject, JSScript *> *thingp, const char *name);
|
||||
|
||||
/* Direct value access used by the write barriers and the methodjit. */
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
|
||||
|
|
|
@ -1312,8 +1312,11 @@ TypeObject::writeBarrierPre(TypeObject *type)
|
|||
return;
|
||||
|
||||
JSCompartment *comp = type->compartment();
|
||||
if (comp->needsBarrier())
|
||||
MarkTypeObjectUnbarriered(comp->barrierTracer(), type, "write barrier");
|
||||
if (comp->needsBarrier()) {
|
||||
TypeObject *tmp = type;
|
||||
MarkTypeObjectUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
|
||||
JS_ASSERT(tmp == type);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1327,8 +1330,11 @@ TypeObject::readBarrier(TypeObject *type)
|
|||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
JSCompartment *comp = type->compartment();
|
||||
if (comp->needsBarrier())
|
||||
MarkTypeObjectUnbarriered(comp->barrierTracer(), type, "read barrier");
|
||||
if (comp->needsBarrier()) {
|
||||
TypeObject *tmp = type;
|
||||
MarkTypeObjectUnbarriered(comp->barrierTracer(), &tmp, "read barrier");
|
||||
JS_ASSERT(tmp == type);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1341,7 +1347,7 @@ TypeNewScript::writeBarrierPre(TypeNewScript *newScript)
|
|||
|
||||
JSCompartment *comp = newScript->fun->compartment();
|
||||
if (comp->needsBarrier()) {
|
||||
MarkObjectUnbarriered(comp->barrierTracer(), newScript->fun, "write barrier");
|
||||
MarkObject(comp->barrierTracer(), &newScript->fun, "write barrier");
|
||||
MarkShape(comp->barrierTracer(), &newScript->shape, "write barrier");
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -440,6 +440,21 @@ js::RunScript(JSContext *cx, JSScript *script, StackFrame *fp)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
struct CheckStackBalance {
|
||||
JSContext *cx;
|
||||
StackFrame *fp;
|
||||
JSObject *enumerators;
|
||||
CheckStackBalance(JSContext *cx)
|
||||
: cx(cx), fp(cx->fp()), enumerators(cx->enumerators)
|
||||
{}
|
||||
~CheckStackBalance() {
|
||||
JS_ASSERT(fp == cx->fp());
|
||||
JS_ASSERT_IF(!fp->isGeneratorFrame(), enumerators == cx->enumerators);
|
||||
}
|
||||
} check(cx);
|
||||
#endif
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
mjit::CompileStatus status;
|
||||
status = mjit::CanMethodJIT(cx, script, script->code, fp->isConstructing(),
|
||||
|
@ -511,12 +526,9 @@ js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
|
|||
return false;
|
||||
|
||||
/* Run function until JSOP_STOP, JSOP_RETURN or error. */
|
||||
JSBool ok;
|
||||
{
|
||||
AutoPreserveEnumerators preserve(cx);
|
||||
ok = RunScript(cx, fun->script(), fp);
|
||||
}
|
||||
JSBool ok = RunScript(cx, fun->script(), fp);
|
||||
|
||||
/* Propagate the return value out. */
|
||||
args.rval() = fp->returnValue();
|
||||
JS_ASSERT_IF(ok && construct, !args.rval().isPrimitive());
|
||||
return ok;
|
||||
|
@ -653,17 +665,17 @@ js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const V
|
|||
|
||||
TypeScript::SetThis(cx, script, fp->thisValue());
|
||||
|
||||
AutoPreserveEnumerators preserve(cx);
|
||||
JSBool ok = RunScript(cx, script, fp);
|
||||
if (result && ok)
|
||||
*result = fp->returnValue();
|
||||
bool ok = RunScript(cx, script, fp);
|
||||
|
||||
if (fp->isStrictEvalFrame())
|
||||
js_PutCallObject(fp);
|
||||
|
||||
Probes::stopExecution(cx, script);
|
||||
|
||||
return !!ok;
|
||||
/* Propgate the return value out. */
|
||||
if (result)
|
||||
*result = fp->returnValue();
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -977,31 +989,35 @@ js::UnwindScope(JSContext *cx, uint32_t stackDepth)
|
|||
}
|
||||
|
||||
/*
|
||||
* Find the results of incrementing or decrementing *vp. For pre-increments,
|
||||
* both *vp and *vp2 will contain the result on return. For post-increments,
|
||||
* vp will contain the original value converted to a number and vp2 will get
|
||||
* the result. Both vp and vp2 must be roots.
|
||||
* Increment/decrement the value 'v'. The resulting value is stored in *slot.
|
||||
* The result of the expression (taking into account prefix/postfix) is stored
|
||||
* in *expr.
|
||||
*/
|
||||
static bool
|
||||
DoIncDec(JSContext *cx, const JSCodeSpec *cs, Value *vp, Value *vp2)
|
||||
DoIncDec(JSContext *cx, JSScript *script, jsbytecode *pc, const Value &v, Value *slot, Value *expr)
|
||||
{
|
||||
if (cs->format & JOF_POST) {
|
||||
double d;
|
||||
if (!ToNumber(cx, *vp, &d))
|
||||
return JS_FALSE;
|
||||
vp->setNumber(d);
|
||||
(cs->format & JOF_INC) ? ++d : --d;
|
||||
vp2->setNumber(d);
|
||||
return JS_TRUE;
|
||||
const JSCodeSpec &cs = js_CodeSpec[*pc];
|
||||
|
||||
if (v.isInt32()) {
|
||||
int32_t i = v.toInt32();
|
||||
if (i > JSVAL_INT_MIN && i < JSVAL_INT_MAX) {
|
||||
int32_t sum = i + (cs.format & JOF_INC ? 1 : -1);
|
||||
*slot = Int32Value(sum);
|
||||
*expr = (cs.format & JOF_POST) ? Int32Value(i) : *slot;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
double d;
|
||||
if (!ToNumber(cx, *vp, &d))
|
||||
return JS_FALSE;
|
||||
(cs->format & JOF_INC) ? ++d : --d;
|
||||
vp->setNumber(d);
|
||||
*vp2 = *vp;
|
||||
return JS_TRUE;
|
||||
if (!ToNumber(cx, *slot, &d))
|
||||
return false;
|
||||
|
||||
double sum = d + (cs.format & JOF_INC ? 1 : -1);
|
||||
*slot = NumberValue(sum);
|
||||
*expr = (cs.format & JOF_POST) ? NumberValue(d) : *slot;
|
||||
|
||||
TypeScript::MonitorOverflow(cx, script, pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
const Value &
|
||||
|
@ -1071,31 +1087,14 @@ js::FindUpvarFrame(JSContext *cx, unsigned targetLevel)
|
|||
|
||||
#define POP_BOOLEAN(cx, vp, b) do { VALUE_TO_BOOLEAN(cx, vp, b); regs.sp--; } while(0)
|
||||
|
||||
#define VALUE_TO_OBJECT(cx, vp, obj) \
|
||||
JS_BEGIN_MACRO \
|
||||
if ((vp)->isObject()) { \
|
||||
obj = &(vp)->toObject(); \
|
||||
} else { \
|
||||
obj = js_ValueToNonNullObject(cx, *(vp)); \
|
||||
if (!obj) \
|
||||
goto error; \
|
||||
(vp)->setObject(*obj); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
#define FETCH_OBJECT(cx, n, obj) \
|
||||
JS_BEGIN_MACRO \
|
||||
Value *vp_ = ®s.sp[n]; \
|
||||
VALUE_TO_OBJECT(cx, vp_, obj); \
|
||||
obj = ToObject(cx, (vp_)); \
|
||||
if (!obj) \
|
||||
goto error; \
|
||||
JS_END_MACRO
|
||||
|
||||
/* Test whether v is an int in the range [-2^31 + 1, 2^31 - 2] */
|
||||
static JS_ALWAYS_INLINE bool
|
||||
CanIncDecWithoutOverflow(int32_t i)
|
||||
{
|
||||
return (i > JSVAL_INT_MIN) && (i < JSVAL_INT_MAX);
|
||||
}
|
||||
|
||||
/*
|
||||
* Threaded interpretation via computed goto appears to be well-supported by
|
||||
* GCC 3 and higher. IBM's C compiler when run with the right options (e.g.,
|
||||
|
@ -2499,62 +2498,29 @@ BEGIN_CASE(JSOP_GNAMEDEC)
|
|||
/* No-op */
|
||||
END_CASE(JSOP_INCPROP)
|
||||
|
||||
{
|
||||
int incr, incr2;
|
||||
uint32_t slot;
|
||||
Value *vp;
|
||||
|
||||
/* Position cases so the most frequent i++ does not need a jump. */
|
||||
BEGIN_CASE(JSOP_DECARG)
|
||||
incr = -1; incr2 = -1; goto do_arg_incop;
|
||||
BEGIN_CASE(JSOP_ARGDEC)
|
||||
incr = -1; incr2 = 0; goto do_arg_incop;
|
||||
BEGIN_CASE(JSOP_INCARG)
|
||||
incr = 1; incr2 = 1; goto do_arg_incop;
|
||||
BEGIN_CASE(JSOP_ARGINC)
|
||||
incr = 1; incr2 = 0;
|
||||
|
||||
do_arg_incop:
|
||||
slot = GET_ARGNO(regs.pc);
|
||||
JS_ASSERT(slot < regs.fp()->numFormalArgs());
|
||||
vp = argv + slot;
|
||||
goto do_int_fast_incop;
|
||||
{
|
||||
Value &arg = regs.fp()->formalArg(GET_ARGNO(regs.pc));
|
||||
if (!DoIncDec(cx, script, regs.pc, arg, &arg, ®s.sp[0]))
|
||||
goto error;
|
||||
regs.sp++;
|
||||
}
|
||||
END_CASE(JSOP_ARGINC);
|
||||
|
||||
BEGIN_CASE(JSOP_DECLOCAL)
|
||||
incr = -1; incr2 = -1; goto do_local_incop;
|
||||
BEGIN_CASE(JSOP_LOCALDEC)
|
||||
incr = -1; incr2 = 0; goto do_local_incop;
|
||||
BEGIN_CASE(JSOP_INCLOCAL)
|
||||
incr = 1; incr2 = 1; goto do_local_incop;
|
||||
BEGIN_CASE(JSOP_LOCALINC)
|
||||
incr = 1; incr2 = 0;
|
||||
|
||||
/*
|
||||
* do_local_incop comes right before do_int_fast_incop as we want to
|
||||
* avoid an extra jump for variable cases as local++ is more frequent
|
||||
* than arg++.
|
||||
*/
|
||||
do_local_incop:
|
||||
slot = GET_SLOTNO(regs.pc);
|
||||
JS_ASSERT(slot < regs.fp()->numSlots());
|
||||
vp = regs.fp()->slots() + slot;
|
||||
|
||||
do_int_fast_incop:
|
||||
int32_t tmp;
|
||||
if (JS_LIKELY(vp->isInt32() && CanIncDecWithoutOverflow(tmp = vp->toInt32()))) {
|
||||
vp->getInt32Ref() = tmp + incr;
|
||||
JS_ASSERT(JSOP_INCARG_LENGTH == js_CodeSpec[op].length);
|
||||
PUSH_INT32(tmp + incr2);
|
||||
} else {
|
||||
PUSH_COPY(*vp);
|
||||
if (!DoIncDec(cx, &js_CodeSpec[op], ®s.sp[-1], vp))
|
||||
goto error;
|
||||
TypeScript::MonitorOverflow(cx, script, regs.pc);
|
||||
}
|
||||
len = JSOP_INCARG_LENGTH;
|
||||
JS_ASSERT(len == js_CodeSpec[op].length);
|
||||
DO_NEXT_OP(len);
|
||||
{
|
||||
Value &local = regs.fp()->localSlot(GET_SLOTNO(regs.pc));
|
||||
if (!DoIncDec(cx, script, regs.pc, local, &local, ®s.sp[0]))
|
||||
goto error;
|
||||
regs.sp++;
|
||||
}
|
||||
END_CASE(JSOP_LOCALINC)
|
||||
|
||||
BEGIN_CASE(JSOP_THIS)
|
||||
if (!ComputeThis(cx, regs.fp()))
|
||||
|
@ -2915,7 +2881,7 @@ BEGIN_CASE(JSOP_TABLESWITCH)
|
|||
int32_t high = GET_JUMP_OFFSET(pc2);
|
||||
|
||||
i -= low;
|
||||
if ((jsuint)i < (jsuint)(high - low + 1)) {
|
||||
if ((uint32_t)i < (uint32_t)(high - low + 1)) {
|
||||
pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;
|
||||
int32_t off = (int32_t) GET_JUMP_OFFSET(pc2);
|
||||
if (off)
|
||||
|
@ -3567,9 +3533,9 @@ BEGIN_CASE(JSOP_INITELEM)
|
|||
if (rref.isMagic(JS_ARRAY_HOLE)) {
|
||||
JS_ASSERT(obj->isArray());
|
||||
JS_ASSERT(JSID_IS_INT(id));
|
||||
JS_ASSERT(jsuint(JSID_TO_INT(id)) < StackSpace::ARGS_LENGTH_MAX);
|
||||
JS_ASSERT(uint32_t(JSID_TO_INT(id)) < StackSpace::ARGS_LENGTH_MAX);
|
||||
if (JSOp(regs.pc[JSOP_INITELEM_LENGTH]) == JSOP_ENDINIT &&
|
||||
!js_SetLengthProperty(cx, obj, (jsuint) (JSID_TO_INT(id) + 1))) {
|
||||
!js_SetLengthProperty(cx, obj, (uint32_t) (JSID_TO_INT(id) + 1))) {
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -61,21 +61,6 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
class AutoPreserveEnumerators {
|
||||
JSContext *cx;
|
||||
JSObject *enumerators;
|
||||
|
||||
public:
|
||||
AutoPreserveEnumerators(JSContext *cx) : cx(cx), enumerators(cx->enumerators)
|
||||
{
|
||||
}
|
||||
|
||||
~AutoPreserveEnumerators()
|
||||
{
|
||||
cx->enumerators = enumerators;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Compute the implicit |this| parameter for a call expression where the callee
|
||||
* funval was resolved from an unqualified name reference to a property on obj
|
||||
|
@ -232,7 +217,7 @@ GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp
|
|||
if (lval.isObject()) {
|
||||
JSObject *obj = &lval.toObject();
|
||||
if (obj->isArray()) {
|
||||
jsuint length = obj->getArrayLength();
|
||||
uint32_t length = obj->getArrayLength();
|
||||
*vp = NumberValue(length);
|
||||
return true;
|
||||
}
|
||||
|
@ -255,7 +240,7 @@ GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp
|
|||
}
|
||||
}
|
||||
|
||||
JSObject *obj = ValueToObjectOrPrototype(cx, lval);
|
||||
JSObject *obj = ValueToObject(cx, lval);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
|
@ -804,13 +789,13 @@ SetObjectElementOperation(JSContext *cx, JSObject *obj, jsid id, const Value &va
|
|||
|
||||
do {
|
||||
if (obj->isDenseArray() && JSID_IS_INT(id)) {
|
||||
jsuint length = obj->getDenseArrayInitializedLength();
|
||||
uint32_t length = obj->getDenseArrayInitializedLength();
|
||||
int32_t i = JSID_TO_INT(id);
|
||||
if ((jsuint)i < length) {
|
||||
if ((uint32_t)i < length) {
|
||||
if (obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) {
|
||||
if (js_PrototypeHasIndexedProperties(cx, obj))
|
||||
break;
|
||||
if ((jsuint)i >= obj->getArrayLength())
|
||||
if ((uint32_t)i >= obj->getArrayLength())
|
||||
obj->setArrayLength(cx, i + 1);
|
||||
}
|
||||
obj->setDenseArrayElementWithType(cx, i, value);
|
||||
|
|
|
@ -435,7 +435,7 @@ js_math_min(JSContext *cx, unsigned argc, Value *vp)
|
|||
static double
|
||||
powi(double x, int y)
|
||||
{
|
||||
jsuint n = (y < 0) ? -y : y;
|
||||
unsigned n = (y < 0) ? -y : y;
|
||||
double m = x;
|
||||
double p = 1;
|
||||
while (true) {
|
||||
|
|
|
@ -78,11 +78,11 @@
|
|||
#include "jsinferinlines.h"
|
||||
#include "jsnuminlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/MethodGuard-inl.h"
|
||||
#include "vm/NumberObject-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
@ -577,7 +577,7 @@ js_IntToString(JSContext *cx, int32_t si)
|
|||
static char *
|
||||
IntToCString(ToCStringBuf *cbuf, int i, int base = 10)
|
||||
{
|
||||
jsuint u = (i < 0) ? -i : i;
|
||||
unsigned u = (i < 0) ? -i : i;
|
||||
|
||||
RangedPtr<char> cp(cbuf->sbuf + cbuf->sbufSize - 1, cbuf->sbuf, cbuf->sbufSize);
|
||||
*cp = '\0';
|
||||
|
@ -589,7 +589,7 @@ IntToCString(ToCStringBuf *cbuf, int i, int base = 10)
|
|||
break;
|
||||
case 16:
|
||||
do {
|
||||
jsuint newu = u / 16;
|
||||
unsigned newu = u / 16;
|
||||
*--cp = "0123456789abcdef"[u - newu * 16];
|
||||
u = newu;
|
||||
} while (u != 0);
|
||||
|
@ -597,7 +597,7 @@ IntToCString(ToCStringBuf *cbuf, int i, int base = 10)
|
|||
default:
|
||||
JS_ASSERT(base >= 2 && base <= 36);
|
||||
do {
|
||||
jsuint newu = u / base;
|
||||
unsigned newu = u / base;
|
||||
*--cp = "0123456789abcdefghijklmnopqrstuvwxyz"[u - newu * base];
|
||||
u = newu;
|
||||
} while (u != 0);
|
||||
|
@ -1127,7 +1127,7 @@ js_NumberToStringWithBase(JSContext *cx, double d, int base)
|
|||
if (JSDOUBLE_IS_INT32(d, &i)) {
|
||||
if (base == 10 && StaticStrings::hasInt(i))
|
||||
return cx->runtime->staticStrings.getInt(i);
|
||||
if (jsuint(i) < jsuint(base)) {
|
||||
if (unsigned(i) < unsigned(base)) {
|
||||
if (i < 10)
|
||||
return cx->runtime->staticStrings.getInt(i);
|
||||
jschar c = 'a' + i - 10;
|
||||
|
@ -1346,7 +1346,7 @@ ValueToUint16Slow(JSContext *cx, const Value &v, uint16_t *out)
|
|||
bool neg = (d < 0);
|
||||
d = floor(neg ? -d : d);
|
||||
d = neg ? -d : d;
|
||||
jsuint m = JS_BIT(16);
|
||||
unsigned m = JS_BIT(16);
|
||||
d = fmod(d, (double) m);
|
||||
if (d < 0)
|
||||
d += m;
|
||||
|
|
|
@ -89,9 +89,9 @@
|
|||
#include "jsobjinlines.h"
|
||||
#include "jsscopeinlines.h"
|
||||
#include "jsscriptinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/MethodGuard-inl.h"
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
#include "jsxml.h"
|
||||
|
@ -2194,7 +2194,7 @@ DefinePropertyOnArray(JSContext *cx, JSObject *obj, const jsid &id, const PropDe
|
|||
if (obj->isDenseArray() && !obj->makeDenseArraySlow(cx))
|
||||
return JS_FALSE;
|
||||
|
||||
jsuint oldLen = obj->getArrayLength();
|
||||
uint32_t oldLen = obj->getArrayLength();
|
||||
|
||||
if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
|
||||
/*
|
||||
|
|
|
@ -695,7 +695,7 @@ struct JSObject : public js::ObjectImpl
|
|||
|
||||
inline js::types::TypeObject *getType(JSContext *cx);
|
||||
|
||||
js::HeapPtr<js::types::TypeObject> &typeFromGC() {
|
||||
const js::HeapPtr<js::types::TypeObject> &typeFromGC() const {
|
||||
/* Direct field access for use by GC. */
|
||||
return type_;
|
||||
}
|
||||
|
|
|
@ -652,23 +652,6 @@ JSObject::denseArrayHasInlineSlots() const
|
|||
|
||||
namespace js {
|
||||
|
||||
inline JSObject *
|
||||
ValueToObjectOrPrototype(JSContext *cx, const Value &v)
|
||||
{
|
||||
if (v.isObject())
|
||||
return &v.toObject();
|
||||
GlobalObject *global = &cx->fp()->scopeChain().global();
|
||||
if (v.isString())
|
||||
return global->getOrCreateStringPrototype(cx);
|
||||
if (v.isNumber())
|
||||
return global->getOrCreateNumberPrototype(cx);
|
||||
if (v.isBoolean())
|
||||
return global->getOrCreateBooleanPrototype(cx);
|
||||
JS_ASSERT(v.isNull() || v.isUndefined());
|
||||
js_ReportIsNullOrUndefined(cx, JSDVG_SEARCH_STACK, v, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Any name atom for a function which will be added as a DeclEnv object to the
|
||||
* scope chain above call objects for fun.
|
||||
|
|
|
@ -64,9 +64,9 @@
|
|||
#include "jsboolinlines.h"
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/Stack-inl.h"
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
@ -500,7 +500,7 @@ JA(JSContext *cx, JSObject *obj, StringifyContext *scx)
|
|||
return JS_FALSE;
|
||||
|
||||
/* Step 6. */
|
||||
jsuint length;
|
||||
uint32_t length;
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -649,7 +649,7 @@ js_Stringify(JSContext *cx, Value *vp, JSObject *replacer, Value space, StringBu
|
|||
*/
|
||||
|
||||
/* Step 4b(ii). */
|
||||
jsuint len;
|
||||
uint32_t len;
|
||||
JS_ALWAYS_TRUE(js_GetLengthProperty(cx, replacer, &len));
|
||||
if (replacer->isDenseArray())
|
||||
len = JS_MIN(len, replacer->getDenseArrayCapacity());
|
||||
|
@ -659,7 +659,7 @@ js_Stringify(JSContext *cx, Value *vp, JSObject *replacer, Value space, StringBu
|
|||
return false;
|
||||
|
||||
/* Step 4b(iii). */
|
||||
jsuint i = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
/* Step 4b(iv). */
|
||||
for (; i < len; i++) {
|
||||
|
|
|
@ -43,7 +43,8 @@
|
|||
#include "jsonparser.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
|
|
|
@ -77,11 +77,11 @@
|
|||
#include "jscntxtinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsopcodeinlines.h"
|
||||
#include "jsscriptinlines.h"
|
||||
|
||||
#include "jsautooplen.h"
|
||||
|
||||
#include "vm/RegExpObject-inl.h"
|
||||
#include "vm/StringBuffer-inl.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace js;
|
||||
|
@ -1825,7 +1825,7 @@ GetLocal(SprintStack *ss, int i)
|
|||
if (obj->isBlock()) {
|
||||
uint32_t depth = obj->asBlock().stackDepth();
|
||||
uint32_t count = obj->asBlock().slotCount();
|
||||
if (jsuint(i - depth) < jsuint(count))
|
||||
if (uint32_t(i - depth) < uint32_t(count))
|
||||
return GetLocalInSlot(ss, i, int(i - depth), obj);
|
||||
}
|
||||
}
|
||||
|
@ -1838,7 +1838,7 @@ GetLocal(SprintStack *ss, int i)
|
|||
if (obj->isBlock()) {
|
||||
uint32_t depth = obj->asBlock().stackDepth();
|
||||
uint32_t count = obj->asBlock().slotCount();
|
||||
if (jsuint(i - depth) < jsuint(count))
|
||||
if (uint32_t(i - depth) < uint32_t(count))
|
||||
return GetLocalInSlot(ss, i, int(i - depth), obj);
|
||||
}
|
||||
}
|
||||
|
@ -2446,15 +2446,10 @@ SprintNormalFor(JSContext *cx, JSPrinter *jp, SprintStack *ss, const char *initP
|
|||
ptrdiff_t next = js_GetSrcNoteOffset(sn, 1);
|
||||
ptrdiff_t tail = js_GetSrcNoteOffset(sn, 2);
|
||||
|
||||
/*
|
||||
* If this loop has a condition, then pc points at a goto
|
||||
* targeting the condition.
|
||||
*/
|
||||
/* Find the loop head, skipping over any leading GOTO or NOP. */
|
||||
jsbytecode *pc2 = pc;
|
||||
if (cond != tail) {
|
||||
LOCAL_ASSERT(*pc == JSOP_GOTO);
|
||||
pc2 += JSOP_GOTO_LENGTH;
|
||||
}
|
||||
if (*pc == JSOP_GOTO || *pc == JSOP_NOP)
|
||||
pc2 += GetBytecodeLength(pc);
|
||||
LOCAL_ASSERT(tail + GET_JUMP_OFFSET(pc + tail) == pc2 - pc);
|
||||
|
||||
if (cond != tail) {
|
||||
|
|
|
@ -150,7 +150,7 @@ Shape::removeChild(Shape *child)
|
|||
|
||||
if (hash->count() == 1) {
|
||||
/* Convert from HASH form back to SHAPE form. */
|
||||
KidsHash::Range r = hash->all();
|
||||
KidsHash::Range r = hash->all();
|
||||
Shape *otherChild = r.front();
|
||||
JS_ASSERT((r.popFront(), r.empty())); /* No more elements! */
|
||||
kidp->setShape(otherChild);
|
||||
|
@ -166,8 +166,11 @@ ReadBarrier(Shape *shape)
|
|||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
JSCompartment *comp = shape->compartment();
|
||||
if (comp->needsBarrier())
|
||||
MarkShapeUnbarriered(comp->barrierTracer(), shape, "read barrier");
|
||||
if (comp->needsBarrier()) {
|
||||
Shape *tmp = shape;
|
||||
MarkShapeUnbarriered(comp->barrierTracer(), &tmp, "read barrier");
|
||||
JS_ASSERT(tmp == shape);
|
||||
}
|
||||
#endif
|
||||
return shape;
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче