зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to m-i.
This commit is contained in:
Коммит
9ae4350b73
|
@ -507,7 +507,7 @@ function HistoryMenu(aPopupShowingEvent) {
|
|||
"@mozilla.org/browser/sessionstore;1",
|
||||
"nsISessionStore");
|
||||
PlacesMenu.call(this, aPopupShowingEvent,
|
||||
"place:redirectsMode=2&sort=4&maxResults=15");
|
||||
"place:sort=4&maxResults=15");
|
||||
}
|
||||
|
||||
HistoryMenu.prototype = {
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.expander[hidden],
|
||||
.expander[hidden] + *,
|
||||
.expander[collapsed] + * {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -126,10 +126,8 @@
|
|||
// Disallow overrides if this is a Strict-Transport-Security
|
||||
// host and the cert is bad (STS Spec section 7.3) or if the
|
||||
// certerror is in a frame (bug 633691).
|
||||
if (getCSSClass() == "badStsCert" || window != top) {
|
||||
var ec = document.getElementById('expertContent');
|
||||
ec.parentNode.removeChild(ec);
|
||||
}
|
||||
if (getCSSClass() == "badStsCert" || window != top)
|
||||
document.getElementById("expertContent").setAttribute("hidden", "true");
|
||||
|
||||
var tech = document.getElementById("technicalContentText");
|
||||
if (tech)
|
||||
|
|
|
@ -1352,7 +1352,7 @@ BrowserGlue.prototype = {
|
|||
// be set to the version it has been added in, we will compare its value
|
||||
// to users' smartBookmarksVersion and add new smart bookmarks without
|
||||
// recreating old deleted ones.
|
||||
const SMART_BOOKMARKS_VERSION = 3;
|
||||
const SMART_BOOKMARKS_VERSION = 4;
|
||||
const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
|
||||
const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
|
||||
|
||||
|
@ -1380,9 +1380,7 @@ BrowserGlue.prototype = {
|
|||
let smartBookmarks = {
|
||||
MostVisited: {
|
||||
title: bundle.GetStringFromName("mostVisitedTitle"),
|
||||
uri: NetUtil.newURI("place:redirectsMode=" +
|
||||
Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET +
|
||||
"&sort=" +
|
||||
uri: NetUtil.newURI("place:sort=" +
|
||||
Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
|
||||
"&maxResults=" + MAX_RESULTS),
|
||||
parent: PlacesUtils.toolbarFolderId,
|
||||
|
|
|
@ -733,6 +733,8 @@ PlacesViewBase.prototype = {
|
|||
.direction == "rtl";
|
||||
},
|
||||
|
||||
get ownerWindow() window,
|
||||
|
||||
/**
|
||||
* Adds an "Open All in Tabs" menuitem to the bottom of the popup.
|
||||
* @param aPopup
|
||||
|
|
|
@ -336,7 +336,7 @@ var PlacesOrganizer = {
|
|||
// The command execution function will take care of seeing if the
|
||||
// selection is a folder or a different container type, and will
|
||||
// load its contents in tabs.
|
||||
PlacesUIUtils.openContainerNodeInTabs(selectedNode, aEvent);
|
||||
PlacesUIUtils.openContainerNodeInTabs(selectedNode, aEvent, currentView);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -363,7 +363,7 @@ var PlacesOrganizer = {
|
|||
|
||||
openSelectedNode: function PO_openSelectedNode(aEvent) {
|
||||
PlacesUIUtils.openNodeWithEvent(this._content.selectedNode, aEvent,
|
||||
this._content.treeBoxObject.view);
|
||||
this._content);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -86,7 +86,7 @@ var SidebarUtils = {
|
|||
else if (!mouseInGutter && openInTabs &&
|
||||
aEvent.originalTarget.localName == "treechildren") {
|
||||
tbo.view.selection.select(row.value);
|
||||
PlacesUIUtils.openContainerNodeInTabs(aTree.selectedNode, aEvent, tbo.view);
|
||||
PlacesUIUtils.openContainerNodeInTabs(aTree.selectedNode, aEvent, aTree);
|
||||
}
|
||||
else if (!mouseInGutter && !isContainer &&
|
||||
aEvent.originalTarget.localName == "treechildren") {
|
||||
|
@ -94,7 +94,7 @@ var SidebarUtils = {
|
|||
// do this *before* attempting to load the link since openURL uses
|
||||
// selection as an indication of which link to load.
|
||||
tbo.view.selection.select(row.value);
|
||||
PlacesUIUtils.openNodeWithEvent(aTree.selectedNode, aEvent, tbo.view);
|
||||
PlacesUIUtils.openNodeWithEvent(aTree.selectedNode, aEvent, aTree);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -699,6 +699,10 @@
|
|||
this._contextMenuShown = false;
|
||||
<body/>
|
||||
</method>
|
||||
|
||||
<property name="ownerWindow"
|
||||
readonly="true"
|
||||
onget="return window;"/>
|
||||
</implementation>
|
||||
<handlers>
|
||||
<handler event="focus"><![CDATA[
|
||||
|
|
|
@ -377,12 +377,6 @@ var PlacesUIUtils = {
|
|||
*/
|
||||
showBookmarkDialog:
|
||||
function PUIU_showBookmarkDialog(aInfo, aParentWindow, aResizable) {
|
||||
// This is a compatibility shim for add-ons. It will warn in the Error
|
||||
// Console when used.
|
||||
if (!aParentWindow) {
|
||||
aParentWindow = this._getWindow(null);
|
||||
}
|
||||
|
||||
// Preserve size attributes differently based on the fact the dialog has
|
||||
// a folder picker or not. If the picker is visible, the dialog should
|
||||
// be resizable since it may not show enough content for the folders
|
||||
|
@ -621,44 +615,9 @@ var PlacesUIUtils = {
|
|||
browserWindow.gBrowser.loadTabs(urls, loadInBackground, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper method for methods which are forced to take a view/window
|
||||
* parameter as an optional parameter. It will be removed post Fx4.
|
||||
*/
|
||||
_getWindow: function PUIU__getWindow(aView) {
|
||||
if (aView) {
|
||||
// Pratically, this is the case for places trees.
|
||||
if (aView instanceof Components.interfaces.nsIDOMNode)
|
||||
return aView.ownerDocument.defaultView;
|
||||
|
||||
return Cu.getGlobalForObject(aView);
|
||||
}
|
||||
|
||||
let caller = arguments.callee.caller;
|
||||
|
||||
// If a view wasn't expected, the method should have got a window.
|
||||
if (aView === null) {
|
||||
Components.utils.reportError("The api has changed. A window should be " +
|
||||
"passed to " + caller.name + ". Not " +
|
||||
"passing a window will throw in a future " +
|
||||
"release.");
|
||||
}
|
||||
else {
|
||||
Components.utils.reportError("The api has changed. A places view " +
|
||||
"should be passed to " + caller.name + ". " +
|
||||
"Not passing a view will throw in a future " +
|
||||
"release.");
|
||||
}
|
||||
|
||||
// This could certainly break in some edge cases (like bug 562998), but
|
||||
// that's the best we should do for those extreme backwards-compatibility cases.
|
||||
let topBrowserWin = this._getTopBrowserWin();
|
||||
return topBrowserWin ? topBrowserWin : focusManager.focusedWindow;
|
||||
},
|
||||
|
||||
openContainerNodeInTabs:
|
||||
function PUIU_openContainerInTabs(aNode, aEvent, aView) {
|
||||
let window = this._getWindow(aView);
|
||||
let window = aView.ownerWindow;
|
||||
|
||||
let urlsToOpen = PlacesUtils.getURLsForContainerNode(aNode);
|
||||
if (!this._confirmOpenInTabs(urlsToOpen.length, window))
|
||||
|
@ -668,7 +627,7 @@ var PlacesUIUtils = {
|
|||
},
|
||||
|
||||
openURINodesInTabs: function PUIU_openURINodesInTabs(aNodes, aEvent, aView) {
|
||||
let window = this._getWindow(aView);
|
||||
let window = aView.ownerWindow;
|
||||
|
||||
let urlsToOpen = [];
|
||||
for (var i=0; i < aNodes.length; i++) {
|
||||
|
@ -693,7 +652,7 @@ var PlacesUIUtils = {
|
|||
*/
|
||||
openNodeWithEvent:
|
||||
function PUIU_openNodeWithEvent(aNode, aEvent, aView) {
|
||||
let window = this._getWindow(aView);
|
||||
let window = aView.ownerWindow;
|
||||
this._openNodeIn(aNode, window.whereToOpenLink(aEvent), window);
|
||||
},
|
||||
|
||||
|
@ -703,7 +662,7 @@ var PlacesUIUtils = {
|
|||
* see also openUILinkIn
|
||||
*/
|
||||
openNodeIn: function PUIU_openNodeIn(aNode, aWhere, aView) {
|
||||
let window = this._getWindow(aView);
|
||||
let window = aView.ownerWindow;
|
||||
this._openNodeIn(aNode, aWhere, window);
|
||||
},
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ let (backup_date = new Date().toLocaleFormat("%Y-%m-%d")) {
|
|||
}
|
||||
|
||||
// Smart bookmarks constants.
|
||||
const SMART_BOOKMARKS_VERSION = 3;
|
||||
const SMART_BOOKMARKS_VERSION = 4;
|
||||
const SMART_BOOKMARKS_ON_TOOLBAR = 1;
|
||||
const SMART_BOOKMARKS_ON_MENU = 3; // Takes in count the additional separator.
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@ ac_add_options --enable-js-diagnostics
|
|||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# This will overwrite the default of stripping everything and keep the symbol table.
|
||||
# This is useful for profiling and debugging and only increases the package size
|
||||
# by 2 MBs.
|
||||
STRIP_FLAGS="--strip-debug"
|
||||
|
||||
# PGO
|
||||
mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@ ac_add_options --enable-js-diagnostics
|
|||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# This will overwrite the default of stripping everything and keep the symbol table.
|
||||
# This is useful for profiling and debugging and only increases the package size
|
||||
# by 2 MBs.
|
||||
STRIP_FLAGS="--strip-debug"
|
||||
|
||||
# PGO
|
||||
mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'
|
||||
|
||||
|
|
|
@ -432,9 +432,6 @@ let PlacesProvider = {
|
|||
// Sort by frecency, descending.
|
||||
options.sortingMode = Ci.nsINavHistoryQueryOptions.SORT_BY_FRECENCY_DESCENDING
|
||||
|
||||
// We don't want source redirects for this query.
|
||||
options.redirectsMode = Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET;
|
||||
|
||||
let links = [];
|
||||
|
||||
let callback = {
|
||||
|
|
|
@ -477,8 +477,6 @@ var WinTaskbarJumpList =
|
|||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.maxResults = aLimit;
|
||||
options.sortingMode = aSortingMode;
|
||||
// We don't want source redirects for these queries.
|
||||
options.redirectsMode = Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET;
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
|
||||
// Return the pending statement to the caller, to allow cancelation.
|
||||
|
|
14
client.mk
14
client.mk
|
@ -294,13 +294,15 @@ $(CONFIGURES): %: %.in $(EXTRA_CONFIG_DEPS)
|
|||
cd $(@D); $(AUTOCONF)
|
||||
|
||||
CONFIG_STATUS_DEPS := \
|
||||
$(wildcard $(CONFIGURES)) \
|
||||
$(wildcard \
|
||||
$(CONFIGURES) \
|
||||
$(TOPSRCDIR)/allmakefiles.sh \
|
||||
$(wildcard $(TOPSRCDIR)/nsprpub/configure) \
|
||||
$(wildcard $(TOPSRCDIR)/config/milestone.txt) \
|
||||
$(wildcard $(TOPSRCDIR)/js/src/config/milestone.txt) \
|
||||
$(wildcard $(TOPSRCDIR)/browser/config/version.txt) \
|
||||
$(wildcard $(addsuffix confvars.sh,$(wildcard $(TOPSRCDIR)/*/))) \
|
||||
$(TOPSRCDIR)/nsprpub/configure \
|
||||
$(TOPSRCDIR)/config/milestone.txt \
|
||||
$(TOPSRCDIR)/js/src/config/milestone.txt \
|
||||
$(TOPSRCDIR)/browser/config/version.txt \
|
||||
$(TOPSRCDIR)/*/confvars.sh \
|
||||
) \
|
||||
$(NULL)
|
||||
|
||||
CONFIGURE_ENV_ARGS += \
|
||||
|
|
|
@ -231,6 +231,7 @@ LIBXUL_LIBS=@LIBXUL_LIBS@
|
|||
|
||||
ENABLE_STRIP = @ENABLE_STRIP@
|
||||
PKG_SKIP_STRIP = @PKG_SKIP_STRIP@
|
||||
STRIP_FLAGS = @STRIP_FLAGS@
|
||||
|
||||
MOZ_POST_DSO_LIB_COMMAND = @MOZ_POST_DSO_LIB_COMMAND@
|
||||
MOZ_POST_PROGRAM_COMMAND = @MOZ_POST_PROGRAM_COMMAND@
|
||||
|
|
|
@ -837,3 +837,8 @@ EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
|
|||
endif
|
||||
EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
|
||||
EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
|
||||
|
||||
# Include internal ply only if needed
|
||||
ifndef MOZ_SYSTEM_PLY
|
||||
PLY_INCLUDE = -I$(topsrcdir)/other-licenses/ply
|
||||
endif
|
||||
|
|
|
@ -1444,7 +1444,7 @@ xpidl-preqs = \
|
|||
$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
|
||||
$(REPORT_BUILD)
|
||||
$(PYTHON_PATH) \
|
||||
-I$(topsrcdir)/other-licenses/ply \
|
||||
$(PLY_INCLUDE) \
|
||||
-I$(topsrcdir)/xpcom/idl-parser \
|
||||
$(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
|
||||
@if test -n "$(findstring $*.h, $(EXPORTS))"; \
|
||||
|
@ -1456,7 +1456,7 @@ ifndef NO_GEN_XPT
|
|||
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
|
||||
$(REPORT_BUILD)
|
||||
$(PYTHON_PATH) \
|
||||
-I$(topsrcdir)/other-licenses/ply \
|
||||
$(PLY_INCLUDE) \
|
||||
-I$(topsrcdir)/xpcom/idl-parser \
|
||||
-I$(topsrcdir)/xpcom/typelib/xpt/tools \
|
||||
$(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
|
||||
|
|
2035
config/rules.mk.orig
2035
config/rules.mk.orig
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8403,6 +8403,7 @@ AC_SUBST(MOZ_ANDROID_HISTORY)
|
|||
AC_SUBST(MOZ_WEBSMS_BACKEND)
|
||||
AC_SUBST(ENABLE_STRIP)
|
||||
AC_SUBST(PKG_SKIP_STRIP)
|
||||
AC_SUBST(STRIP_FLAGS)
|
||||
AC_SUBST(USE_ELF_DYNSTR_GC)
|
||||
AC_SUBST(USE_ELF_HACK)
|
||||
AC_SUBST(INCREMENTAL_LINKER)
|
||||
|
|
|
@ -135,6 +135,7 @@
|
|||
#include "nsIRequest.h"
|
||||
#include "nsHtml5TreeOpExecutor.h"
|
||||
#include "nsHtml5Parser.h"
|
||||
#include "nsIDOMJSWindow.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -1326,8 +1327,9 @@ nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
|
|||
if (!window) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIDOMJSWindow> win = do_QueryInterface(window);
|
||||
nsCOMPtr<nsIDOMWindow> newWindow;
|
||||
nsresult rv = window->Open(aContentTypeOrUrl, aReplaceOrName, aFeatures,
|
||||
nsresult rv = win->OpenJS(aContentTypeOrUrl, aReplaceOrName, aFeatures,
|
||||
getter_AddRefs(newWindow));
|
||||
*aReturn = newWindow.forget().get();
|
||||
return rv;
|
||||
|
|
|
@ -107,6 +107,7 @@ _TEST_FILES = test_bug1682.html \
|
|||
test_bug677495.html \
|
||||
test_bug677495-1.html \
|
||||
test_bug742261.html \
|
||||
test_bug741266.html \
|
||||
$(NULL)
|
||||
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=741266
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 741266</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741266">Mozilla Bug 741266</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 741266 **/
|
||||
var w = window.open("", "", "width=100,height=100");
|
||||
is(w.innerHeight, 100, "Popup height should be 100 when opened with window.open");
|
||||
// XXXbz On at least some platforms, the innerWidth is off by the scrollbar
|
||||
// width for some reason. So just make sure it's the same for both popups.
|
||||
var width = w.innerWidth;
|
||||
w.close();
|
||||
w = document.open("", "", "width=100,height=100");
|
||||
is(w.innerHeight, 100, "Popup height should be 100 when opened with document.open");
|
||||
is(w.innerWidth, width, "Popup width should be the same when opened with document.open");
|
||||
w.close();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -400,7 +400,7 @@ nsXBLStreamListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
|
||||
if (!bindingDocument->GetRootElement()) {
|
||||
// FIXME: How about an error console warning?
|
||||
NS_WARNING("*** XBL doc with no root element! Something went horribly wrong! ***");
|
||||
NS_WARNING("XBL doc with no root element - this usually shouldn't happen");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# 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/.
|
||||
# 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/.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
|
@ -75,17 +75,19 @@ bindinggen_dependencies := \
|
|||
$(binding_header_files): %Binding.h: $(bindinggen_dependencies) \
|
||||
$(webidl_base)/%.webidl \
|
||||
$(NULL)
|
||||
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
|
||||
-I$(topsrcdir)/other-licenses/ply -I$(srcdir)/parser \
|
||||
$(srcdir)/BindingGen.py $(ACCESSOR_OPT) header $(srcdir)/Bindings.conf $*Binding \
|
||||
$(PYTHON_PATH) \
|
||||
$(PLY_INCLUDE) -I$(srcdir)/parser \
|
||||
$(srcdir)/BindingGen.py $(ACCESSOR_OPT) header \
|
||||
$(srcdir)/Bindings.conf $*Binding \
|
||||
$(webidl_base)/$*.webidl
|
||||
|
||||
$(binding_cpp_files): %Binding.cpp: $(bindinggen_dependencies) \
|
||||
$(webidl_base)/%.webidl \
|
||||
$(NULL)
|
||||
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
|
||||
-I$(topsrcdir)/other-licenses/ply -I$(srcdir)/parser \
|
||||
$(srcdir)/BindingGen.py $(ACCESSOR_OPT) cpp $(srcdir)/Bindings.conf $*Binding \
|
||||
$(PYTHON_PATH) \
|
||||
$(PLY_INCLUDE) -I$(srcdir)/parser \
|
||||
$(srcdir)/BindingGen.py $(ACCESSOR_OPT) cpp \
|
||||
$(srcdir)/Bindings.conf $*Binding \
|
||||
$(webidl_base)/$*.webidl
|
||||
|
||||
$(globalgen_targets): ParserResults.pkl
|
||||
|
@ -108,7 +110,7 @@ $(CACHE_DIR)/.done:
|
|||
ParserResults.pkl: $(globalgen_dependencies) \
|
||||
$(addprefix $(webidl_base)/, $(webidl_files))
|
||||
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
|
||||
-I$(topsrcdir)/other-licenses/ply -I$(srcdir)/parser \
|
||||
$(PLY_INCLUDE) -I$(srcdir)/parser \
|
||||
$(srcdir)/GlobalGen.py $(ACCESSOR_OPT) $(srcdir)/Bindings.conf $(webidl_base) \
|
||||
--cachedir=$(CACHE_DIR) \
|
||||
$(webidl_files)
|
||||
|
|
|
@ -593,6 +593,24 @@ const PDU_MAX_USER_DATA_8BIT = 140;
|
|||
// User Data max length in chars
|
||||
const PDU_MAX_USER_DATA_UCS2 = 70;
|
||||
|
||||
// PID - Protocol Indicator
|
||||
const PDU_PID_DEFAULT = 0x00;
|
||||
const PDU_PID_TELEMATIC_INTERWORKING = 0x20;
|
||||
const PDU_PID_SHORT_MESSAGE_TYPE_0 = 0x40;
|
||||
const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_1 = 0x41;
|
||||
const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_2 = 0x42;
|
||||
const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_3 = 0x43;
|
||||
const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_4 = 0x44;
|
||||
const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_5 = 0x45;
|
||||
const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_6 = 0x46;
|
||||
const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_7 = 0x47;
|
||||
const PDU_PID_ENHANDED_MESSAGE_SERVICE = 0x5E;
|
||||
const PDU_PID_RETURN_CALL_MESSAGE = 0x5F
|
||||
const PDU_PID_ANSI_136_R_DATA = 0x7C;
|
||||
const PDU_PID_ME_DATA_DOWNLOAD = 0x7D;
|
||||
const PDU_PID_ME_DEPERSONALIZATION = 0x7E;
|
||||
const PDU_PID_USIM_DATA_DOWNLOAD = 0x7F;
|
||||
|
||||
// DCS - Data Coding Scheme
|
||||
const PDU_DCS_MSG_CODING_7BITS_ALPHABET = 0x00;
|
||||
const PDU_DCS_MSG_CODING_8BITS_ALPHABET = 0x04;
|
||||
|
|
|
@ -1518,6 +1518,13 @@ let RIL = {
|
|||
return PDU_FCS_UNSPECIFIED;
|
||||
}
|
||||
|
||||
if (message.epid == PDU_PID_SHORT_MESSAGE_TYPE_0) {
|
||||
// `A short message type 0 indicates that the ME must acknowledge receipt
|
||||
// of the short message but shall discard its contents.` ~ 3GPP TS 23.040
|
||||
// 9.2.3.9
|
||||
return PDU_FCS_OK;
|
||||
}
|
||||
|
||||
if (message.header && (message.header.segmentMaxSeq > 1)) {
|
||||
message = this._processReceivedSmsSegment(message);
|
||||
} else {
|
||||
|
@ -2233,7 +2240,7 @@ RIL[REQUEST_DEVICE_IDENTITY] = null;
|
|||
RIL[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE] = null;
|
||||
RIL[REQUEST_GET_SMSC_ADDRESS] = function REQUEST_GET_SMSC_ADDRESS(length, options) {
|
||||
if (options.rilRequestError) {
|
||||
if (options.body) {
|
||||
if (options.type == "sendSMS") {
|
||||
this.sendDOMMessage({
|
||||
type: "sms-send-failed",
|
||||
envelopeId: options.envelopeId,
|
||||
|
@ -2928,6 +2935,32 @@ let GsmPDUHelper = {
|
|||
return addr;
|
||||
},
|
||||
|
||||
/**
|
||||
* Read TP-Protocol-Indicator(TP-PID).
|
||||
*
|
||||
* @param msg
|
||||
* message object for output.
|
||||
*
|
||||
* @see 3GPP TS 23.040 9.2.3.9
|
||||
*/
|
||||
readProtocolIndicator: function readProtocolIndicator(msg) {
|
||||
// `The MS shall interpret reserved, obsolete, or unsupported values as the
|
||||
// value 00000000 but shall store them exactly as received.`
|
||||
msg.pid = this.readHexOctet();
|
||||
|
||||
msg.epid = msg.pid;
|
||||
switch (msg.epid & 0xC0) {
|
||||
case 0x40:
|
||||
// Bit 7..0 = 01xxxxxx
|
||||
switch (msg.epid) {
|
||||
case PDU_PID_SHORT_MESSAGE_TYPE_0:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
msg.epid = PDU_PID_DEFAULT;
|
||||
},
|
||||
|
||||
/**
|
||||
* Read GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
|
||||
*
|
||||
|
@ -2943,14 +2976,14 @@ let GsmPDUHelper = {
|
|||
let timestamp = Date.UTC(year, month, day, hour, minute, second);
|
||||
|
||||
// If the most significant bit of the least significant nibble is 1,
|
||||
// the timezone offset is negative (fourth bit from the right => 0x08).
|
||||
// the timezone offset is negative (fourth bit from the right => 0x08):
|
||||
// localtime = UTC + tzOffset
|
||||
// therefore
|
||||
// UTC = localtime - tzOffset
|
||||
let tzOctet = this.readHexOctet();
|
||||
let tzOffset = this.octetToBCD(tzOctet & ~0x08) * 15 * 60 * 1000;
|
||||
if (tzOctet & 0x08) {
|
||||
tzOffset = (tzOctet & 0x08) ? -tzOffset : tzOffset;
|
||||
timestamp -= tzOffset;
|
||||
} else {
|
||||
timestamp += tzOffset;
|
||||
}
|
||||
|
||||
return timestamp;
|
||||
},
|
||||
|
@ -3074,7 +3107,7 @@ let GsmPDUHelper = {
|
|||
|
||||
// TP-Protocol-Identifier
|
||||
if (pi & PDU_PI_PROTOCOL_IDENTIFIER) {
|
||||
msg.pid = this.readHexOctet();
|
||||
this.readProtocolIndicator(msg);
|
||||
}
|
||||
// TP-Data-Coding-Scheme
|
||||
if (pi & PDU_PI_DATA_CODING_SCHEME) {
|
||||
|
@ -3106,6 +3139,7 @@ let GsmPDUHelper = {
|
|||
sender: null, // M X X X X X
|
||||
recipient: null, // X X M X M M
|
||||
pid: null, // M O M O O M
|
||||
epid: null, // M O M O O M
|
||||
dcs: null, // M O M O O X
|
||||
body: null, // M O M O O O
|
||||
timestamp: null, // M X X X X X
|
||||
|
@ -3157,7 +3191,7 @@ let GsmPDUHelper = {
|
|||
let senderAddressLength = this.readHexOctet();
|
||||
msg.sender = this.readAddress(senderAddressLength);
|
||||
// - TP-Protocolo-Identifier -
|
||||
msg.pid = this.readHexOctet();
|
||||
this.readProtocolIndicator(msg);
|
||||
// - TP-Data-Coding-Scheme -
|
||||
msg.dcs = this.readHexOctet();
|
||||
// - TP-Service-Center-Time-Stamp -
|
||||
|
|
|
@ -2802,8 +2802,7 @@ WorkerPrivate::OperationCallback(JSContext* aCx)
|
|||
}
|
||||
|
||||
// Clean up before suspending.
|
||||
JS_FlushCaches(aCx);
|
||||
JS_GC(aCx);
|
||||
JS_GC(JS_GetRuntime(aCx));
|
||||
|
||||
while ((mayContinue = MayContinueRunning())) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
@ -3891,12 +3890,13 @@ WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking,
|
|||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
js::PrepareForFullGC(JS_GetRuntime(aCx));
|
||||
JSRuntime *rt = JS_GetRuntime(aCx);
|
||||
js::PrepareForFullGC(rt);
|
||||
if (aShrinking) {
|
||||
js::ShrinkingGC(aCx, js::gcreason::DOM_WORKER);
|
||||
js::ShrinkingGC(rt, js::gcreason::DOM_WORKER);
|
||||
}
|
||||
else {
|
||||
js::GCForReason(aCx, js::gcreason::DOM_WORKER);
|
||||
js::GCForReason(rt, js::gcreason::DOM_WORKER);
|
||||
}
|
||||
|
||||
if (aCollectChildren) {
|
||||
|
|
|
@ -1846,7 +1846,7 @@ public class GeckoAppShell
|
|||
}
|
||||
|
||||
// This is only used in Native Fennec.
|
||||
public static void setPreventPanning(final boolean aPreventPanning) { }
|
||||
public static void notifyDefaultPrevented(boolean defaultPrevented) { }
|
||||
|
||||
public static short getScreenOrientation() {
|
||||
return GeckoScreenOrientationListener.getInstance().getScreenOrientation();
|
||||
|
|
|
@ -107,6 +107,7 @@ static const char *sExtensionNames[] = {
|
|||
"GL_OES_rgb8_rgba8",
|
||||
"GL_ARB_robustness",
|
||||
"GL_EXT_robustness",
|
||||
"GL_ARB_sync",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -451,6 +452,32 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
|||
}
|
||||
}
|
||||
|
||||
if (IsExtensionSupported(ARB_sync)) {
|
||||
SymLoadStruct syncSymbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fFenceSync, { "FenceSync", nsnull } },
|
||||
{ (PRFuncPtr*) &mSymbols.fIsSync, { "IsSync", nsnull } },
|
||||
{ (PRFuncPtr*) &mSymbols.fDeleteSync, { "DeleteSync", nsnull } },
|
||||
{ (PRFuncPtr*) &mSymbols.fClientWaitSync, { "ClientWaitSync", nsnull } },
|
||||
{ (PRFuncPtr*) &mSymbols.fWaitSync, { "WaitSync", nsnull } },
|
||||
{ (PRFuncPtr*) &mSymbols.fGetInteger64v, { "GetInteger64v", nsnull } },
|
||||
{ (PRFuncPtr*) &mSymbols.fGetSynciv, { "GetSynciv", nsnull } },
|
||||
{ nsnull, { nsnull } },
|
||||
};
|
||||
|
||||
if (!LoadSymbols(&syncSymbols[0], trygl, prefix)) {
|
||||
NS_ERROR("GL supports ARB_sync without supplying its functions.");
|
||||
|
||||
MarkExtensionUnsupported(ARB_sync);
|
||||
mSymbols.fFenceSync = nsnull;
|
||||
mSymbols.fIsSync = nsnull;
|
||||
mSymbols.fDeleteSync = nsnull;
|
||||
mSymbols.fClientWaitSync = nsnull;
|
||||
mSymbols.fWaitSync = nsnull;
|
||||
mSymbols.fGetInteger64v = nsnull;
|
||||
mSymbols.fGetSynciv = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// Load developer symbols, don't fail if we can't find them.
|
||||
SymLoadStruct auxSymbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nsnull } },
|
||||
|
|
|
@ -1500,6 +1500,7 @@ public:
|
|||
OES_rgb8_rgba8,
|
||||
ARB_robustness,
|
||||
EXT_robustness,
|
||||
ARB_sync,
|
||||
Extensions_Max
|
||||
};
|
||||
|
||||
|
@ -2898,6 +2899,51 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
GLsync GLAPIENTRY fFenceSync(GLenum condition, GLbitfield flags) {
|
||||
BEFORE_GL_CALL;
|
||||
GLsync ret = mSymbols.fFenceSync(condition, flags);
|
||||
AFTER_GL_CALL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
realGLboolean GLAPIENTRY fIsSync(GLsync sync) {
|
||||
BEFORE_GL_CALL;
|
||||
realGLboolean ret = mSymbols.fIsSync(sync);
|
||||
AFTER_GL_CALL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteSync(GLsync sync) {
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fDeleteSync(sync);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
GLenum GLAPIENTRY fClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
|
||||
BEFORE_GL_CALL;
|
||||
GLenum ret = mSymbols.fClientWaitSync(sync, flags, timeout);
|
||||
AFTER_GL_CALL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GLAPIENTRY fWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fWaitSync(sync, flags, timeout);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGetInteger64v(GLenum pname, GLint64 *params) {
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fGetInteger64v(pname, params);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fGetSynciv(sync, pname, bufSize, length, values);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void THEBES_API CreatedProgram(GLContext *aOrigin, GLuint aName);
|
||||
void THEBES_API CreatedShader(GLContext *aOrigin, GLuint aName);
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#ifndef GLCONTEXTSYMBOLS_H_
|
||||
#define GLCONTEXTSYMBOLS_H_
|
||||
|
||||
#include "GLDefs.h"
|
||||
|
||||
/*
|
||||
* This file should only be included by GLContext.h, and should be
|
||||
* autogenerated in the future.
|
||||
|
@ -381,6 +383,24 @@ struct GLContextSymbols
|
|||
|
||||
typedef GLenum (GLAPIENTRY * PFNGLGETGRAPHICSRESETSTATUS) (void);
|
||||
PFNGLGETGRAPHICSRESETSTATUS fGetGraphicsResetStatus;
|
||||
|
||||
/*
|
||||
* ARB_sync extension
|
||||
*/
|
||||
typedef GLsync (GLAPIENTRY * PFNGLFENCESYNC) (GLenum condition, GLbitfield flags);
|
||||
PFNGLFENCESYNC fFenceSync;
|
||||
typedef realGLboolean (GLAPIENTRY * PFNGLISSYNC) (GLsync sync);
|
||||
PFNGLISSYNC fIsSync;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETESYNC) (GLsync sync);
|
||||
PFNGLDELETESYNC fDeleteSync;
|
||||
typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||
PFNGLCLIENTWAITSYNC fClientWaitSync;
|
||||
typedef void (GLAPIENTRY * PFNGLWAITSYNC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||
PFNGLWAITSYNC fWaitSync;
|
||||
typedef void (GLAPIENTRY * PFNGLGETINTEGER64V) (GLenum pname, GLint64 *params);
|
||||
PFNGLGETINTEGER64V fGetInteger64v;
|
||||
typedef void (GLAPIENTRY * PFNGLGETSYNCIV) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
|
||||
PFNGLGETSYNCIV fGetSynciv;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#if !defined(LOCALGL_H_)
|
||||
|
||||
#define LOCALGL_H_
|
||||
|
||||
#if !defined(__gltypes_h_) && !defined(__gl_h_)
|
||||
|
@ -72,6 +71,14 @@ typedef ptrdiff_t GLintptr;
|
|||
|
||||
#endif /* #if !defined(__gltypes_h_) && !defined(__gl_h_) */
|
||||
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
// ARB_sync
|
||||
typedef struct __GLsync *GLsync;
|
||||
typedef int64_t GLint64;
|
||||
typedef uint64_t GLuint64;
|
||||
|
||||
|
||||
#ifndef GLAPIENTRY
|
||||
# ifdef WIN32
|
||||
# define GLAPIENTRY APIENTRY
|
||||
|
@ -3032,6 +3039,23 @@ typedef ptrdiff_t GLintptr;
|
|||
#define LOCAL_GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
|
||||
#define LOCAL_GL_WIN_swap_hint 1
|
||||
|
||||
// ARB_sync
|
||||
#define LOCAL_GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
|
||||
#define LOCAL_GL_OBJECT_TYPE 0x9112
|
||||
#define LOCAL_GL_SYNC_CONDITION 0x9113
|
||||
#define LOCAL_GL_SYNC_STATUS 0x9114
|
||||
#define LOCAL_GL_SYNC_FLAGS 0x9115
|
||||
#define LOCAL_GL_SYNC_FENCE 0x9116
|
||||
#define LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
|
||||
#define LOCAL_GL_UNSIGNALED 0x9118
|
||||
#define LOCAL_GL_SIGNALED 0x9119
|
||||
#define LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
|
||||
#define LOCAL_GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
|
||||
#define LOCAL_GL_ALREADY_SIGNALED 0x911A
|
||||
#define LOCAL_GL_TIMEOUT_EXPIRED 0x911B
|
||||
#define LOCAL_GL_CONDITION_SATISFIED 0x911C
|
||||
#define LOCAL_GL_WAIT_FAILED 0x911D
|
||||
|
||||
#define LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
|
||||
#define LOCAL_GL_MAX_VARYING_VECTORS 0x8DFC
|
||||
#define LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
|
||||
|
|
|
@ -375,84 +375,78 @@ gfxDWriteFontEntry::ReadCMAP()
|
|||
nsresult rv;
|
||||
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
if (mCmapInitialized)
|
||||
if (mCharacterMap) {
|
||||
return NS_OK;
|
||||
mCmapInitialized = true;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
// if loading via GDI, just use GetFontTable
|
||||
if (mFont && gfxDWriteFontList::PlatformFontList()->UseGDIFontTableAccess()) {
|
||||
const PRUint32 kCmapTag = TRUETYPE_TAG('c','m','a','p');
|
||||
AutoFallibleTArray<PRUint8,16384> buffer;
|
||||
PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
nsresult rv;
|
||||
|
||||
if (GetFontTable(kCmapTag, buffer) != NS_OK)
|
||||
return NS_ERROR_FAILURE;
|
||||
PRUint8 *cmap = buffer.Elements();
|
||||
AutoFallibleTArray<PRUint8,16384> cmap;
|
||||
rv = GetFontTable(kCMAP, cmap);
|
||||
|
||||
bool unicodeFont = false, symbolFont = false;
|
||||
rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(),
|
||||
mCharacterMap, mUVSOffset,
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
||||
NS_ConvertUTF16toUTF8(mName).get(),
|
||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
||||
if (LOG_CMAPDATA_ENABLED()) {
|
||||
char prefix[256];
|
||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||
NS_ConvertUTF16toUTF8(mName).get());
|
||||
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
|
||||
}
|
||||
#endif
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
} else {
|
||||
// loading using dwrite, don't use GetFontTable to avoid copy
|
||||
nsRefPtr<IDWriteFontFace> fontFace;
|
||||
rv = CreateFontFace(getter_AddRefs(fontFace));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
const PRUint32 kCmapTag = DWRITE_MAKE_OPENTYPE_TAG('c', 'm', 'a', 'p');
|
||||
PRUint8 *tableData;
|
||||
PRUint32 len;
|
||||
void *tableContext = NULL;
|
||||
BOOL exists;
|
||||
hr = fontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('c', 'm', 'a', 'p'),
|
||||
(const void**)&tableData,
|
||||
&len,
|
||||
&tableContext,
|
||||
&exists);
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
hr = fontFace->TryGetFontTable(kCmapTag, (const void**)&tableData,
|
||||
&len, &tableContext, &exists);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
bool isSymbol = fontFace->IsSymbolFont();
|
||||
bool isUnicode = true;
|
||||
if (exists) {
|
||||
rv = gfxFontUtils::ReadCMAP(tableData,
|
||||
len,
|
||||
mCharacterMap,
|
||||
mUVSOffset,
|
||||
isUnicode,
|
||||
rv = gfxFontUtils::ReadCMAP(tableData, len, *charmap,
|
||||
mUVSOffset, isUnicode,
|
||||
isSymbol);
|
||||
}
|
||||
fontFace->ReleaseFontTable(tableContext);
|
||||
} else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
if (mHasCmapTable) {
|
||||
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
|
||||
mCharacterMap = pfl->FindCharMap(charmap);
|
||||
} else {
|
||||
// if error occurred, initialize to null cmap
|
||||
mCharacterMap = new gfxCharacterMap();
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n",
|
||||
NS_ConvertUTF16toUTF8(mName).get(),
|
||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
||||
charmap->SizeOfIncludingThis(moz_malloc_size_of),
|
||||
charmap->mHash, mCharacterMap == charmap ? " new" : ""));
|
||||
if (LOG_CMAPDATA_ENABLED()) {
|
||||
char prefix[256];
|
||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||
NS_ConvertUTF16toUTF8(mName).get());
|
||||
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
|
||||
charmap->Dump(prefix, eGfxLog_cmapdata);
|
||||
}
|
||||
#endif
|
||||
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -343,12 +343,11 @@ FT2FontEntry::CairoFontFace()
|
|||
nsresult
|
||||
FT2FontEntry::ReadCMAP()
|
||||
{
|
||||
if (mCmapInitialized) {
|
||||
if (mCharacterMap) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
mCmapInitialized = true;
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
AutoFallibleTArray<PRUint8,16384> buffer;
|
||||
nsresult rv = GetFontTable(TTAG_cmap, buffer);
|
||||
|
@ -357,11 +356,18 @@ FT2FontEntry::ReadCMAP()
|
|||
bool unicodeFont;
|
||||
bool symbolFont;
|
||||
rv = gfxFontUtils::ReadCMAP(buffer.Elements(), buffer.Length(),
|
||||
mCharacterMap, mUVSOffset,
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
}
|
||||
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
if (mHasCmapTable) {
|
||||
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
|
||||
mCharacterMap = pfl->FindCharMap(charmap);
|
||||
} else {
|
||||
// if error occurred, initialize to null cmap
|
||||
mCharacterMap = new gfxCharacterMap();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,16 @@ static PRUint32 gGlyphExtentsSetupLazyTight = 0;
|
|||
static PRUint32 gGlyphExtentsSetupFallBackToTight = 0;
|
||||
#endif
|
||||
|
||||
void
|
||||
gfxCharacterMap::NotifyReleased()
|
||||
{
|
||||
gfxPlatformFontList *fontlist = gfxPlatformFontList::PlatformFontList();
|
||||
if (mShared) {
|
||||
fontlist->RemoveCmap(this);
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
|
||||
gfxFontEntry::~gfxFontEntry()
|
||||
{
|
||||
delete mUserFontData;
|
||||
|
@ -115,18 +125,20 @@ bool gfxFontEntry::IsSymbolFont()
|
|||
|
||||
bool gfxFontEntry::TestCharacterMap(PRUint32 aCh)
|
||||
{
|
||||
if (!mCmapInitialized) {
|
||||
if (!mCharacterMap) {
|
||||
ReadCMAP();
|
||||
NS_ASSERTION(mCharacterMap, "failed to initialize character map");
|
||||
}
|
||||
return mCharacterMap.test(aCh);
|
||||
return mCharacterMap->test(aCh);
|
||||
}
|
||||
|
||||
nsresult gfxFontEntry::InitializeUVSMap()
|
||||
{
|
||||
// mUVSOffset will not be initialized
|
||||
// until cmap is initialized.
|
||||
if (!mCmapInitialized) {
|
||||
if (!mCharacterMap) {
|
||||
ReadCMAP();
|
||||
NS_ASSERTION(mCharacterMap, "failed to initialize character map");
|
||||
}
|
||||
|
||||
if (!mUVSOffset) {
|
||||
|
@ -170,7 +182,8 @@ PRUint16 gfxFontEntry::GetUVSGlyph(PRUint32 aCh, PRUint32 aVS)
|
|||
|
||||
nsresult gfxFontEntry::ReadCMAP()
|
||||
{
|
||||
mCmapInitialized = true;
|
||||
NS_ASSERTION(false, "using default no-op implementation of ReadCMAP");
|
||||
mCharacterMap = new gfxCharacterMap();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -433,7 +446,12 @@ gfxFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
|||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
// cmaps are shared so only non-shared cmaps are included here
|
||||
if (mCharacterMap && mCharacterMap->mBuildOnTheFly) {
|
||||
aSizes->mCharMapsSize +=
|
||||
mCharacterMap->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
aSizes->mFontTableCacheSize +=
|
||||
mFontTableCache.SizeOfExcludingThis(
|
||||
FontTableHashEntry::SizeOfEntryExcludingThis,
|
||||
|
@ -770,7 +788,7 @@ CalcStyleMatch(gfxFontEntry *aFontEntry, const gfxFontStyle *aStyle)
|
|||
void
|
||||
gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData)
|
||||
{
|
||||
if (mCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) {
|
||||
if (mFamilyCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) {
|
||||
// none of the faces in the family support the required char,
|
||||
// so bail out immediately
|
||||
return;
|
||||
|
@ -1028,7 +1046,8 @@ gfxFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
|||
{
|
||||
aSizes->mFontListSize +=
|
||||
mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
|
||||
aSizes->mCharMapsSize +=
|
||||
mFamilyCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mAvailableFonts.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
@ -3647,7 +3666,9 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
|
|||
|
||||
// check other faces of the family
|
||||
gfxFontFamily *family = font->GetFontEntry()->Family();
|
||||
if (family && family->TestCharacterMap(aCh)) {
|
||||
if (family && !font->GetFontEntry()->mIsProxy &&
|
||||
family->TestCharacterMap(aCh))
|
||||
{
|
||||
GlobalFontMatch matchData(aCh, aRunScript, &mStyle);
|
||||
family->SearchAllFontsForChar(&matchData);
|
||||
gfxFontEntry *fe = matchData.mBestMatch;
|
||||
|
|
|
@ -198,6 +198,56 @@ struct THEBES_API gfxFontStyle {
|
|||
static PRUint32 ParseFontLanguageOverride(const nsString& aLangTag);
|
||||
};
|
||||
|
||||
class gfxCharacterMap : public gfxSparseBitSet {
|
||||
public:
|
||||
nsrefcnt AddRef() {
|
||||
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
|
||||
++mRefCnt;
|
||||
NS_LOG_ADDREF(this, mRefCnt, "gfxCharacterMap", sizeof(*this));
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
nsrefcnt Release() {
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||
--mRefCnt;
|
||||
NS_LOG_RELEASE(this, mRefCnt, "gfxCharacterMap");
|
||||
if (mRefCnt == 0) {
|
||||
NotifyReleased();
|
||||
// |this| has been deleted.
|
||||
return 0;
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
gfxCharacterMap() :
|
||||
mHash(0), mBuildOnTheFly(false), mShared(false)
|
||||
{ }
|
||||
|
||||
void CalcHash() { mHash = GetChecksum(); }
|
||||
|
||||
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
||||
return gfxSparseBitSet::SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// hash of the cmap bitvector
|
||||
PRUint32 mHash;
|
||||
|
||||
// if cmap is built on the fly it's never shared
|
||||
bool mBuildOnTheFly;
|
||||
|
||||
// cmap is shared globally
|
||||
bool mShared;
|
||||
|
||||
protected:
|
||||
void NotifyReleased();
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
|
||||
private:
|
||||
gfxCharacterMap(const gfxCharacterMap&);
|
||||
gfxCharacterMap& operator=(const gfxCharacterMap&);
|
||||
};
|
||||
|
||||
class gfxFontEntry {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(gfxFontEntry)
|
||||
|
@ -216,7 +266,6 @@ public:
|
|||
mCheckedForGraphiteTables(false),
|
||||
#endif
|
||||
mHasCmapTable(false),
|
||||
mCmapInitialized(false),
|
||||
mUVSOffset(0), mUVSData(nsnull),
|
||||
mUserFontData(nsnull),
|
||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||
|
@ -259,16 +308,17 @@ public:
|
|||
#endif
|
||||
|
||||
inline bool HasCmapTable() {
|
||||
if (!mCmapInitialized) {
|
||||
if (!mCharacterMap) {
|
||||
ReadCMAP();
|
||||
NS_ASSERTION(mCharacterMap, "failed to initialize character map");
|
||||
}
|
||||
return mHasCmapTable;
|
||||
}
|
||||
|
||||
inline bool HasCharacter(PRUint32 ch) {
|
||||
if (mCharacterMap.test(ch))
|
||||
if (mCharacterMap && mCharacterMap->test(ch)) {
|
||||
return true;
|
||||
|
||||
}
|
||||
return TestCharacterMap(ch);
|
||||
}
|
||||
|
||||
|
@ -344,8 +394,7 @@ public:
|
|||
bool mCheckedForGraphiteTables;
|
||||
#endif
|
||||
bool mHasCmapTable;
|
||||
bool mCmapInitialized;
|
||||
gfxSparseBitSet mCharacterMap;
|
||||
nsRefPtr<gfxCharacterMap> mCharacterMap;
|
||||
PRUint32 mUVSOffset;
|
||||
nsAutoArrayPtr<PRUint8> mUVSData;
|
||||
gfxUserFontData* mUserFontData;
|
||||
|
@ -375,7 +424,6 @@ protected:
|
|||
mCheckedForGraphiteTables(false),
|
||||
#endif
|
||||
mHasCmapTable(false),
|
||||
mCmapInitialized(false),
|
||||
mUVSOffset(0), mUVSData(nsnull),
|
||||
mUserFontData(nsnull),
|
||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||
|
@ -529,7 +577,7 @@ public:
|
|||
mHasStyles(false),
|
||||
mIsSimpleFamily(false),
|
||||
mIsBadUnderlineFamily(false),
|
||||
mCharacterMapInitialized(false)
|
||||
mFamilyCharacterMapInitialized(false)
|
||||
{ }
|
||||
|
||||
virtual ~gfxFontFamily() {
|
||||
|
@ -607,26 +655,27 @@ public:
|
|||
PRUint32 i, numFonts = mAvailableFonts.Length();
|
||||
for (i = 0; i < numFonts; i++) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (!fe) {
|
||||
// don't try to load cmaps for downloadable fonts not yet loaded
|
||||
if (!fe || fe->mIsProxy) {
|
||||
continue;
|
||||
}
|
||||
fe->ReadCMAP();
|
||||
mCharacterMap.Union(fe->mCharacterMap);
|
||||
mFamilyCharacterMap.Union(*(fe->mCharacterMap));
|
||||
}
|
||||
mCharacterMap.Compact();
|
||||
mCharacterMapInitialized = true;
|
||||
mFamilyCharacterMap.Compact();
|
||||
mFamilyCharacterMapInitialized = true;
|
||||
}
|
||||
|
||||
bool TestCharacterMap(PRUint32 aCh) {
|
||||
if (!mCharacterMapInitialized) {
|
||||
if (!mFamilyCharacterMapInitialized) {
|
||||
ReadAllCMAPs();
|
||||
}
|
||||
return mCharacterMap.test(aCh);
|
||||
return mFamilyCharacterMap.test(aCh);
|
||||
}
|
||||
|
||||
void ResetCharacterMap() {
|
||||
mCharacterMap.reset();
|
||||
mCharacterMapInitialized = false;
|
||||
mFamilyCharacterMap.reset();
|
||||
mFamilyCharacterMapInitialized = false;
|
||||
}
|
||||
|
||||
// mark this family as being in the "bad" underline offset blacklist
|
||||
|
@ -675,14 +724,14 @@ protected:
|
|||
|
||||
nsString mName;
|
||||
nsTArray<nsRefPtr<gfxFontEntry> > mAvailableFonts;
|
||||
gfxSparseBitSet mCharacterMap;
|
||||
bool mOtherFamilyNamesInitialized;
|
||||
bool mHasOtherFamilyNames;
|
||||
bool mFaceNamesInitialized;
|
||||
bool mHasStyles;
|
||||
bool mIsSimpleFamily;
|
||||
bool mIsBadUnderlineFamily;
|
||||
bool mCharacterMapInitialized;
|
||||
gfxSparseBitSet mFamilyCharacterMap;
|
||||
bool mOtherFamilyNamesInitialized : 1;
|
||||
bool mHasOtherFamilyNames : 1;
|
||||
bool mFaceNamesInitialized : 1;
|
||||
bool mHasStyles : 1;
|
||||
bool mIsSimpleFamily : 1;
|
||||
bool mIsBadUnderlineFamily : 1;
|
||||
bool mFamilyCharacterMapInitialized : 1;
|
||||
|
||||
enum {
|
||||
// for "simple" families, the faces are stored in mAvailableFonts
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
#include "nsAutoPtr.h"
|
||||
#include "nsIStreamBufferAccess.h"
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
/* Bug 341128 - w32api defines min/max which causes problems with <bitset> */
|
||||
#ifdef __MINGW32__
|
||||
#undef min
|
||||
|
@ -87,6 +89,28 @@ public:
|
|||
mBlocks[i] = new Block(*block);
|
||||
}
|
||||
}
|
||||
|
||||
bool Equals(const gfxSparseBitSet *aOther) const {
|
||||
if (mBlocks.Length() != aOther->mBlocks.Length()) {
|
||||
return false;
|
||||
}
|
||||
size_t n = mBlocks.Length();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
const Block *b1 = mBlocks[i];
|
||||
const Block *b2 = aOther->mBlocks[i];
|
||||
if (!b1 != !b2) {
|
||||
return false;
|
||||
}
|
||||
if (!b1) {
|
||||
continue;
|
||||
}
|
||||
if (memcmp(&b1->mBits, &b2->mBits, BLOCK_SIZE) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test(PRUint32 aIndex) const {
|
||||
NS_ASSERTION(mBlocks.DebugGetHeader(), "mHdr is null, this is bad");
|
||||
PRUint32 blockIndex = aIndex/BLOCK_SIZE_BITS;
|
||||
|
@ -321,6 +345,18 @@ public:
|
|||
mBlocks.Compact();
|
||||
}
|
||||
|
||||
PRUint32 GetChecksum() const {
|
||||
PRUint32 check = adler32(0, Z_NULL, 0);
|
||||
for (PRUint32 i = 0; i < mBlocks.Length(); i++) {
|
||||
if (mBlocks[i]) {
|
||||
const Block *block = mBlocks[i];
|
||||
check = adler32(check, (PRUint8*) (&i), 4);
|
||||
check = adler32(check, (PRUint8*) block, sizeof(Block));
|
||||
}
|
||||
}
|
||||
return check;
|
||||
}
|
||||
|
||||
private:
|
||||
nsTArray< nsAutoPtr<Block> > mBlocks;
|
||||
};
|
||||
|
|
|
@ -201,7 +201,7 @@ GDIFontEntry::GDIFontEntry(const nsAString& aFaceName,
|
|||
: gfxFontEntry(aFaceName),
|
||||
mWindowsFamily(0), mWindowsPitch(0),
|
||||
mFontType(aFontType),
|
||||
mForceGDI(false), mUnknownCMAP(false),
|
||||
mForceGDI(false),
|
||||
mCharset(), mUnicodeRanges()
|
||||
{
|
||||
mUserFontData = aUserFontData;
|
||||
|
@ -218,43 +218,62 @@ GDIFontEntry::GDIFontEntry(const nsAString& aFaceName,
|
|||
nsresult
|
||||
GDIFontEntry::ReadCMAP()
|
||||
{
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
if (mCharacterMap) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// skip non-SFNT fonts completely
|
||||
if (mFontType != GFX_FONT_TYPE_PS_OPENTYPE &&
|
||||
mFontType != GFX_FONT_TYPE_TT_OPENTYPE &&
|
||||
mFontType != GFX_FONT_TYPE_TRUETYPE)
|
||||
{
|
||||
mCharacterMap = new gfxCharacterMap();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
if (mCmapInitialized)
|
||||
return NS_OK;
|
||||
mCmapInitialized = true;
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
const PRUint32 kCmapTag = TRUETYPE_TAG('c','m','a','p');
|
||||
AutoFallibleTArray<PRUint8,16384> buffer;
|
||||
if (GetFontTable(kCmapTag, buffer) != NS_OK)
|
||||
return NS_ERROR_FAILURE;
|
||||
PRUint8 *cmap = buffer.Elements();
|
||||
PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
nsresult rv;
|
||||
|
||||
bool unicodeFont = false, symbolFont = false;
|
||||
nsresult rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(),
|
||||
mCharacterMap, mUVSOffset,
|
||||
AutoFallibleTArray<PRUint8,16384> cmap;
|
||||
rv = GetFontTable(kCMAP, cmap);
|
||||
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
}
|
||||
mSymbolFont = symbolFont;
|
||||
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
if (mHasCmapTable) {
|
||||
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
|
||||
mCharacterMap = pfl->FindCharMap(charmap);
|
||||
} else {
|
||||
// if error occurred, initialize to null cmap
|
||||
mCharacterMap = new gfxCharacterMap();
|
||||
// For fonts where we failed to read the character map,
|
||||
// we can take a slow path to look up glyphs character by character
|
||||
mCharacterMap->mBuildOnTheFly = true;
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n",
|
||||
NS_ConvertUTF16toUTF8(mName).get(),
|
||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
||||
charmap->SizeOfIncludingThis(moz_malloc_size_of),
|
||||
charmap->mHash, mCharacterMap == charmap ? " new" : ""));
|
||||
if (LOG_CMAPDATA_ENABLED()) {
|
||||
char prefix[256];
|
||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||
NS_ConvertUTF16toUTF8(mName).get());
|
||||
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
|
||||
charmap->Dump(prefix, eGfxLog_cmapdata);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -346,13 +365,12 @@ GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
|
|||
bool
|
||||
GDIFontEntry::TestCharacterMap(PRUint32 aCh)
|
||||
{
|
||||
if (ReadCMAP() != NS_OK) {
|
||||
// For fonts where we failed to read the character map,
|
||||
// we can take a slow path to look up glyphs character by character
|
||||
mUnknownCMAP = true;
|
||||
if (!mCharacterMap) {
|
||||
nsresult rv = ReadCMAP();
|
||||
NS_ASSERTION(mCharacterMap, "failed to initialize a character map");
|
||||
}
|
||||
|
||||
if (mUnknownCMAP) {
|
||||
if (mCharacterMap->mBuildOnTheFly) {
|
||||
if (aCh > 0xFFFF)
|
||||
return false;
|
||||
|
||||
|
@ -404,12 +422,12 @@ GDIFontEntry::TestCharacterMap(PRUint32 aCh)
|
|||
ReleaseDC(NULL, dc);
|
||||
|
||||
if (hasGlyph) {
|
||||
mCharacterMap.set(aCh);
|
||||
mCharacterMap->set(aCh);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// font had a cmap so simply check that
|
||||
return mCharacterMap.test(aCh);
|
||||
return mCharacterMap->test(aCh);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -293,7 +293,6 @@ public:
|
|||
|
||||
gfxWindowsFontType mFontType;
|
||||
bool mForceGDI : 1;
|
||||
bool mUnknownCMAP : 1;
|
||||
|
||||
gfxSparseBitSet mCharset;
|
||||
gfxSparseBitSet mUnicodeRanges;
|
||||
|
|
|
@ -189,33 +189,27 @@ nsresult
|
|||
MacOSFontEntry::ReadCMAP()
|
||||
{
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
if (mCmapInitialized) {
|
||||
if (mCharacterMap) {
|
||||
return NS_OK;
|
||||
}
|
||||
mCmapInitialized = true;
|
||||
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
nsresult rv;
|
||||
|
||||
AutoFallibleTArray<PRUint8,16384> cmap;
|
||||
if (GetFontTable(kCMAP, cmap) != NS_OK) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = GetFontTable(kCMAP, cmap);
|
||||
|
||||
bool unicodeFont, symbolFont; // currently ignored
|
||||
nsresult rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||
mCharacterMap, mUVSOffset,
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
if (NS_FAILED(rv)) {
|
||||
mCharacterMap.reset();
|
||||
return rv;
|
||||
}
|
||||
mHasCmapTable = true;
|
||||
|
||||
CGFontRef fontRef = GetFontRef();
|
||||
if (!fontRef) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// for layout support, check for the presence of mort/morx and/or
|
||||
// opentype layout tables
|
||||
bool hasAATLayout = HasFontTable(TRUETYPE_TAG('m','o','r','x')) ||
|
||||
|
@ -234,7 +228,7 @@ MacOSFontEntry::ReadCMAP()
|
|||
eComplexScript whichScript = gScriptsThatRequireShaping[s].script;
|
||||
|
||||
// check to see if the cmap includes complex script codepoints
|
||||
if (mCharacterMap.TestRange(gScriptsThatRequireShaping[s].rangeStart,
|
||||
if (charmap->TestRange(gScriptsThatRequireShaping[s].rangeStart,
|
||||
gScriptsThatRequireShaping[s].rangeEnd)) {
|
||||
bool omitRange = true;
|
||||
|
||||
|
@ -261,21 +255,32 @@ MacOSFontEntry::ReadCMAP()
|
|||
}
|
||||
|
||||
if (omitRange) {
|
||||
mCharacterMap.ClearRange(gScriptsThatRequireShaping[s].rangeStart,
|
||||
charmap->ClearRange(gScriptsThatRequireShaping[s].rangeStart,
|
||||
gScriptsThatRequireShaping[s].rangeEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
if (mHasCmapTable) {
|
||||
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
|
||||
mCharacterMap = pfl->FindCharMap(charmap);
|
||||
} else {
|
||||
// if error occurred, initialize to null cmap
|
||||
mCharacterMap = new gfxCharacterMap();
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n",
|
||||
NS_ConvertUTF16toUTF8(mName).get(),
|
||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
||||
charmap->SizeOfIncludingThis(moz_malloc_size_of),
|
||||
charmap->mHash, mCharacterMap == charmap ? " new" : ""));
|
||||
if (LOG_CMAPDATA_ENABLED()) {
|
||||
char prefix[256];
|
||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||
NS_ConvertUTF16toUTF8(mName).get());
|
||||
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
|
||||
charmap->Dump(prefix, eGfxLog_cmapdata);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -213,10 +213,13 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
|
|||
gFontListPrefObserver = new gfxFontListPrefObserver();
|
||||
NS_ADDREF(gFontListPrefObserver);
|
||||
Preferences::AddStrongObservers(gFontListPrefObserver, kObservedPrefs);
|
||||
|
||||
mSharedCmaps.Init(16);
|
||||
}
|
||||
|
||||
gfxPlatformFontList::~gfxPlatformFontList()
|
||||
{
|
||||
mSharedCmaps.Clear();
|
||||
NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer");
|
||||
Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs);
|
||||
NS_RELEASE(gFontListPrefObserver);
|
||||
|
@ -714,6 +717,41 @@ gfxPlatformFontList::GetStandardFamilyName(const nsAString& aFontName, nsAString
|
|||
return !aFamilyName.IsEmpty();
|
||||
}
|
||||
|
||||
gfxCharacterMap*
|
||||
gfxPlatformFontList::FindCharMap(gfxCharacterMap *aCmap)
|
||||
{
|
||||
aCmap->CalcHash();
|
||||
gfxCharacterMap *cmap = AddCmap(aCmap);
|
||||
cmap->mShared = true;
|
||||
return cmap;
|
||||
}
|
||||
|
||||
// add a cmap to the shared cmap set
|
||||
gfxCharacterMap*
|
||||
gfxPlatformFontList::AddCmap(const gfxCharacterMap* aCharMap)
|
||||
{
|
||||
CharMapHashKey *found =
|
||||
mSharedCmaps.PutEntry(const_cast<gfxCharacterMap*>(aCharMap));
|
||||
return found->GetKey();
|
||||
}
|
||||
|
||||
// remove the cmap from the shared cmap set
|
||||
void
|
||||
gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap)
|
||||
{
|
||||
// skip lookups during teardown
|
||||
if (mSharedCmaps.Count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// cmap needs to match the entry *and* be the same ptr before removing
|
||||
CharMapHashKey *found =
|
||||
mSharedCmaps.GetEntry(const_cast<gfxCharacterMap*>(aCharMap));
|
||||
if (found && found->GetKey() == aCharMap) {
|
||||
mSharedCmaps.RemoveEntry(const_cast<gfxCharacterMap*>(aCharMap));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::InitLoader()
|
||||
{
|
||||
|
@ -830,6 +868,21 @@ SizeOfStringEntryExcludingThis(nsStringHashKey* aHashEntry,
|
|||
return aHashEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfSharedCmapExcludingThis(CharMapHashKey* aHashEntry,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
|
||||
|
||||
PRUint32 size = aHashEntry->GetKey()->SizeOfIncludingThis(aMallocSizeOf);
|
||||
sizes->mCharMapsSize += size;
|
||||
|
||||
// we return zero here because the measurements have been added directly
|
||||
// to the relevant fields of the FontListSizes record
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
|
@ -865,6 +918,10 @@ gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
|||
aSizes->mFontListSize +=
|
||||
mBadUnderlineFamilyNames.SizeOfExcludingThis(SizeOfStringEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mSharedCmaps.SizeOfExcludingThis(SizeOfSharedCmapExcludingThis,
|
||||
aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -50,6 +50,53 @@
|
|||
#include "nsIMemoryReporter.h"
|
||||
#include "mozilla/FunctionTimer.h"
|
||||
|
||||
class CharMapHashKey : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
typedef gfxCharacterMap* KeyType;
|
||||
typedef const gfxCharacterMap* KeyTypePointer;
|
||||
|
||||
CharMapHashKey(const gfxCharacterMap *aCharMap) :
|
||||
mCharMap(const_cast<gfxCharacterMap*>(aCharMap))
|
||||
{
|
||||
MOZ_COUNT_CTOR(CharMapHashKey);
|
||||
}
|
||||
CharMapHashKey(const CharMapHashKey& toCopy) :
|
||||
mCharMap(toCopy.mCharMap)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CharMapHashKey);
|
||||
}
|
||||
~CharMapHashKey()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CharMapHashKey);
|
||||
}
|
||||
|
||||
gfxCharacterMap* GetKey() const { return mCharMap; }
|
||||
|
||||
bool KeyEquals(const gfxCharacterMap *aCharMap) const {
|
||||
NS_ASSERTION(!aCharMap->mBuildOnTheFly && !mCharMap->mBuildOnTheFly,
|
||||
"custom cmap used in shared cmap hashtable");
|
||||
// cmaps built on the fly never match
|
||||
if (aCharMap->mHash != mCharMap->mHash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return mCharMap->Equals(aCharMap);
|
||||
}
|
||||
|
||||
static const gfxCharacterMap* KeyToPointer(gfxCharacterMap *aCharMap) {
|
||||
return aCharMap;
|
||||
}
|
||||
static PLDHashNumber HashKey(const gfxCharacterMap *aCharMap) {
|
||||
return aCharMap->mHash;
|
||||
}
|
||||
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
protected:
|
||||
gfxCharacterMap *mCharMap;
|
||||
};
|
||||
|
||||
// gfxPlatformFontList is an abstract class for the global font list on the system;
|
||||
// concrete subclasses for each platform implement the actual interface to the system fonts.
|
||||
// This class exists because we cannot rely on the platform font-finding APIs to behave
|
||||
|
@ -155,6 +202,16 @@ public:
|
|||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
// search for existing cmap that matches the input
|
||||
// return the input if no match is found
|
||||
gfxCharacterMap* FindCharMap(gfxCharacterMap *aCmap);
|
||||
|
||||
// add a cmap to the shared cmap set
|
||||
gfxCharacterMap* AddCmap(const gfxCharacterMap *aCharMap);
|
||||
|
||||
// remove the cmap from the shared cmap set
|
||||
void RemoveCmap(const gfxCharacterMap *aCharMap);
|
||||
|
||||
protected:
|
||||
class MemoryReporter
|
||||
: public nsIMemoryMultiReporter
|
||||
|
@ -264,6 +321,10 @@ protected:
|
|||
|
||||
nsTHashtable<nsStringHashKey> mBadUnderlineFamilyNames;
|
||||
|
||||
// character map data shared across families
|
||||
// contains weak ptrs to cmaps shared by font entry objects
|
||||
nsTHashtable<CharMapHashKey> mSharedCmaps;
|
||||
|
||||
// data used as part of the font cmap loading process
|
||||
nsTArray<nsRefPtr<gfxFontFamily> > mFontFamiliesToLoad;
|
||||
PRUint32 mStartIndex;
|
||||
|
|
|
@ -115,8 +115,8 @@ include $(topsrcdir)/config/rules.mk
|
|||
# NB: the IPDL compiler manages .ipdl-->.h/.cpp dependencies itself,
|
||||
# which is why we don't have explicit .h/.cpp targets here
|
||||
export:: $(ALL_IPDLSRCS)
|
||||
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
|
||||
-I$(topsrcdir)/other-licenses/ply \
|
||||
$(PYTHON_PATH) \
|
||||
$(PLY_INCLUDE) \
|
||||
$(srcdir)/ipdl.py \
|
||||
--outheaders-dir=_ipdlheaders \
|
||||
--outcpp-dir=. \
|
||||
|
|
|
@ -49,7 +49,7 @@ check::
|
|||
@$(PYTHON) $(srcdir)/runtests.py \
|
||||
$(srcdir)/ok $(srcdir)/error \
|
||||
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
|
||||
-I$(topsrcdir)/other-licenses/ply \
|
||||
$(PLY_INCLUDE) \
|
||||
$(topsrcdir)/ipc/ipdl/ipdl.py \
|
||||
OKTESTS $(OKTESTS) \
|
||||
ERRORTESTS $(ERRORTESTS)
|
||||
|
|
|
@ -278,6 +278,15 @@ RilClient::OnFileCanReadWithoutBlocking(int fd)
|
|||
mIncoming = new RilRawData();
|
||||
ssize_t ret = read(fd, mIncoming->mData, RilRawData::MAX_DATA_SIZE);
|
||||
if (ret <= 0) {
|
||||
if (ret == -1) {
|
||||
if (errno == EINTR) {
|
||||
continue; // retry system call when interrupted
|
||||
}
|
||||
else if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return; // no data available: return and re-poll
|
||||
}
|
||||
// else fall through to error handling on other errno's
|
||||
}
|
||||
LOG("Cannot read from network, error %d\n", ret);
|
||||
// At this point, assume that we can't actually access
|
||||
// the socket anymore, and start a reconnect loop.
|
||||
|
|
|
@ -409,9 +409,9 @@ GC(JSContext *cx,
|
|||
unsigned argc,
|
||||
jsval *vp)
|
||||
{
|
||||
JS_GC(cx);
|
||||
#ifdef JS_GCMETER
|
||||
JSRuntime *rt = JS_GetRuntime(cx);
|
||||
JS_GC(rt);
|
||||
#ifdef JS_GCMETER
|
||||
js_DumpGCStats(rt, stdout);
|
||||
#endif
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
|
@ -1054,16 +1054,15 @@ XPCShellEnvironment::~XPCShellEnvironment()
|
|||
}
|
||||
mGlobalHolder.Release();
|
||||
|
||||
JS_GC(mCx);
|
||||
JSRuntime *rt = JS_GetRuntime(mCx);
|
||||
JS_GC(rt);
|
||||
|
||||
mCxStack = nsnull;
|
||||
|
||||
if (mJSPrincipals) {
|
||||
JS_DropPrincipals(JS_GetRuntime(mCx), mJSPrincipals);
|
||||
JS_DropPrincipals(rt, mJSPrincipals);
|
||||
}
|
||||
|
||||
JSRuntime* rt = gOldContextCallback ? JS_GetRuntime(mCx) : NULL;
|
||||
|
||||
JS_EndRequest(mCx);
|
||||
JS_DestroyContext(mCx);
|
||||
|
||||
|
|
|
@ -2817,8 +2817,8 @@ NS_IMETHODIMP
|
|||
jsdService::GC (void)
|
||||
{
|
||||
ASSERT_VALID_CONTEXT;
|
||||
JSContext *cx = JSD_GetDefaultJSContext (mCx);
|
||||
JS_GC(cx);
|
||||
JSRuntime *rt = JSD_GetJSRuntime (mCx);
|
||||
JS_GC(rt);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,6 +98,13 @@ JSD_GetDefaultJSContext(JSDContext* jsdc)
|
|||
return jsdc->dumbContext;
|
||||
}
|
||||
|
||||
JSD_PUBLIC_API(JSRuntime*)
|
||||
JSD_GetJSRuntime(JSDContext* jsdc)
|
||||
{
|
||||
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
||||
return jsdc->jsrt;
|
||||
}
|
||||
|
||||
JSD_PUBLIC_API(void)
|
||||
JSD_SetUserCallbacks(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user)
|
||||
{
|
||||
|
|
|
@ -188,6 +188,12 @@ JSD_GetMinorVersion(void);
|
|||
extern JSD_PUBLIC_API(JSContext*)
|
||||
JSD_GetDefaultJSContext(JSDContext* jsdc);
|
||||
|
||||
/*
|
||||
* Returns a JSRuntime this context is associated with
|
||||
*/
|
||||
extern JSD_PUBLIC_API(JSRuntime*)
|
||||
JSD_GetJSRuntime(JSDContext* jsdc);
|
||||
|
||||
/*
|
||||
* Set the private data for this context, returns previous value
|
||||
*/
|
||||
|
|
|
@ -286,7 +286,7 @@ MapObject::construct(JSContext *cx, unsigned argc, Value *vp)
|
|||
JSBool
|
||||
MapObject::size(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
THIS_MAP(get, cx, argc, vp, args, map);
|
||||
THIS_MAP(size, cx, argc, vp, args, map);
|
||||
JS_STATIC_ASSERT(sizeof map.count() <= sizeof(uint32_t));
|
||||
args.rval().setNumber(map.count());
|
||||
return true;
|
||||
|
@ -455,7 +455,7 @@ SetObject::construct(JSContext *cx, unsigned argc, Value *vp)
|
|||
JSBool
|
||||
SetObject::size(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
THIS_SET(has, cx, argc, vp, args, set);
|
||||
THIS_SET(size, cx, argc, vp, args, set);
|
||||
JS_STATIC_ASSERT(sizeof set.count() <= sizeof(uint32_t));
|
||||
args.rval().setNumber(set.count());
|
||||
return true;
|
||||
|
|
|
@ -47,7 +47,7 @@ GC(JSContext *cx, unsigned argc, jsval *vp)
|
|||
PrepareForDebugGC(cx->runtime);
|
||||
else
|
||||
PrepareForFullGC(cx->runtime);
|
||||
GCForReason(cx, gcreason::API);
|
||||
GCForReason(cx->runtime, gcreason::API);
|
||||
|
||||
char buf[256] = { '\0' };
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
|
@ -234,7 +234,7 @@ VerifyBarriers(JSContext *cx, unsigned argc, jsval *vp)
|
|||
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Too many arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
gc::VerifyBarriers(cx);
|
||||
gc::VerifyBarriers(cx->runtime);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ GCSlice(JSContext *cx, unsigned argc, jsval *vp)
|
|||
limit = false;
|
||||
}
|
||||
|
||||
GCDebugSlice(cx, limit, budget);
|
||||
GCDebugSlice(cx->runtime, limit, budget);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -469,7 +469,6 @@ 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();
|
||||
|
@ -499,7 +498,7 @@ MJitChunkLimit(JSContext *cx, unsigned argc, jsval *vp)
|
|||
|
||||
// Clear out analysis information which might refer to code compiled with
|
||||
// the previous chunk limit.
|
||||
JS_GC(cx);
|
||||
JS_GC(cx->runtime);
|
||||
|
||||
vp->setUndefined();
|
||||
return true;
|
||||
|
|
|
@ -837,3 +837,8 @@ EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
|
|||
endif
|
||||
EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
|
||||
EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
|
||||
|
||||
# Include internal ply only if needed
|
||||
ifndef MOZ_SYSTEM_PLY
|
||||
PLY_INCLUDE = -I$(topsrcdir)/other-licenses/ply
|
||||
endif
|
||||
|
|
|
@ -1444,7 +1444,7 @@ xpidl-preqs = \
|
|||
$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
|
||||
$(REPORT_BUILD)
|
||||
$(PYTHON_PATH) \
|
||||
-I$(topsrcdir)/other-licenses/ply \
|
||||
$(PLY_INCLUDE) \
|
||||
-I$(topsrcdir)/xpcom/idl-parser \
|
||||
$(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
|
||||
@if test -n "$(findstring $*.h, $(EXPORTS))"; \
|
||||
|
@ -1456,7 +1456,7 @@ ifndef NO_GEN_XPT
|
|||
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
|
||||
$(REPORT_BUILD)
|
||||
$(PYTHON_PATH) \
|
||||
-I$(topsrcdir)/other-licenses/ply \
|
||||
$(PLY_INCLUDE) \
|
||||
-I$(topsrcdir)/xpcom/idl-parser \
|
||||
-I$(topsrcdir)/xpcom/typelib/xpt/tools \
|
||||
$(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,5 @@
|
|||
load(libdir + "asserts.js");
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
assertThrowsInstanceOf(function () { Map.prototype.size.apply(g, []); }, g.TypeError);
|
||||
assertThrowsInstanceOf(function () { Set.prototype.size.apply(g, []); }, g.TypeError);
|
|
@ -0,0 +1,14 @@
|
|||
// Environment.prototype.getVariable does not see variables bound in enclosing scopes.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var hits = 0;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
assertEq(frame.environment.getVariable("x"), 13);
|
||||
assertEq(frame.environment.getVariable("k"), undefined);
|
||||
assertEq(frame.environment.find("k").getVariable("k"), 3);
|
||||
hits++;
|
||||
};
|
||||
g.eval("var k = 3; function f(x) { debugger; }");
|
||||
g.f(13);
|
||||
assertEq(hits, 1);
|
|
@ -0,0 +1,16 @@
|
|||
// getVariable works in function scopes.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var hits = 0;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
assertEq(frame.environment.getVariable("a"), 1);
|
||||
assertEq(frame.environment.getVariable("b"), 2);
|
||||
assertEq(frame.environment.getVariable("c"), 3);
|
||||
assertEq(frame.environment.getVariable("d"), 4);
|
||||
assertEq(frame.environment.getVariable("e"), 5);
|
||||
hits++;
|
||||
};
|
||||
g.eval("function f(a, [b, c]) { var d = c + 1; let e = d + 1; debugger; }");
|
||||
g.f(1, [2, 3]);
|
||||
assertEq(hits, 1);
|
|
@ -0,0 +1,22 @@
|
|||
// getVariable sees bindings in let-block scopes.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var log = '';
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
log += frame.environment.getVariable("x");
|
||||
};
|
||||
g.eval("function f() {\n" +
|
||||
" let x = 'a';\n" +
|
||||
" debugger;\n" +
|
||||
" for (let x = 0; x < 2; x++)\n" +
|
||||
" if (x === 0)\n" +
|
||||
" debugger;\n" +
|
||||
" else {\n" +
|
||||
" let x = 'b'; debugger;\n" +
|
||||
" }\n" +
|
||||
"}\n");
|
||||
g.f();
|
||||
g.eval("let (x = 'c') { debugger; }");
|
||||
g.eval("{ let x = 'd'; debugger; }");
|
||||
assertEq(log, 'a0bcd');
|
|
@ -0,0 +1,12 @@
|
|||
// getVariable sees variables in function scopes added by non-strict direct eval.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var v;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
v = frame.environment.getVariable("x");
|
||||
};
|
||||
|
||||
g.eval("function f(s) { eval(s); debugger; }");
|
||||
g.f("var x = 'Q';");
|
||||
assertEq(v, 'Q');
|
|
@ -0,0 +1,10 @@
|
|||
// getVariable sees global variables.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var log = '';
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
log += frame.environment.getVariable("x") + frame.environment.getVariable("y");
|
||||
};
|
||||
g.eval("var x = 'a'; this.y = 'b'; debugger;");
|
||||
assertEq(log, 'ab');
|
|
@ -0,0 +1,12 @@
|
|||
// getVariable sees properties inherited from the global object's prototype chain.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var log = '';
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
log += frame.environment.getVariable("x") + frame.environment.getVariable("y");
|
||||
};
|
||||
g.eval("Object.getPrototypeOf(this).x = 'a';\n" +
|
||||
"Object.prototype.y = 'b';\n" +
|
||||
"debugger;\n");
|
||||
assertEq(log, 'ab');
|
|
@ -0,0 +1,10 @@
|
|||
// getVariable can get properties from with-block scopes.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var v;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
v = frame.environment.getVariable("x");
|
||||
};
|
||||
g.eval("var x = 1; { let x = 2; with ({x: 3}) { debugger; } }");
|
||||
assertEq(v, 3);
|
|
@ -0,0 +1,10 @@
|
|||
// getVariable sees properties inherited from a with-object's prototype chain.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var v;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
v = frame.environment.getVariable("x");
|
||||
};
|
||||
g.eval("var x = 1; { let x = 2; with (Object.create({x: 3})) { debugger; } }");
|
||||
assertEq(v, 3);
|
|
@ -0,0 +1,13 @@
|
|||
// getVariable works on ancestors of frame.environment.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var log = '';
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
for (var env = frame.environment; env; env = env.parent) {
|
||||
if (env.find("x") === env)
|
||||
log += env.getVariable("x");
|
||||
}
|
||||
};
|
||||
g.eval("var x = 1; { let x = 2; with (Object.create({x: 3})) { debugger; } }");
|
||||
assertEq(log, "321");
|
|
@ -0,0 +1,27 @@
|
|||
// getVariable works on a heavyweight environment after control leaves its scope.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var envs = [];
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
envs.push(frame.environment);
|
||||
};
|
||||
g.eval("var f;\n" +
|
||||
"for (var x = 0; x < 3; x++) {\n" +
|
||||
" (function (x) {\n" +
|
||||
" for (var y = 0; y < 3; y++) {\n" +
|
||||
" (function (z) {\n" +
|
||||
" eval(z); // force heavyweight\n" +
|
||||
" debugger;\n" +
|
||||
" })(x + y);\n" +
|
||||
" }\n" +
|
||||
" })(x);\n" +
|
||||
"}");
|
||||
|
||||
var i = 0;
|
||||
for (var x = 0; x < 3; x++) {
|
||||
for (var y = 0; y < 3; y++) {
|
||||
var e = envs[i++];
|
||||
assertEq(e.getVariable("z"), x + y);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// The value returned by getVariable can be a Debugger.Object.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debugger;
|
||||
var gw = dbg.addDebuggee(g);
|
||||
var hits = 0;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
var a = frame.environment.getVariable('Math');
|
||||
assertEq(a instanceof Debugger.Object, true);
|
||||
var b = gw.getOwnPropertyDescriptor('Math').value;
|
||||
assertEq(a, b);
|
||||
hits++;
|
||||
};
|
||||
g.eval("debugger;");
|
||||
assertEq(hits, 1);
|
|
@ -0,0 +1,17 @@
|
|||
// getVariable that would trigger a getter does not crash or explode.
|
||||
// It should throw WouldRunDebuggee, but that isn't implemented yet.
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var hits = 0;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
assertThrowsInstanceOf(function () {
|
||||
frame.environment.getVariable("x");
|
||||
}, Error);
|
||||
hits++;
|
||||
};
|
||||
g.eval("Object.defineProperty(this, 'x', {get: function () { throw new Error('fail'); }});\n" +
|
||||
"debugger;");
|
||||
assertEq(hits, 1);
|
|
@ -0,0 +1,9 @@
|
|||
// Environment.prototype.setVariable can set global variables.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
frame.environment.setVariable("x", 2);
|
||||
};
|
||||
g.eval("var x = 1; debugger;");
|
||||
assertEq(g.x, 2);
|
|
@ -0,0 +1,10 @@
|
|||
// The argument to setVariable can be a Debugger.Object.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debugger;
|
||||
var gw = dbg.addDebuggee(g);
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
frame.environment.setVariable("x", gw);
|
||||
};
|
||||
g.eval("var x = 1; debugger;");
|
||||
assertEq(g.x, g);
|
|
@ -0,0 +1,16 @@
|
|||
// setVariable cannot create new global variables.
|
||||
// (Other kinds of environment are tested in Environment-variables.js.)
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debugger(g);
|
||||
var hits = 0;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
assertThrowsInstanceOf(function () { frame.environment.setVariable("x", 7); }, TypeError);
|
||||
hits++;
|
||||
};
|
||||
g.eval("debugger");
|
||||
assertEq("x" in g, false);
|
||||
assertEq(hits, 1);
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// setVariable can set variables and arguments in functions.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debugger(g);
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
frame.environment.setVariable("a", 100);
|
||||
frame.environment.setVariable("b", 200);
|
||||
};
|
||||
g.eval("function f(a) { var b = a + 1; debugger; return a + b; }");
|
||||
assertEq(g.f(1), 300);
|
|
@ -0,0 +1,14 @@
|
|||
// setVariable can change the types of variables and arguments in functions.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
g.eval("function f(a) { var b = a + 1; debugger; return a + b; }");
|
||||
for (var i = 0; i < 20; i++)
|
||||
assertEq(g.f(i), 2 * i + 1);
|
||||
|
||||
var dbg = new Debugger(g);
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
frame.environment.setVariable("a", "xyz");
|
||||
frame.environment.setVariable("b", "zy");
|
||||
};
|
||||
for (var i = 0; i < 10; i++)
|
||||
assertEq(g.f(i), "xyzzy");
|
|
@ -0,0 +1,9 @@
|
|||
// setVariable on an argument works as expected with non-strict 'arguments'.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
g.eval("function f(a) { debugger; return arguments[0]; }");
|
||||
var dbg = new Debugger(g);
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
frame.environment.setVariable("a", 2);
|
||||
};
|
||||
assertEq(g.f(1), 2);
|
|
@ -0,0 +1,15 @@
|
|||
// setVariable works on let-bindings.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
function test(code, val) {
|
||||
g.eval("function f() { " + code + " }");
|
||||
var dbg = new Debugger(g);
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
frame.environment.setVariable("a", val);
|
||||
};
|
||||
assertEq(g.f(), val);
|
||||
}
|
||||
|
||||
test("let a = 1; debugger; return a;", "xyzzy");
|
||||
test("{ let a = 1; debugger; return a; }", "plugh");
|
||||
test("let (a = 1) { debugger; return a; }", "wcgr");
|
|
@ -0,0 +1,29 @@
|
|||
// setVariable throws if no binding exists.
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
function test(code) {
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debugger(g);
|
||||
var hits = 0;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
var env = frame.older.environment;
|
||||
assertThrowsInstanceOf(function () { env.setVariable("y", 2); }, Error);
|
||||
hits++;
|
||||
};
|
||||
g.eval("var y = 0; function d() { debugger; }");
|
||||
|
||||
assertEq(g.eval(code), 0);
|
||||
|
||||
assertEq(g.y, 0);
|
||||
assertEq(hits, 1);
|
||||
}
|
||||
|
||||
// local scope of non-heavyweight function
|
||||
test("function f() { var x = 1; d(); return y; } f();");
|
||||
|
||||
// block scope
|
||||
test("function h(x) { if (x) { let x = 1; d(); return y; } } h(3);");
|
||||
|
||||
// strict eval scope
|
||||
test("'use strict'; eval('d(); y;');");
|
|
@ -0,0 +1,32 @@
|
|||
// setVariable works on non-innermost environments.
|
||||
|
||||
// (The debuggee code here is a bit convoluted to defeat optimizations that
|
||||
// could make obj.b a null closure or obj.i a flat closure--that is, a function
|
||||
// that gets a frozen copy of i instead of a reference to the runtime
|
||||
// environment that contains it. setVariable does not currently detect this
|
||||
// flat closure case.)
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
g.eval("function d() { debugger; }\n" +
|
||||
"var i = 'FAIL';\n" +
|
||||
"function a() {\n" +
|
||||
" var obj = {b: function (i) { d(obj); return i; },\n" +
|
||||
" i: function () { return i; }};\n" +
|
||||
" var i = 'FAIL2';\n" +
|
||||
" return obj;\n" +
|
||||
"}\n");
|
||||
|
||||
var dbg = Debugger(g);
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
var x = 0;
|
||||
for (var env = frame.older.environment; env; env = env.parent) {
|
||||
if (env.getVariable("i") !== undefined)
|
||||
env.setVariable("i", x++);
|
||||
}
|
||||
};
|
||||
|
||||
var obj = g.a();
|
||||
var r = obj.b('FAIL3');
|
||||
assertEq(r, 0);
|
||||
assertEq(obj.i(), 1);
|
||||
assertEq(g.i, 2);
|
|
@ -0,0 +1,16 @@
|
|||
// setVariable cannot modify the binding for a FunctionExpression's name.
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
var hits = 0;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
var env = frame.environment.find("f");
|
||||
assertEq(env.getVariable("f"), frame.callee);
|
||||
assertThrowsInstanceOf(function () { env.setVariable("f", 0) }, TypeError);
|
||||
assertThrowsInstanceOf(function () { env.setVariable("f", frame.callee) }, TypeError);
|
||||
hits++;
|
||||
};
|
||||
g.eval("(function f() { debugger; })();");
|
||||
assertEq(hits, 1);
|
|
@ -0,0 +1,21 @@
|
|||
// setVariable can create a new property on a with block's bindings object, if
|
||||
// it is shadowing an existing property on the prototype chain.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
var env = frame.environment.find("x");
|
||||
env.setVariable("x", 2);
|
||||
};
|
||||
g.eval("var obj1 = {x: 1}, obj2 = Object.create(obj1), z; with (obj2) { debugger; z = x; }");
|
||||
assertEq(g.obj1.x, 1);
|
||||
assertEq(g.obj2.x, 2);
|
||||
assertEq(g.z, 2);
|
||||
|
||||
// The property created by setVariable is like the one created by ordinary
|
||||
// assignment in a with-block.
|
||||
var desc = Object.getOwnPropertyDescriptor(g.obj2, "x");
|
||||
assertEq(desc.configurable, true);
|
||||
assertEq(desc.enumerable, true);
|
||||
assertEq(desc.writable, true);
|
||||
assertEq(desc.value, 2);
|
|
@ -0,0 +1,22 @@
|
|||
// setVariable triggering a setter doesn't crash or explode.
|
||||
// It should throw WouldRunDebuggee, but that isn't implemented yet.
|
||||
|
||||
function test(code) {
|
||||
var g = newGlobal('new-compartment');
|
||||
g.eval("function d() { debugger; }");
|
||||
var dbg = Debugger(g);
|
||||
var hits = 0;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
var env = frame.environment.find("x");
|
||||
try {
|
||||
env.setVariable("x", 0);
|
||||
} catch (exc) {
|
||||
}
|
||||
hits++;
|
||||
};
|
||||
g.eval(code);
|
||||
}
|
||||
|
||||
test("Object.defineProperty(this, 'x', {set: function (v) {}}); d();");
|
||||
test("Object.defineProperty(Object.prototype, 'x', {set: function (v) {}}); d();");
|
||||
test("with ({set x(v) {}}) eval(d());");
|
|
@ -0,0 +1,92 @@
|
|||
// Comprehensive test of get/setVariable on many kinds of environments and
|
||||
// bindings.
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
var cases = [
|
||||
// global bindings and bindings on the global prototype chain
|
||||
"x = VAL; @@",
|
||||
"var x = VAL; @@",
|
||||
"Object.prototype.x = VAL; @@",
|
||||
|
||||
// let, catch, and comprehension bindings
|
||||
"let x = VAL; @@",
|
||||
"{ let x = VAL; @@ }",
|
||||
"let (x = VAL) { @@ }",
|
||||
"try { throw VAL; } catch (x) { @@ }",
|
||||
"try { throw VAL; } catch (x) { @@ }",
|
||||
"for (let x of [VAL]) { @@ }",
|
||||
"for each (let x in [VAL]) { @@ }",
|
||||
"switch (0) { default: let x = VAL; @@ }",
|
||||
"[function () { @@ }() for (x of [VAL])];",
|
||||
// "((function () { @@ })() for (x of [VAL])).next();", // bug 709367
|
||||
|
||||
// arguments
|
||||
"function f(x) { @@ } f(VAL);",
|
||||
"function f([w, x]) { @@ } f([0, VAL]);",
|
||||
"function f({v: x}) { @@ } f({v: VAL});",
|
||||
"function f([w, {v: x}]) { @@ } f([0, {v: VAL}]);",
|
||||
|
||||
// bindings in functions
|
||||
"function f() { var x = VAL; @@ } f();",
|
||||
"function f() { let x = VAL; @@ } f();",
|
||||
"function f([x]) { let x = VAL; @@ } f(['fail']);",
|
||||
"function f(x) { { let x = VAL; @@ } } f('fail');",
|
||||
"function f() { function x() {} x = VAL; @@ } f();",
|
||||
|
||||
// dynamic bindings
|
||||
"function f(s) { eval(s); @@ } f('var x = VAL');",
|
||||
"function f(s) { let (x = 'fail') { eval(s); } x = VAL; @@ } f('var x;');",
|
||||
"var x = VAL; function f(s) { eval('var x = 0;'); eval(s); @@ } f('delete x;');",
|
||||
"function f(obj) { with (obj) { @@ } } f({x: VAL});",
|
||||
"function f(obj) { with (obj) { @@ } } f(Object.create({x: VAL}));",
|
||||
"function f(b) { if (b) { function x(){} } x = VAL; @@ } f(1);",
|
||||
];
|
||||
|
||||
var nextval = 1000;
|
||||
|
||||
function test(code, debugStmts, followupStmts) {
|
||||
var val = nextval++;
|
||||
var hits = 0;
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
g.eval("function debugMe() { var x = 'wrong-x'; debugger; }");
|
||||
g.capture = null;
|
||||
|
||||
var dbg = Debugger(g);
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
if (frame.callee !== null && frame.callee.name == 'debugMe')
|
||||
frame = frame.older;
|
||||
var env = frame.environment.find("x");
|
||||
assertEq(env.getVariable("x"), val)
|
||||
assertEq(env.setVariable("x", 'ok'), undefined);
|
||||
assertEq(env.getVariable("x"), 'ok');
|
||||
|
||||
// setVariable cannot create new variables.
|
||||
assertThrowsInstanceOf(function () { env.setVariable("newVar", 0); }, TypeError);
|
||||
hits++;
|
||||
};
|
||||
|
||||
code = code.replace("@@", debugStmts);
|
||||
if (followupStmts !== undefined)
|
||||
code += " " + followupStmts;
|
||||
code = code.replace(/VAL/g, uneval(val));
|
||||
g.eval(code);
|
||||
assertEq(hits, 1);
|
||||
}
|
||||
|
||||
for (var s of cases) {
|
||||
// Test triggering the debugger right in the scope in which x is bound.
|
||||
test(s, "debugger; assertEq(x, 'ok');");
|
||||
|
||||
// Test calling a function that triggers the debugger.
|
||||
test(s, "debugMe(); assertEq(x, 'ok');");
|
||||
|
||||
// Test triggering the debugger from a scope nested in x's scope.
|
||||
test(s, "let (y = 'irrelevant') { (function (z) { let (zz = y) { debugger; }})(); } assertEq(x, 'ok');"),
|
||||
|
||||
// Test closing over the variable and triggering the debugger later, after
|
||||
// leaving the variable's scope.
|
||||
test(s, "capture = {dbg: function () { debugger; }, get x() { return x; }};",
|
||||
"assertEq(capture.x, VAL); capture.dbg(); assertEq(capture.x, 'ok');");
|
||||
}
|
|
@ -377,3 +377,5 @@ MSG_DEF(JSMSG_EMPTY_CONSEQUENT, 290, 0, JSEXN_SYNTAXERR, "mistyped ; after
|
|||
MSG_DEF(JSMSG_NOT_ITERABLE, 291, 1, JSEXN_TYPEERR, "{0} is not iterable")
|
||||
MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 292, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'url' property")
|
||||
MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 293, 0, JSEXN_TYPEERR, "findScripts query object has 'innermost' property without both 'url' and 'line' properties")
|
||||
MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND, 294, 0, JSEXN_TYPEERR, "variable not found in environment")
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ wrap(JSContext *cx, JSObject *toWrap, JSObject *target)
|
|||
static JSObject *
|
||||
PreWrap(JSContext *cx, JSObject *scope, JSObject *obj, unsigned flags)
|
||||
{
|
||||
JS_GC(cx);
|
||||
JS_GC(JS_GetRuntime(cx));
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,14 +29,14 @@ BEGIN_TEST(testConservativeGC)
|
|||
|
||||
tmp = JSVAL_NULL;
|
||||
|
||||
JS_GC(cx);
|
||||
JS_GC(rt);
|
||||
|
||||
EVAL("var a = [];\n"
|
||||
"for (var i = 0; i != 10000; ++i) {\n"
|
||||
"a.push(i + 0.1, [1, 2], String(Math.sqrt(i)), {a: i});\n"
|
||||
"}", &tmp);
|
||||
|
||||
JS_GC(cx);
|
||||
JS_GC(rt);
|
||||
|
||||
checkObjectFields((JSObject *)objCopy, JSVAL_TO_OBJECT(v2));
|
||||
CHECK(!memcmp(&strCopy, JSVAL_TO_STRING(v3), sizeof(strCopy)));
|
||||
|
@ -69,7 +69,7 @@ BEGIN_TEST(testDerivedValues)
|
|||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 1000; j++)
|
||||
JS_NewStringCopyZ(cx, "as I pondered weak and weary");
|
||||
JS_GC(cx);
|
||||
JS_GC(rt);
|
||||
}
|
||||
|
||||
CHECK(!memcmp(ch, expected, sizeof(expected)));
|
||||
|
|
|
@ -39,7 +39,7 @@ BEGIN_TEST(testExternalStrings)
|
|||
// clear that newborn root
|
||||
JS_NewUCStringCopyN(cx, arr, arrlen);
|
||||
|
||||
JS_GC(cx);
|
||||
JS_GC(rt);
|
||||
|
||||
// a generous fudge factor to account for strings rooted by conservative gc
|
||||
const unsigned epsilon = 10;
|
||||
|
|
|
@ -37,7 +37,7 @@ BEGIN_TEST(testGCOutOfMemory)
|
|||
CHECK(!ok);
|
||||
CHECK(!JS_IsExceptionPending(cx));
|
||||
CHECK_EQUAL(errorCount, 1);
|
||||
JS_GC(cx);
|
||||
JS_GC(rt);
|
||||
EVAL("(function() {"
|
||||
" var array = [];"
|
||||
" for (var i = max >> 2; i != 0;) {"
|
||||
|
|
|
@ -36,7 +36,7 @@ BEGIN_TEST(testInternAcrossGC)
|
|||
sw.strOk = false;
|
||||
CHECK(sw.str);
|
||||
JS_SetFinalizeCallback(rt, FinalizeCallback);
|
||||
JS_GC(cx);
|
||||
JS_GC(rt);
|
||||
CHECK(sw.strOk);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ struct ScriptObjectFixture : public JSAPITest {
|
|||
{
|
||||
CHECK(script);
|
||||
|
||||
JS_GC(cx);
|
||||
JS_GC(rt);
|
||||
|
||||
/* After a garbage collection, the script should still work. */
|
||||
jsval result;
|
||||
|
|
|
@ -11,7 +11,7 @@ static JSTrapStatus
|
|||
EmptyTrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
jsval closure)
|
||||
{
|
||||
JS_GC(cx);
|
||||
JS_GC(JS_GetRuntime(cx));
|
||||
if (JSVAL_IS_STRING(closure))
|
||||
++emptyTrapCallCount;
|
||||
return JSTRAP_CONTINUE;
|
||||
|
@ -59,7 +59,7 @@ BEGIN_TEST(testTrap_gc)
|
|||
JS_SetTrap(cx, script, line2, EmptyTrapHandler, STRING_TO_JSVAL(trapClosure));
|
||||
JS_SetTrap(cx, script, line6, EmptyTrapHandler, STRING_TO_JSVAL(trapClosure));
|
||||
|
||||
JS_GC(cx);
|
||||
JS_GC(rt);
|
||||
|
||||
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(trapClosure), trapClosureText));
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ BEGIN_TEST(testTrap_gc)
|
|||
CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
|
||||
CHECK_EQUAL(emptyTrapCallCount, 11);
|
||||
|
||||
JS_GC(cx);
|
||||
JS_GC(rt);
|
||||
|
||||
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(trapClosure), trapClosureText));
|
||||
|
||||
|
|
|
@ -202,7 +202,7 @@ BEGIN_TEST(testXDR_bug506491)
|
|||
CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
|
||||
|
||||
// try to break the Block object that is the parent of f
|
||||
JS_GC(cx);
|
||||
JS_GC(rt);
|
||||
|
||||
// confirm
|
||||
EVAL("f() === 'ok';\n", v2.addr());
|
||||
|
|
|
@ -1137,25 +1137,19 @@ JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback)
|
|||
JS_PUBLIC_API(JSContext *)
|
||||
JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
||||
{
|
||||
return js_NewContext(rt, stackChunkSize);
|
||||
return NewContext(rt, stackChunkSize);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_DestroyContext(JSContext *cx)
|
||||
{
|
||||
js_DestroyContext(cx, JSDCM_FORCE_GC);
|
||||
DestroyContext(cx, DCM_FORCE_GC);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_DestroyContextNoGC(JSContext *cx)
|
||||
{
|
||||
js_DestroyContext(cx, JSDCM_NO_GC);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_DestroyContextMaybeGC(JSContext *cx)
|
||||
{
|
||||
js_DestroyContext(cx, JSDCM_MAYBE_GC);
|
||||
DestroyContext(cx, DCM_NO_GC);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
|
@ -2860,11 +2854,11 @@ JS_IsGCMarkingTracer(JSTracer *trc)
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_GC(JSContext *cx)
|
||||
JS_GC(JSRuntime *rt)
|
||||
{
|
||||
AssertNoGC(cx);
|
||||
PrepareForFullGC(cx->runtime);
|
||||
GC(cx, GC_NORMAL, gcreason::API);
|
||||
AssertNoGC(rt);
|
||||
PrepareForFullGC(rt);
|
||||
GC(rt, GC_NORMAL, gcreason::API);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
|
@ -2961,11 +2955,6 @@ JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key)
|
|||
return 0;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_FlushCaches(JSContext *cx)
|
||||
{
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
JS_NewExternalString(JSContext *cx, const jschar *chars, size_t length,
|
||||
const JSStringFinalizer *fin)
|
||||
|
|
|
@ -2568,9 +2568,6 @@ JS_DestroyContext(JSContext *cx);
|
|||
extern JS_PUBLIC_API(void)
|
||||
JS_DestroyContextNoGC(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DestroyContextMaybeGC(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_GetContextPrivate(JSContext *cx);
|
||||
|
||||
|
@ -3158,12 +3155,6 @@ JS_DumpNamedRoots(JSRuntime *rt,
|
|||
* in the return value. To keep on mapping, return JS_MAP_GCROOT_NEXT. These
|
||||
* constants are flags; you can OR them together.
|
||||
*
|
||||
* This function acquires and releases rt's GC lock around the mapping of the
|
||||
* roots table, so the map function should run to completion in as few cycles
|
||||
* as possible. Of course, map cannot call JS_GC, JS_MaybeGC, JS_BeginRequest,
|
||||
* or any JS API entry point that acquires locks, without double-tripping or
|
||||
* deadlocking on the GC lock.
|
||||
*
|
||||
* The JSGCRootType parameter indicates whether rp is a pointer to a Value
|
||||
* (which is obtained by '(Value *)rp') or a pointer to a GC-thing pointer
|
||||
* (which is obtained by '(void **)rp').
|
||||
|
@ -3260,6 +3251,9 @@ struct JSTracer {
|
|||
const void *debugPrintArg;
|
||||
size_t debugPrintIndex;
|
||||
JSBool eagerlyTraceWeakMaps;
|
||||
#ifdef DEBUG
|
||||
void *realLocation;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -3300,6 +3294,22 @@ JS_CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind);
|
|||
JS_END_MACRO
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Sets the real location for a marked reference, when passing the address
|
||||
* directly is not feasable.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
# define JS_SET_TRACING_LOCATION(trc, location) \
|
||||
JS_BEGIN_MACRO \
|
||||
(trc)->realLocation = (location); \
|
||||
JS_END_MACRO
|
||||
#else
|
||||
# define JS_SET_TRACING_LOCATION(trc, location) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_END_MACRO
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Convenience macro to describe the argument of JS_CallTracer using C string
|
||||
* and index.
|
||||
|
@ -3395,10 +3405,10 @@ JS_DumpHeap(JSRuntime *rt, FILE *fp, void* startThing, JSGCTraceKind kind,
|
|||
* Garbage collector API.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_GC(JSContext *cx);
|
||||
JS_GC(JSRuntime *rt);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CompartmentGC(JSContext *cx, JSCompartment *comp);
|
||||
JS_CompartmentGC(JSRuntime *rt, JSCompartment *comp);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_MaybeGC(JSContext *cx);
|
||||
|
@ -3473,15 +3483,6 @@ JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32_t value);
|
|||
extern JS_PUBLIC_API(uint32_t)
|
||||
JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key);
|
||||
|
||||
/*
|
||||
* Flush the code cache for the current thread. The operation might be
|
||||
* delayed if the cache cannot be flushed currently because native
|
||||
* code is currently executing.
|
||||
*/
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_FlushCaches(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Create a new JSString whose chars member refers to external memory, i.e.,
|
||||
* memory requiring application-specific finalization.
|
||||
|
|
|
@ -502,8 +502,10 @@ js_DumpAtoms(JSContext *cx, FILE *fp)
|
|||
|
||||
JS_STATIC_ASSERT(TEMP_SIZE_START >= sizeof(JSHashTable));
|
||||
|
||||
namespace js {
|
||||
|
||||
void
|
||||
js_InitAtomMap(JSContext *cx, AtomIndexMap *indices, JSAtom **atoms)
|
||||
InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtrAtom *atoms)
|
||||
{
|
||||
if (indices->isMap()) {
|
||||
typedef AtomIndexMap::WordMap WordMap;
|
||||
|
@ -512,7 +514,7 @@ js_InitAtomMap(JSContext *cx, AtomIndexMap *indices, JSAtom **atoms)
|
|||
JSAtom *atom = r.front().key;
|
||||
jsatomid index = r.front().value;
|
||||
JS_ASSERT(index < indices->count());
|
||||
atoms[index] = atom;
|
||||
atoms[index].init(atom);
|
||||
}
|
||||
} else {
|
||||
for (const AtomIndexMap::InlineElem *it = indices->asInline(), *end = indices->inlineEnd();
|
||||
|
@ -521,13 +523,11 @@ js_InitAtomMap(JSContext *cx, AtomIndexMap *indices, JSAtom **atoms)
|
|||
if (!atom)
|
||||
continue;
|
||||
JS_ASSERT(it->value < indices->count());
|
||||
atoms[it->value] = atom;
|
||||
atoms[it->value].init(atom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
bool
|
||||
IndexToIdSlow(JSContext *cx, uint32_t index, jsid *idp)
|
||||
{
|
||||
|
|
|
@ -470,15 +470,15 @@ inline bool
|
|||
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
|
||||
jsid *idp, js::Value *vp);
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* For all unmapped atoms recorded in al, add a mapping from the atom's index
|
||||
* to its address. map->length must already be set to the number of atoms in
|
||||
* the list and map->vector must point to pre-allocated memory.
|
||||
*/
|
||||
extern void
|
||||
js_InitAtomMap(JSContext *cx, js::AtomIndexMap *indices, JSAtom **atoms);
|
||||
|
||||
namespace js {
|
||||
InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtrAtom *atoms);
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
|
|
|
@ -169,7 +169,7 @@ js_GetCurrentScript(JSContext *cx)
|
|||
}
|
||||
|
||||
JSContext *
|
||||
js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
||||
js::NewContext(JSRuntime *rt, size_t stackChunkSize)
|
||||
{
|
||||
JS_AbortIfWrongThread(rt);
|
||||
|
||||
|
@ -198,7 +198,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
|||
* keywords, numbers, and strings. If one of these steps should fail, the
|
||||
* runtime will be left in a partially initialized state, with zeroes and
|
||||
* nulls stored in the default-initialized remainder of the struct. We'll
|
||||
* clean the runtime up under js_DestroyContext, because cx will be "last"
|
||||
* clean the runtime up under DestroyContext, because cx will be "last"
|
||||
* as well as "first".
|
||||
*/
|
||||
if (first) {
|
||||
|
@ -213,14 +213,14 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
|||
JS_EndRequest(cx);
|
||||
#endif
|
||||
if (!ok) {
|
||||
js_DestroyContext(cx, JSDCM_NEW_FAILED);
|
||||
DestroyContext(cx, DCM_NEW_FAILED);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSContextCallback cxCallback = rt->cxCallback;
|
||||
if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) {
|
||||
js_DestroyContext(cx, JSDCM_NEW_FAILED);
|
||||
DestroyContext(cx, DCM_NEW_FAILED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
|||
}
|
||||
|
||||
void
|
||||
js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
js::DestroyContext(JSContext *cx, DestroyContextMode mode)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
JS_AbortIfWrongThread(rt);
|
||||
|
@ -239,14 +239,13 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
|||
JS_ASSERT(cx->outstandingRequests == 0);
|
||||
#endif
|
||||
|
||||
if (mode != JSDCM_NEW_FAILED) {
|
||||
if (mode != DCM_NEW_FAILED) {
|
||||
if (JSContextCallback cxCallback = rt->cxCallback) {
|
||||
/*
|
||||
* JSCONTEXT_DESTROY callback is not allowed to fail and must
|
||||
* return true.
|
||||
*/
|
||||
DebugOnly<JSBool> callbackStatus = cxCallback(cx, JSCONTEXT_DESTROY);
|
||||
JS_ASSERT(callbackStatus);
|
||||
JS_ALWAYS_TRUE(cxCallback(cx, JSCONTEXT_DESTROY));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,13 +254,6 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
|||
if (last) {
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
{
|
||||
AutoLockGC lock(rt);
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dump remaining type inference results first. This printing
|
||||
* depends on atoms still existing.
|
||||
|
@ -270,30 +262,20 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
|||
c->types.print(cx, false);
|
||||
|
||||
/* Unpin all common atoms before final GC. */
|
||||
FinishCommonAtoms(cx->runtime);
|
||||
FinishCommonAtoms(rt);
|
||||
|
||||
/* Clear debugging state to remove GC roots. */
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next())
|
||||
c->clearTraps(cx);
|
||||
c->clearTraps(rt->defaultFreeOp());
|
||||
JS_ClearAllWatchPoints(cx);
|
||||
|
||||
PrepareForFullGC(rt);
|
||||
GC(cx, GC_NORMAL, gcreason::LAST_CONTEXT);
|
||||
} else if (mode == JSDCM_FORCE_GC) {
|
||||
GC(rt, GC_NORMAL, gcreason::LAST_CONTEXT);
|
||||
} else if (mode == DCM_FORCE_GC) {
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
PrepareForFullGC(rt);
|
||||
GC(cx, GC_NORMAL, gcreason::DESTROY_CONTEXT);
|
||||
} else if (mode == JSDCM_MAYBE_GC) {
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
JS_MaybeGC(cx);
|
||||
GC(rt, GC_NORMAL, gcreason::DESTROY_CONTEXT);
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
{
|
||||
AutoLockGC lock(rt);
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
}
|
||||
#endif
|
||||
Foreground::delete_(cx);
|
||||
}
|
||||
|
||||
|
@ -885,30 +867,14 @@ js_InvokeOperationCallback(JSContext *cx)
|
|||
JS_ATOMIC_SET(&rt->interrupt, 0);
|
||||
|
||||
if (rt->gcIsNeeded)
|
||||
GCSlice(cx, GC_NORMAL, rt->gcTriggerReason);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* We automatically yield the current context every time the operation
|
||||
* callback is hit since we might be called as a result of an impending
|
||||
* GC on another thread, which would deadlock if we do not yield.
|
||||
* Operation callbacks are supposed to happen rarely (seconds, not
|
||||
* milliseconds) so it is acceptable to yield at every callback.
|
||||
*
|
||||
* As the GC can be canceled before it does any request checks we yield
|
||||
* even if rt->gcIsNeeded was true above. See bug 590533.
|
||||
*/
|
||||
JS_YieldRequest(cx);
|
||||
#endif
|
||||
|
||||
JSOperationCallback cb = cx->operationCallback;
|
||||
GCSlice(rt, GC_NORMAL, rt->gcTriggerReason);
|
||||
|
||||
/*
|
||||
* Important: Additional callbacks can occur inside the callback handler
|
||||
* if it re-enters the JS engine. The embedding must ensure that the
|
||||
* callback is disconnected before attempting such re-entry.
|
||||
*/
|
||||
|
||||
JSOperationCallback cb = cx->operationCallback;
|
||||
return !cb || cb(cx);
|
||||
}
|
||||
|
||||
|
@ -990,9 +956,6 @@ JSContext::JSContext(JSRuntime *rt)
|
|||
functionCallback(NULL),
|
||||
#endif
|
||||
enumerators(NULL),
|
||||
#ifdef JS_THREADSAFE
|
||||
gcBackgroundFree(NULL),
|
||||
#endif
|
||||
activeCompilations(0)
|
||||
#ifdef DEBUG
|
||||
, stackIterAssertionEnabled(true)
|
||||
|
|
|
@ -146,15 +146,8 @@ struct ConservativeGCData
|
|||
uintptr_t words[JS_HOWMANY(sizeof(jmp_buf), sizeof(uintptr_t))];
|
||||
} registerSnapshot;
|
||||
|
||||
/*
|
||||
* Cycle collector uses this to communicate that the native stack of the
|
||||
* GC thread should be scanned only if the thread have more than the given
|
||||
* threshold of requests.
|
||||
*/
|
||||
unsigned requestThreshold;
|
||||
|
||||
ConservativeGCData()
|
||||
: nativeStackTop(NULL), requestThreshold(0)
|
||||
: nativeStackTop(NULL)
|
||||
{}
|
||||
|
||||
~ConservativeGCData() {
|
||||
|
@ -183,6 +176,13 @@ struct ConservativeGCData
|
|||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A FreeOp can do one thing: free memory. For convenience, it has delete_
|
||||
* convenience methods that also call destructors.
|
||||
*
|
||||
* FreeOp is passed to finalizers and other sweep-phase hooks so that we do not
|
||||
* need to pass a JSContext to those hooks.
|
||||
*/
|
||||
class FreeOp : public JSFreeOp {
|
||||
bool shouldFreeLater_;
|
||||
bool onBackgroundThread_;
|
||||
|
@ -215,7 +215,7 @@ class FreeOp : public JSFreeOp {
|
|||
/*
|
||||
* Check that JSFreeOp is the first base class for FreeOp and we can
|
||||
* reinterpret a pointer to JSFreeOp as a pointer to FreeOp without
|
||||
* any offset adjustments. JSClass::freeOp <-> Class::freeOp depends
|
||||
* any offset adjustments. JSClass::finalize <-> Class::finalize depends
|
||||
* on this.
|
||||
*/
|
||||
JS_STATIC_ASSERT(offsetof(FreeOp, shouldFreeLater_) == sizeof(JSFreeOp));
|
||||
|
@ -1119,14 +1119,6 @@ struct JSContext : js::ContextFriendFields
|
|||
genStack.popBack();
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* When non-null JSContext::free_ delegates the job to the background
|
||||
* thread.
|
||||
*/
|
||||
js::GCHelperThread *gcBackgroundFree;
|
||||
#endif
|
||||
|
||||
inline void* malloc_(size_t bytes) {
|
||||
return runtime->malloc_(bytes, this);
|
||||
}
|
||||
|
@ -1150,12 +1142,6 @@ struct JSContext : js::ContextFriendFields
|
|||
}
|
||||
|
||||
inline void free_(void* p) {
|
||||
#ifdef JS_THREADSAFE
|
||||
if (gcBackgroundFree) {
|
||||
gcBackgroundFree->freeLater(p);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
runtime->free_(p);
|
||||
}
|
||||
|
||||
|
@ -1461,24 +1447,23 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* Create and destroy functions for JSContext, which is manually allocated
|
||||
* and exclusively owned.
|
||||
*/
|
||||
extern JSContext *
|
||||
js_NewContext(JSRuntime *rt, size_t stackChunkSize);
|
||||
NewContext(JSRuntime *rt, size_t stackChunkSize);
|
||||
|
||||
typedef enum JSDestroyContextMode {
|
||||
JSDCM_NO_GC,
|
||||
JSDCM_MAYBE_GC,
|
||||
JSDCM_FORCE_GC,
|
||||
JSDCM_NEW_FAILED
|
||||
} JSDestroyContextMode;
|
||||
enum DestroyContextMode {
|
||||
DCM_NO_GC,
|
||||
DCM_FORCE_GC,
|
||||
DCM_NEW_FAILED
|
||||
};
|
||||
|
||||
extern void
|
||||
js_DestroyContext(JSContext *cx, JSDestroyContextMode mode);
|
||||
DestroyContext(JSContext *cx, DestroyContextMode mode);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#ifdef va_start
|
||||
extern JSBool
|
||||
|
|
|
@ -390,7 +390,7 @@ CallSetter(JSContext *cx, JSObject *obj, jsid id, StrictPropertyOp op, unsigned
|
|||
return CallJSPropertyOpSetter(cx, op, obj, id, strict, vp);
|
||||
}
|
||||
|
||||
static inline JSAtom **
|
||||
static inline HeapPtrAtom *
|
||||
FrameAtomBase(JSContext *cx, js::StackFrame *fp)
|
||||
{
|
||||
return fp->script()->atoms;
|
||||
|
|
|
@ -746,22 +746,22 @@ JSCompartment::removeDebuggee(FreeOp *fop,
|
|||
}
|
||||
|
||||
void
|
||||
JSCompartment::clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler)
|
||||
JSCompartment::clearBreakpointsIn(FreeOp *fop, js::Debugger *dbg, JSObject *handler)
|
||||
{
|
||||
for (gc::CellIter i(this, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->hasAnyBreakpointsOrStepMode())
|
||||
script->clearBreakpointsIn(cx, dbg, handler);
|
||||
script->clearBreakpointsIn(fop, dbg, handler);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::clearTraps(JSContext *cx)
|
||||
JSCompartment::clearTraps(FreeOp *fop)
|
||||
{
|
||||
for (gc::CellIter i(this, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->hasAnyBreakpointsOrStepMode())
|
||||
script->clearTraps(cx->runtime->defaultFreeOp());
|
||||
script->clearTraps(fop);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -455,8 +455,8 @@ struct JSCompartment
|
|||
js::GlobalObjectSet::Enum *debuggeesEnum = NULL);
|
||||
bool setDebugModeFromC(JSContext *cx, bool b);
|
||||
|
||||
void clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler);
|
||||
void clearTraps(JSContext *cx);
|
||||
void clearBreakpointsIn(js::FreeOp *fop, js::Debugger *dbg, JSObject *handler);
|
||||
void clearTraps(js::FreeOp *fop);
|
||||
|
||||
private:
|
||||
void sweepBreakpoints(js::FreeOp *fop);
|
||||
|
|
|
@ -231,7 +231,7 @@ JS_ClearScriptTraps(JSContext *cx, JSScript *script)
|
|||
JS_PUBLIC_API(void)
|
||||
JS_ClearAllTrapsForCompartment(JSContext *cx)
|
||||
{
|
||||
cx->compartment->clearTraps(cx);
|
||||
cx->compartment->clearTraps(cx->runtime->defaultFreeOp());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче