зеркало из https://github.com/mozilla/pjs.git
Merge last green changeset from inbound to mozilla-central
This commit is contained in:
Коммит
a39f4b9489
|
@ -871,10 +871,11 @@ refChildCB(AtkObject *aAtkObj, gint aChildIndex)
|
|||
if (!childAtkObj)
|
||||
return nsnull;
|
||||
g_object_ref(childAtkObj);
|
||||
|
||||
//this will addref parent
|
||||
|
||||
if (aAtkObj != childAtkObj->accessible_parent)
|
||||
atk_object_set_parent(childAtkObj, aAtkObj);
|
||||
return childAtkObj;
|
||||
|
||||
return childAtkObj;
|
||||
}
|
||||
|
||||
gint
|
||||
|
|
|
@ -110,3 +110,16 @@ StyleInfo::Margin(css::Side aSide, nsAString& aValue)
|
|||
aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));
|
||||
aValue.AppendLiteral("px");
|
||||
}
|
||||
|
||||
void
|
||||
StyleInfo::Format(const nscolor& aValue, nsString& aFormattedValue)
|
||||
{
|
||||
// Combine the string like rgb(R, G, B) from nscolor.
|
||||
aFormattedValue.AppendLiteral("rgb(");
|
||||
aFormattedValue.AppendInt(NS_GET_R(aValue));
|
||||
aFormattedValue.AppendLiteral(", ");
|
||||
aFormattedValue.AppendInt(NS_GET_G(aValue));
|
||||
aFormattedValue.AppendLiteral(", ");
|
||||
aFormattedValue.AppendInt(NS_GET_B(aValue));
|
||||
aFormattedValue.Append(')');
|
||||
}
|
||||
|
|
|
@ -60,6 +60,8 @@ public:
|
|||
void MarginTop(nsAString& aValue) { Margin(css::eSideTop, aValue); }
|
||||
void MarginBottom(nsAString& aValue) { Margin(css::eSideBottom, aValue); }
|
||||
|
||||
static void Format(const nscolor& aValue, nsString& aFormattedValue);
|
||||
|
||||
private:
|
||||
StyleInfo() MOZ_DELETE;
|
||||
StyleInfo(const StyleInfo&) MOZ_DELETE;
|
||||
|
|
|
@ -364,9 +364,9 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
|
|||
aDocument->IsResourceDoc() || !aDocument->IsActive())
|
||||
return nsnull;
|
||||
|
||||
// Ignore documents without presshell.
|
||||
nsIPresShell *presShell = aDocument->GetShell();
|
||||
if (!presShell)
|
||||
// Ignore documents without presshell and not having root frame.
|
||||
nsIPresShell* presShell = aDocument->GetShell();
|
||||
if (!presShell || !presShell->GetRootFrame())
|
||||
return nsnull;
|
||||
|
||||
// Do not create document accessible until role content is loaded, otherwise
|
||||
|
|
|
@ -41,12 +41,16 @@
|
|||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsHyperTextAccessibleWrap.h"
|
||||
#include "StyleInfo.h"
|
||||
|
||||
#include "gfxFont.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Constants and structures
|
||||
|
||||
|
@ -70,7 +74,6 @@ const char* const kCopyValue = nsnull;
|
|||
static nsCSSTextAttrMapItem gCSSTextAttrsMap[] =
|
||||
{
|
||||
// CSS name CSS value Attribute name Attribute value
|
||||
{ "color", kAnyValue, &nsGkAtoms::color, kCopyValue },
|
||||
{ "font-family", kAnyValue, &nsGkAtoms::font_family, kCopyValue },
|
||||
{ "font-style", kAnyValue, &nsGkAtoms::font_style, kCopyValue },
|
||||
{ "text-decoration", "line-through", &nsGkAtoms::textLineThroughStyle, "solid" },
|
||||
|
@ -154,34 +157,34 @@ nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes,
|
|||
nsLangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&langTextAttr));
|
||||
|
||||
// "color" text attribute
|
||||
nsCSSTextAttr colorTextAttr(0, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&colorTextAttr));
|
||||
|
||||
// "font-family" text attribute
|
||||
nsCSSTextAttr fontFamilyTextAttr(1, hyperTextElm, offsetElm);
|
||||
nsCSSTextAttr fontFamilyTextAttr(0, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontFamilyTextAttr));
|
||||
|
||||
// "font-style" text attribute
|
||||
nsCSSTextAttr fontStyleTextAttr(2, hyperTextElm, offsetElm);
|
||||
nsCSSTextAttr fontStyleTextAttr(1, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontStyleTextAttr));
|
||||
|
||||
// "text-line-through-style" text attribute
|
||||
nsCSSTextAttr lineThroughTextAttr(3, hyperTextElm, offsetElm);
|
||||
nsCSSTextAttr lineThroughTextAttr(2, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&lineThroughTextAttr));
|
||||
|
||||
// "text-underline-style" text attribute
|
||||
nsCSSTextAttr underlineTextAttr(4, hyperTextElm, offsetElm);
|
||||
nsCSSTextAttr underlineTextAttr(3, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&underlineTextAttr));
|
||||
|
||||
// "text-position" text attribute
|
||||
nsCSSTextAttr posTextAttr(5, hyperTextElm, offsetElm);
|
||||
nsCSSTextAttr posTextAttr(4, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&posTextAttr));
|
||||
|
||||
// "background-color" text attribute
|
||||
nsBGColorTextAttr bgColorTextAttr(rootFrame, frame);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&bgColorTextAttr));
|
||||
|
||||
// "color" text attribute
|
||||
ColorTextAttr colorTextAttr(rootFrame, frame);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&colorTextAttr));
|
||||
|
||||
// "font-size" text attribute
|
||||
nsFontSizeTextAttr fontSizeTextAttr(rootFrame, frame);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontSizeTextAttr));
|
||||
|
@ -363,7 +366,7 @@ nsCSSTextAttr::Format(const nsAutoString& aValue, nsAString& aFormattedValue)
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsBackgroundTextAttr
|
||||
// nsBGColorTextAttr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsBGColorTextAttr::nsBGColorTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame) :
|
||||
|
@ -387,16 +390,8 @@ nsBGColorTextAttr::GetValueFor(nsIContent *aContent, nscolor *aValue)
|
|||
void
|
||||
nsBGColorTextAttr::Format(const nscolor& aValue, nsAString& aFormattedValue)
|
||||
{
|
||||
// Combine the string like rgb(R, G, B) from nscolor.
|
||||
nsAutoString value;
|
||||
value.AppendLiteral("rgb(");
|
||||
value.AppendInt(NS_GET_R(aValue));
|
||||
value.AppendLiteral(", ");
|
||||
value.AppendInt(NS_GET_G(aValue));
|
||||
value.AppendLiteral(", ");
|
||||
value.AppendInt(NS_GET_B(aValue));
|
||||
value.Append(')');
|
||||
|
||||
StyleInfo::Format(aValue, value);
|
||||
aFormattedValue = value;
|
||||
}
|
||||
|
||||
|
@ -426,6 +421,43 @@ nsBGColorTextAttr::GetColor(nsIFrame *aFrame, nscolor *aColor)
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ColorTextAttr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ColorTextAttr::ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
|
||||
nsTextAttr<nscolor>(!aFrame)
|
||||
{
|
||||
mRootNativeValue = aRootFrame->GetStyleColor()->mColor;
|
||||
mIsRootDefined = true;
|
||||
|
||||
if (aFrame) {
|
||||
mNativeValue = aFrame->GetStyleColor()->mColor;
|
||||
mIsDefined = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ColorTextAttr::GetValueFor(nsIContent* aContent, nscolor* aValue)
|
||||
{
|
||||
nsIFrame* frame = aContent->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
*aValue = frame->GetStyleColor()->mColor;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ColorTextAttr::Format(const nscolor& aValue, nsAString& aFormattedValue)
|
||||
{
|
||||
nsAutoString value;
|
||||
StyleInfo::Format(aValue, value);
|
||||
aFormattedValue = value;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsFontSizeTextAttr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -307,6 +307,25 @@ private:
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class is used for the work with 'color' text attribute in nsTextAttrsMgr
|
||||
* class.
|
||||
*/
|
||||
class ColorTextAttr : public nsTextAttr<nscolor>
|
||||
{
|
||||
public:
|
||||
ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
|
||||
|
||||
// nsITextAttr
|
||||
virtual nsIAtom* GetName() const { return nsGkAtoms::color; }
|
||||
|
||||
protected:
|
||||
// nsTextAttr
|
||||
virtual bool GetValueFor(nsIContent* aContent, nscolor* aValue);
|
||||
virtual void Format(const nscolor& aValue, nsAString& aFormattedValue);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class is used for the work with "font-size" text attribute in nsTextAttrsMgr
|
||||
* class.
|
||||
|
|
|
@ -192,6 +192,7 @@
|
|||
@BINPATH@/components/find.xpt
|
||||
@BINPATH@/components/fuel.xpt
|
||||
@BINPATH@/components/gfx.xpt
|
||||
@BINPATH@/components/html5.xpt
|
||||
@BINPATH@/components/htmlparser.xpt
|
||||
@BINPATH@/components/imglib2.xpt
|
||||
@BINPATH@/components/imgicon.xpt
|
||||
|
|
|
@ -190,6 +190,7 @@
|
|||
@BINPATH@/components/find.xpt
|
||||
@BINPATH@/components/fuel.xpt
|
||||
@BINPATH@/components/gfx.xpt
|
||||
@BINPATH@/components/html5.xpt
|
||||
@BINPATH@/components/htmlparser.xpt
|
||||
@BINPATH@/components/imglib2.xpt
|
||||
@BINPATH@/components/imgicon.xpt
|
||||
|
|
|
@ -1191,6 +1191,7 @@ xpicleanup@BIN_SUFFIX@
|
|||
components/fuel.xpt
|
||||
components/gfx.xpt
|
||||
components/gksvgrenderer.xpt
|
||||
components/html5.xpt
|
||||
components/htmlparser.xpt
|
||||
components/imgicon.xpt
|
||||
components/imglib2.xpt
|
||||
|
|
|
@ -181,8 +181,4 @@ radio[pane=paneSync] {
|
|||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#syncEnginesList {
|
||||
height: 10em;
|
||||
}
|
||||
|
||||
%endif
|
||||
|
|
|
@ -239,8 +239,4 @@ caption {
|
|||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#syncEnginesList {
|
||||
height: 10em;
|
||||
}
|
||||
|
||||
%endif
|
||||
|
|
|
@ -169,10 +169,6 @@ radio[pane=paneSync] {
|
|||
#syncAddDeviceLabel {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#syncEnginesList {
|
||||
height: 11em;
|
||||
}
|
||||
|
||||
%endif
|
||||
|
|
|
@ -99,6 +99,33 @@ def build_linux_headers(inst_dir):
|
|||
build_linux_headers_aux(inst_dir)
|
||||
with_env({"PATH" : aux_inst_dir + "/bin:%s" % os.environ["PATH"]}, f)
|
||||
|
||||
def build_gcc(stage_dir, is_stage_one):
|
||||
gcc_build_dir = stage_dir + '/gcc'
|
||||
tool_inst_dir = stage_dir + '/inst'
|
||||
lib_inst_dir = stage_dir + '/libinst'
|
||||
gcc_configure_args = ["--prefix=%s" % tool_inst_dir,
|
||||
"--enable-__cxa_atexit",
|
||||
"--with-gmp=%s" % lib_inst_dir,
|
||||
"--with-mpfr=%s" % lib_inst_dir,
|
||||
"--with-mpc=%s" % lib_inst_dir,
|
||||
"--enable-languages=c,c++",
|
||||
"--disable-multilib",
|
||||
"--disable-bootstrap"]
|
||||
if is_stage_one:
|
||||
# We build the stage1 gcc without shared libraries. Otherwise its
|
||||
# libgcc.so would depend on the system libc.so, which causes problems
|
||||
# when it tries to use that libgcc.so and the libc we are about to
|
||||
# build.
|
||||
gcc_configure_args.append("--disable-shared")
|
||||
|
||||
build_package(gcc_source_dir, gcc_build_dir, gcc_configure_args)
|
||||
|
||||
if is_stage_one:
|
||||
# The glibc build system uses -lgcc_eh, but at least in this setup
|
||||
# libgcc.a has all it needs.
|
||||
d = tool_inst_dir + "/lib/gcc/x86_64-unknown-linux-gnu/4.5.2/"
|
||||
os.symlink(d + "libgcc.a", d + "libgcc_eh.a")
|
||||
|
||||
def build_one_stage(env, stage_dir, is_stage_one):
|
||||
def f():
|
||||
build_one_stage_aux(stage_dir, is_stage_one)
|
||||
|
@ -129,33 +156,18 @@ def build_one_stage_aux(stage_dir, is_stage_one):
|
|||
build_package(binutils_source_dir, binutils_build_dir,
|
||||
["--prefix=%s" % tool_inst_dir])
|
||||
|
||||
gcc_build_dir = stage_dir + '/gcc'
|
||||
gcc_configure_args = ["--prefix=%s" % tool_inst_dir,
|
||||
"--enable-__cxa_atexit",
|
||||
"--with-gmp=%s" % lib_inst_dir,
|
||||
"--with-mpfr=%s" % lib_inst_dir,
|
||||
"--with-mpc=%s" % lib_inst_dir,
|
||||
"--enable-languages=c,c++",
|
||||
"--disable-multilib",
|
||||
"--disable-bootstrap"]
|
||||
# During stage one we have to build gcc first, this glibc doesn't even
|
||||
# build with gcc 4.6. During stage two, we have to build glibc first.
|
||||
# The problem is that libstdc++ is built with xgcc and if glibc has
|
||||
# not been built yet xgcc will use the system one.
|
||||
if is_stage_one:
|
||||
# We build the stage1 gcc without shared libraries. Otherwise its
|
||||
# libgcc.so would depend on the system libc.so, which causes problems
|
||||
# when it tries to use that libgcc.so and the libc we are about to
|
||||
# build.
|
||||
gcc_configure_args.append("--disable-shared")
|
||||
|
||||
build_package(gcc_source_dir, gcc_build_dir, gcc_configure_args)
|
||||
|
||||
if is_stage_one:
|
||||
# The glibc build system uses -lgcc_eh, but at least in this setup
|
||||
# libgcc.a has all it needs.
|
||||
d = tool_inst_dir + "/lib/gcc/x86_64-unknown-linux-gnu/4.5.2/"
|
||||
os.symlink(d + "libgcc.a", d + "libgcc_eh.a")
|
||||
|
||||
build_glibc({"CC" : tool_inst_dir + "/bin/gcc",
|
||||
"CXX" : tool_inst_dir + "/bin/g++"},
|
||||
stage_dir, tool_inst_dir)
|
||||
build_gcc(stage_dir, is_stage_one)
|
||||
build_glibc({"CC" : tool_inst_dir + "/bin/gcc",
|
||||
"CXX" : tool_inst_dir + "/bin/g++"},
|
||||
stage_dir, tool_inst_dir)
|
||||
else:
|
||||
build_glibc({}, stage_dir, tool_inst_dir)
|
||||
build_gcc(stage_dir, is_stage_one)
|
||||
|
||||
def build_tar_package(tar, name, base, directory):
|
||||
name = os.path.realpath(name)
|
||||
|
|
|
@ -318,7 +318,7 @@ if test -n "$gonkdir" ; then
|
|||
STLPORT_CPPFLAGS="-I$gonkdir/ndk/sources/cxx-stl/stlport/stlport/"
|
||||
STLPORT_LIBS="-lstlport"
|
||||
|
||||
CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/arch-arm/include -isystem $gonkdir/bionic/libc/kernel/arch-arm -isystem $gonkdir/bionic/libm/include -isystem $gonkdir/frameworks/base/opengl/include -isystem $gonkdir/frameworks/base/native/include -isystem $gonkdir/hardware/libhardware/include -isystem $gonkdir/hardware/libhardware_legacy/include -isystem $gonkdir/system/core/include -isystem $gonkdir/bionic -isystem $gonkdir/frameworks/base/include $STLPORT_CPPFLAGS $CPPFLAGS -isystem $gonkdir/frameworks/base/services/sensorservice"
|
||||
CPPFLAGS="-DANDROID -I$gonkdir/bionic/libc/include/ -I$gonkdir/bionic/libc/kernel/common -I$gonkdir/bionic/libc/arch-arm/include -I$gonkdir/bionic/libc/kernel/arch-arm -I$gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/hardware/libhardware_legacy/include -I$gonkdir/system/core/include -I$gonkdir/bionic -I$gonkdir/frameworks/base/include $STLPORT_CPPFLAGS $CPPFLAGS -I$gonkdir/frameworks/base/services/sensorservice"
|
||||
CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
|
||||
CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS"
|
||||
LIBS="$LIBS $STLPORT_LIBS"
|
||||
|
|
|
@ -1144,12 +1144,34 @@ public:
|
|||
* @param aSourceBuffer the string to parse as an HTML document
|
||||
* @param aTargetDocument the document object to parse into. Must not have
|
||||
* child nodes.
|
||||
* @param aScriptingEnabledForNoscriptParsing whether <noscript> is parsed
|
||||
* as if scripting was enabled
|
||||
* @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse
|
||||
* fragments is made, NS_ERROR_OUT_OF_MEMORY if aSourceBuffer is too
|
||||
* long and NS_OK otherwise.
|
||||
*/
|
||||
static nsresult ParseDocumentHTML(const nsAString& aSourceBuffer,
|
||||
nsIDocument* aTargetDocument);
|
||||
nsIDocument* aTargetDocument,
|
||||
bool aScriptingEnabledForNoscriptParsing);
|
||||
|
||||
/**
|
||||
* Converts HTML source to plain text by parsing the source and using the
|
||||
* plain text serializer on the resulting tree.
|
||||
*
|
||||
* @param aSourceBuffer the string to parse as an HTML document
|
||||
* @param aResultBuffer the string where the plain text result appears;
|
||||
* may be the same string as aSourceBuffer
|
||||
* @param aFlags Flags from nsIDocumentEncoder.
|
||||
* @param aWrapCol Number of columns after which to line wrap; 0 for no
|
||||
* auto-wrapping
|
||||
* @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse
|
||||
* fragments is made, NS_ERROR_OUT_OF_MEMORY if aSourceBuffer is too
|
||||
* long and NS_OK otherwise.
|
||||
*/
|
||||
static nsresult ConvertToPlainText(const nsAString& aSourceBuffer,
|
||||
nsAString& aResultBuffer,
|
||||
PRUint32 aFlags,
|
||||
PRUint32 aWrapCol);
|
||||
|
||||
/**
|
||||
* Creates a new XML document, which is marked to be loaded as data.
|
||||
|
@ -1941,6 +1963,32 @@ public:
|
|||
*/
|
||||
static bool URIIsChromeOrInPref(nsIURI *aURI, const char *aPref);
|
||||
|
||||
/**
|
||||
* This will parse aSource, to extract the value of the pseudo attribute
|
||||
* with the name specified in aName. See
|
||||
* http://www.w3.org/TR/xml-stylesheet/#NT-StyleSheetPI for the specification
|
||||
* which is used to parse aSource.
|
||||
*
|
||||
* @param aSource the string to parse
|
||||
* @param aName the name of the attribute to get the value for
|
||||
* @param aValue [out] the value for the attribute with name specified in
|
||||
* aAttribute. Empty if the attribute isn't present.
|
||||
* @return true if the attribute exists and was successfully parsed.
|
||||
* false if the attribute doesn't exist, or has a malformed
|
||||
* value, such as an unknown or unterminated entity.
|
||||
*/
|
||||
static bool GetPseudoAttributeValue(const nsString& aSource, nsIAtom *aName,
|
||||
nsAString& aValue);
|
||||
|
||||
/**
|
||||
* Returns true if the language name is a version of JavaScript and
|
||||
* false otherwise
|
||||
*/
|
||||
static bool IsJavaScriptLanguage(const nsString& aName, PRUint32 *aVerFlags);
|
||||
|
||||
static void SplitMimeType(const nsAString& aValue, nsString& aType,
|
||||
nsString& aParams);
|
||||
|
||||
private:
|
||||
static bool InitializeEventTable();
|
||||
|
||||
|
|
|
@ -172,7 +172,8 @@ interface nsIDocumentEncoder : nsISupports
|
|||
|
||||
/**
|
||||
* Output the content of noframes elements (only for serializing
|
||||
* to plaintext).
|
||||
* to plaintext). (Used only internally in the plain text serializer;
|
||||
* ignored if passed by the caller.)
|
||||
*/
|
||||
const unsigned long OutputNoFramesContent = (1 << 12);
|
||||
|
||||
|
|
|
@ -127,7 +127,6 @@ CPPSRCS = \
|
|||
nsNodeIterator.cpp \
|
||||
nsNodeUtils.cpp \
|
||||
nsObjectLoadingContent.cpp \
|
||||
nsParserUtils.cpp \
|
||||
nsPlainTextSerializer.cpp \
|
||||
nsPropertyTable.cpp \
|
||||
nsRange.cpp \
|
||||
|
|
|
@ -80,7 +80,6 @@
|
|||
#include "nsIPrompt.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
@ -712,7 +711,7 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement,
|
|||
|
||||
nsAutoString mimeType;
|
||||
nsAutoString params;
|
||||
nsParserUtils::SplitMimeType(aType, mimeType, params);
|
||||
nsContentUtils::SplitMimeType(aType, mimeType, params);
|
||||
|
||||
// see bug 18817
|
||||
if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
|
||||
|
|
|
@ -180,6 +180,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
|||
#include "nsIViewManager.h"
|
||||
#include "nsEventStateManager.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsParserConstants.h"
|
||||
|
||||
#ifdef IBMBIDI
|
||||
#include "nsIBidiKeyboard.h"
|
||||
|
@ -720,6 +721,185 @@ nsContentUtils::URIIsChromeOrInPref(nsIURI *aURI, const char *aPref)
|
|||
return false;
|
||||
}
|
||||
|
||||
#define SKIP_WHITESPACE(iter, end_iter, end_res) \
|
||||
while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
|
||||
++(iter); \
|
||||
} \
|
||||
if ((iter) == (end_iter)) { \
|
||||
return (end_res); \
|
||||
}
|
||||
|
||||
#define SKIP_ATTR_NAME(iter, end_iter) \
|
||||
while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
|
||||
*(iter) != '=') { \
|
||||
++(iter); \
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::GetPseudoAttributeValue(const nsString& aSource, nsIAtom *aName,
|
||||
nsAString& aValue)
|
||||
{
|
||||
aValue.Truncate();
|
||||
|
||||
const PRUnichar *start = aSource.get();
|
||||
const PRUnichar *end = start + aSource.Length();
|
||||
const PRUnichar *iter;
|
||||
|
||||
while (start != end) {
|
||||
SKIP_WHITESPACE(start, end, false)
|
||||
iter = start;
|
||||
SKIP_ATTR_NAME(iter, end)
|
||||
|
||||
if (start == iter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember the attr name.
|
||||
const nsDependentSubstring & attrName = Substring(start, iter);
|
||||
|
||||
// Now check whether this is a valid name="value" pair.
|
||||
start = iter;
|
||||
SKIP_WHITESPACE(start, end, false)
|
||||
if (*start != '=') {
|
||||
// No '=', so this is not a name="value" pair. We don't know
|
||||
// what it is, and we have no way to handle it.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Have to skip the value.
|
||||
++start;
|
||||
SKIP_WHITESPACE(start, end, false)
|
||||
PRUnichar q = *start;
|
||||
if (q != kQuote && q != kApostrophe) {
|
||||
// Not a valid quoted value, so bail.
|
||||
return false;
|
||||
}
|
||||
|
||||
++start; // Point to the first char of the value.
|
||||
iter = start;
|
||||
|
||||
while (iter != end && *iter != q) {
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (iter == end) {
|
||||
// Oops, unterminated quoted string.
|
||||
return false;
|
||||
}
|
||||
|
||||
// At this point attrName holds the name of the "attribute" and
|
||||
// the value is between start and iter.
|
||||
|
||||
if (aName->Equals(attrName)) {
|
||||
nsIParserService* parserService = nsContentUtils::GetParserService();
|
||||
NS_ENSURE_TRUE(parserService, false);
|
||||
|
||||
// We'll accumulate as many characters as possible (until we hit either
|
||||
// the end of the string or the beginning of an entity). Chunks will be
|
||||
// delimited by start and chunkEnd.
|
||||
const PRUnichar *chunkEnd = start;
|
||||
while (chunkEnd != iter) {
|
||||
if (*chunkEnd == kLessThan) {
|
||||
aValue.Truncate();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*chunkEnd == kAmpersand) {
|
||||
aValue.Append(start, chunkEnd - start);
|
||||
|
||||
// Point to first character after the ampersand.
|
||||
++chunkEnd;
|
||||
|
||||
const PRUnichar *afterEntity;
|
||||
PRUnichar result[2];
|
||||
PRUint32 count =
|
||||
parserService->DecodeEntity(chunkEnd, iter, &afterEntity, result);
|
||||
if (count == 0) {
|
||||
aValue.Truncate();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aValue.Append(result, count);
|
||||
|
||||
// Advance to after the entity and begin a new chunk.
|
||||
start = chunkEnd = afterEntity;
|
||||
}
|
||||
else {
|
||||
++chunkEnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Append remainder.
|
||||
aValue.Append(start, iter - start);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Resume scanning after the end of the attribute value (past the quote
|
||||
// char).
|
||||
start = iter + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::IsJavaScriptLanguage(const nsString& aName, PRUint32 *aFlags)
|
||||
{
|
||||
JSVersion version = JSVERSION_UNKNOWN;
|
||||
|
||||
if (aName.LowerCaseEqualsLiteral("javascript") ||
|
||||
aName.LowerCaseEqualsLiteral("livescript") ||
|
||||
aName.LowerCaseEqualsLiteral("mocha")) {
|
||||
version = JSVERSION_DEFAULT;
|
||||
} else if (aName.LowerCaseEqualsLiteral("javascript1.0")) {
|
||||
version = JSVERSION_1_0;
|
||||
} else if (aName.LowerCaseEqualsLiteral("javascript1.1")) {
|
||||
version = JSVERSION_1_1;
|
||||
} else if (aName.LowerCaseEqualsLiteral("javascript1.2")) {
|
||||
version = JSVERSION_1_2;
|
||||
} else if (aName.LowerCaseEqualsLiteral("javascript1.3")) {
|
||||
version = JSVERSION_1_3;
|
||||
} else if (aName.LowerCaseEqualsLiteral("javascript1.4")) {
|
||||
version = JSVERSION_1_4;
|
||||
} else if (aName.LowerCaseEqualsLiteral("javascript1.5")) {
|
||||
version = JSVERSION_1_5;
|
||||
} else if (aName.LowerCaseEqualsLiteral("javascript1.6")) {
|
||||
version = JSVERSION_1_6;
|
||||
} else if (aName.LowerCaseEqualsLiteral("javascript1.7")) {
|
||||
version = JSVERSION_1_7;
|
||||
} else if (aName.LowerCaseEqualsLiteral("javascript1.8")) {
|
||||
version = JSVERSION_1_8;
|
||||
}
|
||||
|
||||
if (version == JSVERSION_UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
*aFlags = version;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
|
||||
nsString& aParams)
|
||||
{
|
||||
aType.Truncate();
|
||||
aParams.Truncate();
|
||||
PRInt32 semiIndex = aValue.FindChar(PRUnichar(';'));
|
||||
if (-1 != semiIndex) {
|
||||
aType = Substring(aValue, 0, semiIndex);
|
||||
aParams = Substring(aValue, semiIndex + 1,
|
||||
aValue.Length() - (semiIndex + 1));
|
||||
aParams.StripWhitespace();
|
||||
}
|
||||
else {
|
||||
aType = aValue;
|
||||
}
|
||||
aType.StripWhitespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Access a cached parser service. Don't addref. We need only one
|
||||
* reference to it and this class has that one.
|
||||
|
@ -3747,7 +3927,8 @@ nsContentUtils::ParseFragmentHTML(const nsAString& aSourceBuffer,
|
|||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::ParseDocumentHTML(const nsAString& aSourceBuffer,
|
||||
nsIDocument* aTargetDocument)
|
||||
nsIDocument* aTargetDocument,
|
||||
bool aScriptingEnabledForNoscriptParsing)
|
||||
{
|
||||
if (nsContentUtils::sFragmentParsingActive) {
|
||||
NS_NOTREACHED("Re-entrant fragment parsing attempted.");
|
||||
|
@ -3761,7 +3942,8 @@ nsContentUtils::ParseDocumentHTML(const nsAString& aSourceBuffer,
|
|||
}
|
||||
nsresult rv =
|
||||
sHTMLFragmentParser->ParseDocument(aSourceBuffer,
|
||||
aTargetDocument);
|
||||
aTargetDocument,
|
||||
aScriptingEnabledForNoscriptParsing);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -3812,6 +3994,44 @@ nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
|
|||
return rv;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
|
||||
nsAString& aResultBuffer,
|
||||
PRUint32 aFlags,
|
||||
PRUint32 aWrapCol)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_NewURI(getter_AddRefs(uri), "about:blank");
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
do_CreateInstance("@mozilla.org/nullprincipal;1");
|
||||
nsCOMPtr<nsIDOMDocument> domDocument;
|
||||
nsresult rv = nsContentUtils::CreateDocument(EmptyString(),
|
||||
EmptyString(),
|
||||
nsnull,
|
||||
uri,
|
||||
uri,
|
||||
principal,
|
||||
nsnull,
|
||||
DocumentFlavorHTML,
|
||||
getter_AddRefs(domDocument));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
|
||||
rv = nsContentUtils::ParseDocumentHTML(aSourceBuffer, document,
|
||||
!(aFlags & nsIDocumentEncoder::OutputNoScriptContent));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocumentEncoder> encoder = do_CreateInstance(
|
||||
"@mozilla.org/layout/documentEncoder;1?type=text/plain");
|
||||
|
||||
rv = encoder->Init(domDocument, NS_LITERAL_STRING("text/plain"), aFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
encoder->SetWrapColumn(aWrapCol);
|
||||
|
||||
return encoder->EncodeToString(aResultBuffer);
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
#include "nsMimeTypes.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
|
|
|
@ -102,7 +102,7 @@ nsDOMParser::ParseFromString(const PRUnichar *str,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
|
||||
nsDependentString sourceBuffer(str);
|
||||
rv = nsContentUtils::ParseDocumentHTML(sourceBuffer, document);
|
||||
rv = nsContentUtils::ParseDocumentHTML(sourceBuffer, document, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Keep the XULXBL state, base URL and principal setting in sync with the
|
||||
|
|
|
@ -2901,6 +2901,14 @@ nsGenericElement::GetAttributeNodeNS(const nsAString& aNamespaceURI,
|
|||
|
||||
OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNodeNS);
|
||||
|
||||
return GetAttributeNodeNSInternal(aNamespaceURI, aLocalName, aReturn);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericElement::GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName,
|
||||
nsIDOMAttr** aReturn)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNamedNodeMap> map;
|
||||
nsresult rv = GetAttributes(getter_AddRefs(map));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -5208,8 +5216,8 @@ nsGenericElement::SetAttrAndNotify(PRInt32 aNamespaceID,
|
|||
nsCOMPtr<nsIDOMAttr> attrNode;
|
||||
nsAutoString ns;
|
||||
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
|
||||
GetAttributeNodeNS(ns, nsDependentAtomString(aName),
|
||||
getter_AddRefs(attrNode));
|
||||
GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
|
||||
getter_AddRefs(attrNode));
|
||||
mutation.mRelatedNode = attrNode;
|
||||
|
||||
mutation.mAttrName = aName;
|
||||
|
@ -5388,8 +5396,8 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
if (hasMutationListeners) {
|
||||
nsAutoString ns;
|
||||
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
|
||||
GetAttributeNodeNS(ns, nsDependentAtomString(aName),
|
||||
getter_AddRefs(attrNode));
|
||||
GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
|
||||
getter_AddRefs(attrNode));
|
||||
}
|
||||
|
||||
// Clear binding to nsIDOMNamedNodeMap
|
||||
|
|
|
@ -794,6 +794,10 @@ protected:
|
|||
return this;
|
||||
}
|
||||
|
||||
nsresult GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName,
|
||||
nsIDOMAttr** aReturn);
|
||||
|
||||
public:
|
||||
// Because of a bug in MS C++ compiler nsDOMSlots must be declared public,
|
||||
// otherwise nsXULElement::nsXULSlots doesn't compile.
|
||||
|
|
|
@ -1,236 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Namespace class for some static parsing-related methods.
|
||||
*/
|
||||
|
||||
#include "nsParserUtils.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIParserService.h"
|
||||
#include "nsParserConstants.h"
|
||||
|
||||
#define SKIP_WHITESPACE(iter, end_iter, end_res) \
|
||||
while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
|
||||
++(iter); \
|
||||
} \
|
||||
if ((iter) == (end_iter)) { \
|
||||
return (end_res); \
|
||||
}
|
||||
|
||||
#define SKIP_ATTR_NAME(iter, end_iter) \
|
||||
while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
|
||||
*(iter) != '=') { \
|
||||
++(iter); \
|
||||
}
|
||||
|
||||
bool
|
||||
nsParserUtils::GetQuotedAttributeValue(const nsString& aSource, nsIAtom *aName,
|
||||
nsAString& aValue)
|
||||
{
|
||||
aValue.Truncate();
|
||||
|
||||
const PRUnichar *start = aSource.get();
|
||||
const PRUnichar *end = start + aSource.Length();
|
||||
const PRUnichar *iter;
|
||||
|
||||
while (start != end) {
|
||||
SKIP_WHITESPACE(start, end, false)
|
||||
iter = start;
|
||||
SKIP_ATTR_NAME(iter, end)
|
||||
|
||||
if (start == iter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember the attr name.
|
||||
const nsDependentSubstring & attrName = Substring(start, iter);
|
||||
|
||||
// Now check whether this is a valid name="value" pair.
|
||||
start = iter;
|
||||
SKIP_WHITESPACE(start, end, false)
|
||||
if (*start != '=') {
|
||||
// No '=', so this is not a name="value" pair. We don't know
|
||||
// what it is, and we have no way to handle it.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Have to skip the value.
|
||||
++start;
|
||||
SKIP_WHITESPACE(start, end, false)
|
||||
PRUnichar q = *start;
|
||||
if (q != kQuote && q != kApostrophe) {
|
||||
// Not a valid quoted value, so bail.
|
||||
return false;
|
||||
}
|
||||
|
||||
++start; // Point to the first char of the value.
|
||||
iter = start;
|
||||
|
||||
while (iter != end && *iter != q) {
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (iter == end) {
|
||||
// Oops, unterminated quoted string.
|
||||
return false;
|
||||
}
|
||||
|
||||
// At this point attrName holds the name of the "attribute" and
|
||||
// the value is between start and iter.
|
||||
|
||||
if (aName->Equals(attrName)) {
|
||||
nsIParserService* parserService = nsContentUtils::GetParserService();
|
||||
NS_ENSURE_TRUE(parserService, false);
|
||||
|
||||
// We'll accumulate as many characters as possible (until we hit either
|
||||
// the end of the string or the beginning of an entity). Chunks will be
|
||||
// delimited by start and chunkEnd.
|
||||
const PRUnichar *chunkEnd = start;
|
||||
while (chunkEnd != iter) {
|
||||
if (*chunkEnd == kLessThan) {
|
||||
aValue.Truncate();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*chunkEnd == kAmpersand) {
|
||||
aValue.Append(start, chunkEnd - start);
|
||||
|
||||
// Point to first character after the ampersand.
|
||||
++chunkEnd;
|
||||
|
||||
const PRUnichar *afterEntity;
|
||||
PRUnichar result[2];
|
||||
PRUint32 count =
|
||||
parserService->DecodeEntity(chunkEnd, iter, &afterEntity, result);
|
||||
if (count == 0) {
|
||||
aValue.Truncate();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aValue.Append(result, count);
|
||||
|
||||
// Advance to after the entity and begin a new chunk.
|
||||
start = chunkEnd = afterEntity;
|
||||
}
|
||||
else {
|
||||
++chunkEnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Append remainder.
|
||||
aValue.Append(start, iter - start);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Resume scanning after the end of the attribute value (past the quote
|
||||
// char).
|
||||
start = iter + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true if the language name is a version of JavaScript and
|
||||
// false otherwise
|
||||
bool
|
||||
nsParserUtils::IsJavaScriptLanguage(const nsString& aName, PRUint32 *aFlags)
|
||||
{
|
||||
JSVersion version = JSVERSION_UNKNOWN;
|
||||
|
||||
if (aName.LowerCaseEqualsLiteral("javascript") ||
|
||||
aName.LowerCaseEqualsLiteral("livescript") ||
|
||||
aName.LowerCaseEqualsLiteral("mocha")) {
|
||||
version = JSVERSION_DEFAULT;
|
||||
}
|
||||
else if (aName.LowerCaseEqualsLiteral("javascript1.0")) {
|
||||
version = JSVERSION_1_0;
|
||||
}
|
||||
else if (aName.LowerCaseEqualsLiteral("javascript1.1")) {
|
||||
version = JSVERSION_1_1;
|
||||
}
|
||||
else if (aName.LowerCaseEqualsLiteral("javascript1.2")) {
|
||||
version = JSVERSION_1_2;
|
||||
}
|
||||
else if (aName.LowerCaseEqualsLiteral("javascript1.3")) {
|
||||
version = JSVERSION_1_3;
|
||||
}
|
||||
else if (aName.LowerCaseEqualsLiteral("javascript1.4")) {
|
||||
version = JSVERSION_1_4;
|
||||
}
|
||||
else if (aName.LowerCaseEqualsLiteral("javascript1.5")) {
|
||||
version = JSVERSION_1_5;
|
||||
}
|
||||
else if (aName.LowerCaseEqualsLiteral("javascript1.6")) {
|
||||
version = JSVERSION_1_6;
|
||||
}
|
||||
else if (aName.LowerCaseEqualsLiteral("javascript1.7")) {
|
||||
version = JSVERSION_1_7;
|
||||
}
|
||||
else if (aName.LowerCaseEqualsLiteral("javascript1.8")) {
|
||||
version = JSVERSION_1_8;
|
||||
}
|
||||
if (version == JSVERSION_UNKNOWN)
|
||||
return false;
|
||||
*aFlags = version;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsParserUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
|
||||
nsString& aParams)
|
||||
{
|
||||
aType.Truncate();
|
||||
aParams.Truncate();
|
||||
PRInt32 semiIndex = aValue.FindChar(PRUnichar(';'));
|
||||
if (-1 != semiIndex) {
|
||||
aType = Substring(aValue, 0, semiIndex);
|
||||
aParams = Substring(aValue, semiIndex + 1,
|
||||
aValue.Length() - (semiIndex + 1));
|
||||
aParams.StripWhitespace();
|
||||
}
|
||||
else {
|
||||
aType = aValue;
|
||||
}
|
||||
aType.StripWhitespace();
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Namespace class for some static parsing-related methods.
|
||||
*/
|
||||
|
||||
#ifndef nsParserUtils_h__
|
||||
#define nsParserUtils_h__
|
||||
|
||||
#include "nsString.h"
|
||||
class nsIAtom;
|
||||
|
||||
class nsParserUtils {
|
||||
public:
|
||||
/**
|
||||
* This will parse aSource, to extract the value of the pseudo attribute
|
||||
* with the name specified in aName. See
|
||||
* http://www.w3.org/TR/xml-stylesheet/#NT-StyleSheetPI for the specification
|
||||
* which is used to parse aSource.
|
||||
*
|
||||
* @param aSource the string to parse
|
||||
* @param aName the name of the attribute to get the value for
|
||||
* @param aValue [out] the value for the attribute with name specified in
|
||||
* aAttribute. Empty if the attribute isn't present.
|
||||
* @return true if the attribute exists and was successfully parsed.
|
||||
* false if the attribute doesn't exist, or has a malformed
|
||||
* value, such as an unknown or unterminated entity.
|
||||
*/
|
||||
static bool
|
||||
GetQuotedAttributeValue(const nsString& aSource, nsIAtom *aName,
|
||||
nsAString& aValue);
|
||||
|
||||
static bool
|
||||
IsJavaScriptLanguage(const nsString& aName, PRUint32 *aVerFlags);
|
||||
|
||||
static void
|
||||
SplitMimeType(const nsAString& aValue, nsString& aType,
|
||||
nsString& aParams);
|
||||
};
|
||||
|
||||
#endif // nsParserUtils_h__
|
||||
|
||||
|
||||
|
|
@ -44,7 +44,6 @@
|
|||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsIContent.h"
|
||||
|
@ -509,14 +508,14 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
|
|||
if (scriptContent->IsHTML()) {
|
||||
scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::language, language);
|
||||
if (!language.IsEmpty()) {
|
||||
if (nsParserUtils::IsJavaScriptLanguage(language, &version))
|
||||
if (nsContentUtils::IsJavaScriptLanguage(language, &version))
|
||||
typeID = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
else
|
||||
typeID = nsIProgrammingLanguage::UNKNOWN;
|
||||
// IE, Opera, etc. do not respect language version, so neither should
|
||||
// we at this late date in the browser wars saga. Note that this change
|
||||
// affects HTML but not XUL or SVG (but note also that XUL has its own
|
||||
// code to check nsParserUtils::IsJavaScriptLanguage -- that's probably
|
||||
// code to check nsContentUtils::IsJavaScriptLanguage -- that's probably
|
||||
// a separate bug, one we may not be able to fix short of XUL2). See
|
||||
// bug 255895 (https://bugzilla.mozilla.org/show_bug.cgi?id=255895).
|
||||
NS_ASSERTION(JSVERSION_DEFAULT == 0,
|
||||
|
|
|
@ -37,37 +37,18 @@
|
|||
|
||||
#include "TestHarness.h"
|
||||
|
||||
#include "nsIParser.h"
|
||||
#include "nsIHTMLToTextSink.h"
|
||||
#include "nsIParser.h"
|
||||
#include "nsIContentSink.h"
|
||||
#include "nsIParserService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsParserCIID.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
|
||||
#include "nsIParserUtils.h"
|
||||
|
||||
void
|
||||
ConvertBufToPlainText(nsString &aConBuf, int aFlag)
|
||||
{
|
||||
nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID);
|
||||
if (parser) {
|
||||
nsCOMPtr<nsIContentSink> sink;
|
||||
sink = do_CreateInstance(NS_PLAINTEXTSINK_CONTRACTID);
|
||||
if (sink) {
|
||||
nsCOMPtr<nsIHTMLToTextSink> textSink(do_QueryInterface(sink));
|
||||
if (textSink) {
|
||||
nsAutoString convertedText;
|
||||
textSink->Initialize(&convertedText, aFlag, 72);
|
||||
parser->SetContentSink(sink);
|
||||
parser->Parse(aConBuf, 0, NS_LITERAL_CSTRING("text/html"), true);
|
||||
aConBuf = convertedText;
|
||||
}
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIParserUtils> utils =
|
||||
do_GetService(NS_PARSERUTILS_CONTRACTID);
|
||||
utils->ConvertToPlainText(aConBuf, aFlag, 72, aConBuf);
|
||||
}
|
||||
|
||||
// Test for ASCII with format=flowed; delsp=yes
|
||||
|
|
|
@ -71,6 +71,7 @@ _CHROME_FILES = \
|
|||
test_bug574596.html \
|
||||
test_bug683852.xul \
|
||||
test_bug599295.html \
|
||||
test_bug650784.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=650776
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 650776</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650776">Mozilla Bug 650776</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 650776 **/
|
||||
|
||||
var c = Components.interfaces.nsIDocumentEncoder;
|
||||
var s = Components.classes["@mozilla.org/parserutils;1"]
|
||||
.getService(Components.interfaces.nsIParserUtils);
|
||||
|
||||
is(s.convertToPlainText("foo", c.OutputLFLineBreak, 0), "foo", "Wrong conversion result 1");
|
||||
is(s.convertToPlainText("foo foo foo", c.OutputWrap | c.OutputLFLineBreak, 7), "foo foo\nfoo", "Wrong conversion result 2");
|
||||
is(s.convertToPlainText("<body><noscript>b<span>a</span>r</noscript>foo", c.OutputLFLineBreak, 0), "foo", "Wrong conversion result 3");
|
||||
is(s.convertToPlainText("<body><noscript>b<span>a</span>r</noscript>foo", c.OutputNoScriptContent, 0), "barfoo", "Wrong conversion result 4");
|
||||
is(s.convertToPlainText("foo\u00A0bar", c.OutputPersistNBSP | c.OutputLFLineBreak, 0), "foo\u00A0bar", "Wrong conversion result 5");
|
||||
is(s.convertToPlainText("foo\u00A0bar", c.OutputLFLineBreak, 0), "foo bar", "Wrong conversion result 6");
|
||||
is(s.convertToPlainText("<body><noframes>bar</noframes>foo", c.OutputLFLineBreak, 0), "foo", "Wrong conversion result 7");
|
||||
// OutputNoFramesContent doesn't actually work, because the flag gets overridden by
|
||||
// the browser.frames.enabled pref in all cases.
|
||||
is(s.convertToPlainText("<body><noframes>bar</noframes>foo", c.OutputNoFramesContent | c.OutputLFLineBreak, 0), "foo", "Wrong conversion result 8");
|
||||
is(s.convertToPlainText("<i>foo</i> <b>bar</b>", c.OutputFormatted | c.OutputLFLineBreak, 0), "/foo/ *bar*\n", "Wrong conversion result 9");
|
||||
is(s.convertToPlainText("<p>foo</p> <p>bar</p>", c.OutputLFLineBreak, 0), "foo\n\nbar", "Wrong conversion result 10");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<html>
|
||||
<script language=javascript>
|
||||
|
||||
function draw() {
|
||||
var canv = document.getElementById("canv");
|
||||
var ctx = canv.getContext("2d");
|
||||
try {
|
||||
canv.width = 50000;
|
||||
} catch (e) { }
|
||||
|
||||
ctx.clearRect(0, 0, 10, 10);
|
||||
}
|
||||
|
||||
</script>
|
||||
<body onload="draw()">
|
||||
<canvas id="canv" width="5" height="5"></canvas>
|
||||
</body>
|
||||
</html>
|
|
@ -3,3 +3,4 @@ load 421715-1.html
|
|||
load 553938-1.html
|
||||
load 647480.html
|
||||
load 0px-size-font-667225.html
|
||||
skip-if(cocoaWidget&&layersGPUAccelerated) load 729116.html # bug 731117
|
||||
|
|
|
@ -362,8 +362,6 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
|||
|
||||
/*** end of early success return cases ***/
|
||||
|
||||
ScopedGfxFeatureReporter reporter("WebGL");
|
||||
|
||||
// At this point we know that the old context is not going to survive, even though we still don't
|
||||
// know if creating the new context will succeed.
|
||||
DestroyResourcesAndContext();
|
||||
|
@ -386,6 +384,8 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
|||
bool verbose =
|
||||
Preferences::GetBool("webgl.verbose", false);
|
||||
|
||||
ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
|
||||
|
||||
if (disabled)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
using namespace mozilla;
|
||||
|
||||
|
||||
class WebGLMemoryMultiReporter : public nsIMemoryMultiReporter
|
||||
class WebGLMemoryMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
|
|
@ -1306,6 +1306,10 @@ nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, PRInt3
|
|||
mTarget = target;
|
||||
} else {
|
||||
mValid = false;
|
||||
// Create a dummy target in the hopes that it will help us deal with users
|
||||
// calling into us after having changed the size where the size resulted
|
||||
// in an inability to create a correct DrawTarget.
|
||||
mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
|
||||
}
|
||||
|
||||
mResetLayer = true;
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#include "nsIDOMEvent.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsAsyncDOMEvent.h"
|
||||
|
@ -439,7 +438,7 @@ nsHTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
|
|||
nsAutoString mimeType;
|
||||
nsAutoString notUsed;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType);
|
||||
nsParserUtils::SplitMimeType(aType, mimeType, notUsed);
|
||||
nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
|
||||
if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
|
@ -347,7 +346,7 @@ nsHTMLStyleElement::GetStyleSheetInfo(nsAString& aTitle,
|
|||
|
||||
nsAutoString mimeType;
|
||||
nsAutoString notUsed;
|
||||
nsParserUtils::SplitMimeType(aType, mimeType, notUsed);
|
||||
nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
|
||||
if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIParser.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
|
|
@ -146,6 +146,11 @@ nsMathMLElement::ParseAttribute(PRInt32 aNamespaceID,
|
|||
aValue, aResult);
|
||||
}
|
||||
|
||||
static nsGenericElement::MappedAttributeEntry sMtableStyles[] = {
|
||||
{ &nsGkAtoms::width },
|
||||
{ nsnull }
|
||||
};
|
||||
|
||||
static nsGenericElement::MappedAttributeEntry sTokenStyles[] = {
|
||||
{ &nsGkAtoms::mathsize_ },
|
||||
{ &nsGkAtoms::fontsize_ },
|
||||
|
@ -171,6 +176,10 @@ static nsGenericElement::MappedAttributeEntry sCommonPresStyles[] = {
|
|||
bool
|
||||
nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
||||
{
|
||||
static const MappedAttributeEntry* const mtableMap[] = {
|
||||
sMtableStyles,
|
||||
sCommonPresStyles
|
||||
};
|
||||
static const MappedAttributeEntry* const tokenMap[] = {
|
||||
sTokenStyles,
|
||||
sCommonPresStyles
|
||||
|
@ -194,6 +203,9 @@ nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
|||
tag == nsGkAtoms::math)
|
||||
return FindAttributeDependence(aAttribute, mstyleMap);
|
||||
|
||||
if (tag == nsGkAtoms::mtable_)
|
||||
return FindAttributeDependence(aAttribute, mtableMap);
|
||||
|
||||
if (tag == nsGkAtoms::maction_ ||
|
||||
tag == nsGkAtoms::maligngroup_ ||
|
||||
tag == nsGkAtoms::malignmark_ ||
|
||||
|
@ -211,7 +223,6 @@ nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
|||
tag == nsGkAtoms::msub_ ||
|
||||
tag == nsGkAtoms::msubsup_ ||
|
||||
tag == nsGkAtoms::msup_ ||
|
||||
tag == nsGkAtoms::mtable_ ||
|
||||
tag == nsGkAtoms::mtd_ ||
|
||||
tag == nsGkAtoms::mtr_ ||
|
||||
tag == nsGkAtoms::munder_ ||
|
||||
|
@ -459,6 +470,19 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
|||
colorValue->SetColorValue(color);
|
||||
}
|
||||
}
|
||||
|
||||
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
|
||||
// width: value
|
||||
nsCSSValue* width = aData->ValueForWidth();
|
||||
if (width->GetUnit() == eCSSUnit_Null) {
|
||||
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
|
||||
// This does not handle auto and unitless values
|
||||
if (value && value->Type() == nsAttrValue::eString) {
|
||||
ParseNumericValue(value->GetStringValue(), *width, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
#include "nsGkAtoms.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsXMLProcessingInstruction.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
nsresult
|
||||
NS_NewXMLProcessingInstruction(nsIContent** aInstancePtrResult,
|
||||
|
@ -129,7 +129,7 @@ nsXMLProcessingInstruction::GetAttrValue(nsIAtom *aName, nsAString& aValue)
|
|||
nsAutoString data;
|
||||
|
||||
GetData(data);
|
||||
return nsParserUtils::GetQuotedAttributeValue(data, aName, aValue);
|
||||
return nsContentUtils::GetPseudoAttributeValue(data, aName, aValue);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsXMLProcessingInstruction.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
@ -209,10 +208,12 @@ nsXMLStylesheetPI::GetStyleSheetInfo(nsAString& aTitle,
|
|||
nsAutoString data;
|
||||
GetData(data);
|
||||
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::title, aTitle);
|
||||
nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::title, aTitle);
|
||||
|
||||
nsAutoString alternate;
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::alternate, alternate);
|
||||
nsContentUtils::GetPseudoAttributeValue(data,
|
||||
nsGkAtoms::alternate,
|
||||
alternate);
|
||||
|
||||
// if alternate, does it have title?
|
||||
if (alternate.EqualsLiteral("yes")) {
|
||||
|
@ -223,13 +224,13 @@ nsXMLStylesheetPI::GetStyleSheetInfo(nsAString& aTitle,
|
|||
*aIsAlternate = true;
|
||||
}
|
||||
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::media, aMedia);
|
||||
nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::media, aMedia);
|
||||
|
||||
nsAutoString type;
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::type, type);
|
||||
nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type);
|
||||
|
||||
nsAutoString mimeType, notUsed;
|
||||
nsParserUtils::SplitMimeType(type, mimeType, notUsed);
|
||||
nsContentUtils::SplitMimeType(type, mimeType, notUsed);
|
||||
if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
|
||||
aType.Assign(type);
|
||||
return;
|
||||
|
|
|
@ -68,7 +68,6 @@
|
|||
#include "prtime.h"
|
||||
#include "prlog.h"
|
||||
#include "prmem.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsGenericElement.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
|
@ -265,11 +264,11 @@ CheckXSLTParamPI(nsIDOMProcessingInstruction* aPi,
|
|||
if (target.EqualsLiteral("xslt-param-namespace")) {
|
||||
aPi->GetData(data);
|
||||
nsAutoString prefix, namespaceAttr;
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::prefix,
|
||||
prefix);
|
||||
nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::prefix,
|
||||
prefix);
|
||||
if (!prefix.IsEmpty() &&
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::_namespace,
|
||||
namespaceAttr)) {
|
||||
nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::_namespace,
|
||||
namespaceAttr)) {
|
||||
aProcessor->AddXSLTParamNamespace(prefix, namespaceAttr);
|
||||
}
|
||||
}
|
||||
|
@ -278,14 +277,14 @@ CheckXSLTParamPI(nsIDOMProcessingInstruction* aPi,
|
|||
else if (target.EqualsLiteral("xslt-param")) {
|
||||
aPi->GetData(data);
|
||||
nsAutoString name, namespaceAttr, select, value;
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::name,
|
||||
name);
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::_namespace,
|
||||
namespaceAttr);
|
||||
if (!nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::select, select)) {
|
||||
nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::name,
|
||||
name);
|
||||
nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::_namespace,
|
||||
namespaceAttr);
|
||||
if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::select, select)) {
|
||||
select.SetIsVoid(true);
|
||||
}
|
||||
if (!nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::value, value)) {
|
||||
if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::value, value)) {
|
||||
value.SetIsVoid(true);
|
||||
}
|
||||
if (!name.IsEmpty()) {
|
||||
|
@ -1340,7 +1339,7 @@ nsXMLContentSink::HandleProcessingInstruction(const PRUnichar *aTarget,
|
|||
|
||||
// If it's not a CSS stylesheet PI...
|
||||
nsAutoString type;
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::type, type);
|
||||
nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type);
|
||||
|
||||
if (mState != eXMLContentSinkState_InProlog ||
|
||||
!target.EqualsLiteral("xml-stylesheet") ||
|
||||
|
@ -1368,16 +1367,18 @@ nsXMLContentSink::ParsePIData(const nsString &aData, nsString &aHref,
|
|||
bool &aIsAlternate)
|
||||
{
|
||||
// If there was no href, we can't do anything with this PI
|
||||
if (!nsParserUtils::GetQuotedAttributeValue(aData, nsGkAtoms::href, aHref)) {
|
||||
if (!nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::href, aHref)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsParserUtils::GetQuotedAttributeValue(aData, nsGkAtoms::title, aTitle);
|
||||
nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::title, aTitle);
|
||||
|
||||
nsParserUtils::GetQuotedAttributeValue(aData, nsGkAtoms::media, aMedia);
|
||||
nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::media, aMedia);
|
||||
|
||||
nsAutoString alternate;
|
||||
nsParserUtils::GetQuotedAttributeValue(aData, nsGkAtoms::alternate, alternate);
|
||||
nsContentUtils::GetPseudoAttributeValue(aData,
|
||||
nsGkAtoms::alternate,
|
||||
alternate);
|
||||
|
||||
aIsAlternate = alternate.EqualsLiteral("yes");
|
||||
|
||||
|
|
|
@ -1368,7 +1368,8 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, bool aNotify)
|
|||
if (hasMutationListeners) {
|
||||
nsAutoString ns;
|
||||
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
|
||||
GetAttributeNodeNS(ns, nsDependentAtomString(aName), getter_AddRefs(attrNode));
|
||||
GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
|
||||
getter_AddRefs(attrNode));
|
||||
}
|
||||
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
#include "nsLayoutCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsXULElement.h"
|
||||
|
@ -1079,7 +1078,7 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
|
|||
// various version strings anyway. So we make no attempt to support
|
||||
// languages other than JS for language=
|
||||
nsAutoString lang(aAttributes[1]);
|
||||
if (nsParserUtils::IsJavaScriptLanguage(lang, &version)) {
|
||||
if (nsContentUtils::IsJavaScriptLanguage(lang, &version)) {
|
||||
langID = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
|
||||
// Even when JS version < 1.6 is specified, E4X is
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
#include "nsXULContentUtils.h"
|
||||
#include "nsIXULOverlayProvider.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsParserCIID.h"
|
||||
#include "nsPIBoxObject.h"
|
||||
#include "nsRDFCID.h"
|
||||
|
@ -2545,9 +2544,9 @@ nsXULDocument::InsertXULOverlayPI(const nsXULPrototypePI* aProtoPI,
|
|||
}
|
||||
|
||||
nsAutoString href;
|
||||
nsParserUtils::GetQuotedAttributeValue(aProtoPI->mData,
|
||||
nsGkAtoms::href,
|
||||
href);
|
||||
nsContentUtils::GetPseudoAttributeValue(aProtoPI->mData,
|
||||
nsGkAtoms::href,
|
||||
href);
|
||||
|
||||
// If there was no href, we can't do anything with this PI
|
||||
if (href.IsEmpty()) {
|
||||
|
|
|
@ -7667,19 +7667,8 @@ void nsGlobalWindow::MaybeUpdateTouchState()
|
|||
if(this == focusedWindow) {
|
||||
UpdateTouchState();
|
||||
}
|
||||
}
|
||||
|
||||
void nsGlobalWindow::UpdateTouchState()
|
||||
{
|
||||
FORWARD_TO_INNER_VOID(UpdateTouchState, ());
|
||||
|
||||
nsCOMPtr<nsIWidget> mainWidget = GetMainWidget();
|
||||
if (!mainWidget)
|
||||
return;
|
||||
|
||||
if (mMayHaveTouchEventListener) {
|
||||
mainWidget->RegisterTouchWindow();
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
|
||||
|
@ -7688,6 +7677,20 @@ void nsGlobalWindow::UpdateTouchState()
|
|||
DOM_TOUCH_LISTENER_ADDED,
|
||||
nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsGlobalWindow::UpdateTouchState()
|
||||
{
|
||||
FORWARD_TO_INNER_VOID(UpdateTouchState, ());
|
||||
|
||||
nsCOMPtr<nsIWidget> mainWidget = GetMainWidget();
|
||||
if (!mainWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mMayHaveTouchEventListener) {
|
||||
mainWidget->RegisterTouchWindow();
|
||||
} else {
|
||||
mainWidget->UnregisterTouchWindow();
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ public:
|
|||
/**
|
||||
* Simple object that holds a single point in space.
|
||||
*/
|
||||
class nsGeoPositionCoords : public nsIDOMGeoPositionCoords
|
||||
class nsGeoPositionCoords MOZ_FINAL : public nsIDOMGeoPositionCoords
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -96,8 +96,8 @@ public:
|
|||
double aAlt, double aHError,
|
||||
double aVError, double aHeading,
|
||||
double aSpeed);
|
||||
private:
|
||||
~nsGeoPositionCoords();
|
||||
private:
|
||||
const double mLat, mLong, mAlt, mHError, mVError, mHeading, mSpeed;
|
||||
};
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "nsIDOMGeoPosition.h"
|
||||
|
||||
typedef nsIDOMGeoPositionAddress *GeoPositionAddress;
|
||||
typedef nsIDOMGeoPositionCoords *GeoPositionCoords;
|
||||
typedef nsGeoPositionCoords *GeoPositionCoords;
|
||||
typedef nsIDOMGeoPosition *GeoPosition;
|
||||
|
||||
namespace IPC {
|
||||
|
@ -233,7 +233,7 @@ struct ParamTraits<GeoPosition>
|
|||
|
||||
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
|
||||
aParam->GetCoords(getter_AddRefs(coords));
|
||||
GeoPositionCoords simpleCoords = coords.get();
|
||||
GeoPositionCoords simpleCoords = static_cast<GeoPositionCoords>(coords.get());
|
||||
WriteParam(aMsg, simpleCoords);
|
||||
|
||||
nsCOMPtr<nsIDOMGeoPositionAddress> address;
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include "nsISHEntry.h"
|
||||
#include "nsIWebPageDescriptor.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsIDOMNodeFilter.h"
|
||||
#include "nsIDOMProcessingInstruction.h"
|
||||
|
@ -2604,72 +2605,6 @@ nsWebBrowserPersist::EnumCleanupUploadList(nsHashKey *aKey, void *aData, void* c
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsWebBrowserPersist::GetQuotedAttributeValue(
|
||||
const nsAString &aSource, const nsAString &aAttribute, nsAString &aValue)
|
||||
{
|
||||
// NOTE: This code was lifted verbatim from nsParserUtils.cpp
|
||||
aValue.Truncate();
|
||||
nsAString::const_iterator start, end;
|
||||
aSource.BeginReading(start);
|
||||
aSource.EndReading(end);
|
||||
nsAString::const_iterator iter(end);
|
||||
|
||||
while (start != end) {
|
||||
if (FindInReadable(aAttribute, start, iter))
|
||||
{
|
||||
// walk past any whitespace
|
||||
while (iter != end && nsCRT::IsAsciiSpace(*iter))
|
||||
{
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (iter == end)
|
||||
break;
|
||||
|
||||
// valid name="value" pair?
|
||||
if (*iter != '=')
|
||||
{
|
||||
start = iter;
|
||||
iter = end;
|
||||
continue;
|
||||
}
|
||||
// move past the =
|
||||
++iter;
|
||||
|
||||
while (iter != end && nsCRT::IsAsciiSpace(*iter))
|
||||
{
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (iter == end)
|
||||
break;
|
||||
|
||||
PRUnichar q = *iter;
|
||||
if (q != '"' && q != '\'')
|
||||
{
|
||||
start = iter;
|
||||
iter = end;
|
||||
continue;
|
||||
}
|
||||
|
||||
// point to the first char of the value
|
||||
++iter;
|
||||
start = iter;
|
||||
if (FindCharInReadable(q, iter, end))
|
||||
{
|
||||
aValue = Substring(start, iter);
|
||||
return true;
|
||||
}
|
||||
|
||||
// we've run out of string. Just return...
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult nsWebBrowserPersist::FixupXMLStyleSheetLink(nsIDOMProcessingInstruction *aPI, const nsAString &aHref)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPI);
|
||||
|
@ -2680,7 +2615,9 @@ nsresult nsWebBrowserPersist::FixupXMLStyleSheetLink(nsIDOMProcessingInstruction
|
|||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoString href;
|
||||
GetQuotedAttributeValue(data, NS_LITERAL_STRING("href"), href);
|
||||
nsContentUtils::GetPseudoAttributeValue(data,
|
||||
nsGkAtoms::href,
|
||||
href);
|
||||
|
||||
// Construct and set a new data value for the xml-stylesheet
|
||||
if (!aHref.IsEmpty() && !href.IsEmpty())
|
||||
|
@ -2691,11 +2628,21 @@ nsresult nsWebBrowserPersist::FixupXMLStyleSheetLink(nsIDOMProcessingInstruction
|
|||
nsAutoString type;
|
||||
nsAutoString media;
|
||||
|
||||
GetQuotedAttributeValue(data, NS_LITERAL_STRING("alternate"), alternate);
|
||||
GetQuotedAttributeValue(data, NS_LITERAL_STRING("charset"), charset);
|
||||
GetQuotedAttributeValue(data, NS_LITERAL_STRING("title"), title);
|
||||
GetQuotedAttributeValue(data, NS_LITERAL_STRING("type"), type);
|
||||
GetQuotedAttributeValue(data, NS_LITERAL_STRING("media"), media);
|
||||
nsContentUtils::GetPseudoAttributeValue(data,
|
||||
nsGkAtoms::alternate,
|
||||
alternate);
|
||||
nsContentUtils::GetPseudoAttributeValue(data,
|
||||
nsGkAtoms::charset,
|
||||
charset);
|
||||
nsContentUtils::GetPseudoAttributeValue(data,
|
||||
nsGkAtoms::title,
|
||||
title);
|
||||
nsContentUtils::GetPseudoAttributeValue(data,
|
||||
nsGkAtoms::type,
|
||||
type);
|
||||
nsContentUtils::GetPseudoAttributeValue(data,
|
||||
nsGkAtoms::media,
|
||||
media);
|
||||
|
||||
NS_NAMED_LITERAL_STRING(kCloseAttr, "\" ");
|
||||
nsAutoString newData;
|
||||
|
@ -2736,7 +2683,7 @@ nsresult nsWebBrowserPersist::GetXMLStyleSheetLink(nsIDOMProcessingInstruction *
|
|||
rv = aPI->GetData(data);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
GetQuotedAttributeValue(data, NS_LITERAL_STRING("href"), aHref);
|
||||
nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::href, aHref);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -152,8 +152,6 @@ private:
|
|||
{
|
||||
return StoreURIAttributeNS(aNode, "", aAttribute, aNeedsPersisting, aData);
|
||||
}
|
||||
bool GetQuotedAttributeValue(
|
||||
const nsAString &aSource, const nsAString &aAttribute, nsAString &aValue);
|
||||
bool DocumentEncoderExists(const PRUnichar *aContentType);
|
||||
|
||||
nsresult GetNodeToFixup(nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut);
|
||||
|
|
|
@ -60,8 +60,7 @@ namespace mozilla {
|
|||
namespace gl {
|
||||
|
||||
#ifdef DEBUG
|
||||
// see comment near declaration in GLContext.h. Should be thread-local.
|
||||
GLContext* GLContext::sCurrentGLContext = nsnull;
|
||||
PRUintn GLContext::sCurrentGLContextTLS = -1;
|
||||
#endif
|
||||
|
||||
PRUint32 GLContext::sDebugMode = 0;
|
||||
|
|
|
@ -602,9 +602,15 @@ public:
|
|||
|
||||
virtual bool MakeCurrentImpl(bool aForce = false) = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
static void StaticInit() {
|
||||
PR_NewThreadPrivateIndex(&sCurrentGLContextTLS, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool MakeCurrent(bool aForce = false) {
|
||||
#ifdef DEBUG
|
||||
sCurrentGLContext = this;
|
||||
PR_SetThreadPrivate(sCurrentGLContextTLS, this);
|
||||
#endif
|
||||
return MakeCurrentImpl(aForce);
|
||||
}
|
||||
|
@ -1505,10 +1511,12 @@ protected:
|
|||
GLContextSymbols mSymbols;
|
||||
|
||||
#ifdef DEBUG
|
||||
// this should be thread-local, but that is slightly annoying to implement because on Mac
|
||||
// we don't have any __thread-like keyword. So for now, MOZ_GL_DEBUG assumes (and asserts)
|
||||
// that only the main thread is doing OpenGL calls.
|
||||
static THEBES_API GLContext* sCurrentGLContext;
|
||||
// GLDebugMode will check that we don't send call
|
||||
// to a GLContext that isn't current on the current
|
||||
// thread.
|
||||
// Store the current context when binding to thread local
|
||||
// storage to support DebugMode on an arbitrary thread.
|
||||
static PRUintn sCurrentGLContextTLS;
|
||||
#endif
|
||||
|
||||
void UpdateActualFormat();
|
||||
|
@ -1632,21 +1640,16 @@ public:
|
|||
|
||||
void BeforeGLCall(const char* glFunction) {
|
||||
if (DebugMode()) {
|
||||
// since the static member variable sCurrentGLContext is not thread-local as it should,
|
||||
// we have to assert that we're in the main thread. Note that sCurrentGLContext is only used
|
||||
// for the OpenGL debug mode.
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_ERROR("OpenGL call from non-main thread. While this is fine in itself, "
|
||||
"the OpenGL debug mode, which is currently enabled, doesn't support this. "
|
||||
"It needs to be patched by making GLContext::sCurrentGLContext be thread-local.\n");
|
||||
NS_ABORT();
|
||||
}
|
||||
GLContext *currentGLContext = NULL;
|
||||
|
||||
currentGLContext = (GLContext*)PR_GetThreadPrivate(sCurrentGLContextTLS);
|
||||
|
||||
if (DebugMode() & DebugTrace)
|
||||
printf_stderr("[gl:%p] > %s\n", this, glFunction);
|
||||
if (this != sCurrentGLContext) {
|
||||
if (this != currentGLContext) {
|
||||
printf_stderr("Fatal: %s called on non-current context %p. "
|
||||
"The current context for this thread is %p.\n",
|
||||
glFunction, this, sCurrentGLContext);
|
||||
glFunction, this, currentGLContext);
|
||||
NS_ABORT();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -267,15 +267,6 @@ is_power_of_two(int v)
|
|||
static void BeforeGLCall(const char* glFunction)
|
||||
{
|
||||
if (GLContext::DebugMode()) {
|
||||
// since the static member variable sCurrentGLContext is not thread-local as it should,
|
||||
// we have to assert that we're in the main thread. Note that sCurrentGLContext is only used
|
||||
// for the OpenGL debug mode.
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_ERROR("OpenGL call from non-main thread. While this is fine in itself, "
|
||||
"the OpenGL debug mode, which is currently enabled, doesn't support this. "
|
||||
"It needs to be patched by making GLContext::sCurrentGLContext be thread-local.\n");
|
||||
NS_ABORT();
|
||||
}
|
||||
if (GLContext::DebugMode() & GLContext::DebugTrace)
|
||||
printf_stderr("[egl] > %s\n", glFunction);
|
||||
}
|
||||
|
|
|
@ -125,9 +125,9 @@ LayerManagerD3D10::~LayerManagerD3D10()
|
|||
}
|
||||
|
||||
bool
|
||||
LayerManagerD3D10::Initialize()
|
||||
LayerManagerD3D10::Initialize(bool force)
|
||||
{
|
||||
ScopedGfxFeatureReporter reporter("D3D10 Layers");
|
||||
ScopedGfxFeatureReporter reporter("D3D10 Layers", force);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
*
|
||||
* \return True is initialization was succesful, false when it was not.
|
||||
*/
|
||||
bool Initialize();
|
||||
bool Initialize(bool force = false);
|
||||
|
||||
/*
|
||||
* LayerManager implementation.
|
||||
|
|
|
@ -70,9 +70,9 @@ LayerManagerD3D9::~LayerManagerD3D9()
|
|||
}
|
||||
|
||||
bool
|
||||
LayerManagerD3D9::Initialize()
|
||||
LayerManagerD3D9::Initialize(bool force)
|
||||
{
|
||||
ScopedGfxFeatureReporter reporter("D3D9 Layers");
|
||||
ScopedGfxFeatureReporter reporter("D3D9 Layers", force);
|
||||
|
||||
/* XXX: this preference and blacklist code should move out of the layer manager */
|
||||
bool forceAccelerate =
|
||||
|
|
|
@ -103,7 +103,7 @@ public:
|
|||
*
|
||||
* \return True is initialization was succesful, false when it was not.
|
||||
*/
|
||||
bool Initialize();
|
||||
bool Initialize(bool force = false);
|
||||
|
||||
/*
|
||||
* Sets the clipping region for this layer manager. This is important on
|
||||
|
|
|
@ -171,9 +171,9 @@ LayerManagerOGL::CreateContext()
|
|||
}
|
||||
|
||||
bool
|
||||
LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext)
|
||||
LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext, bool force)
|
||||
{
|
||||
ScopedGfxFeatureReporter reporter("GL Layers");
|
||||
ScopedGfxFeatureReporter reporter("GL Layers", force);
|
||||
|
||||
// Do not allow double intiailization
|
||||
NS_ABORT_IF_FALSE(mGLContext == nsnull, "Don't reiniailize layer managers");
|
||||
|
|
|
@ -106,11 +106,11 @@ public:
|
|||
*
|
||||
* \return True is initialization was succesful, false when it was not.
|
||||
*/
|
||||
bool Initialize() {
|
||||
return Initialize(CreateContext());
|
||||
bool Initialize(bool force = false) {
|
||||
return Initialize(CreateContext(), force);
|
||||
}
|
||||
|
||||
bool Initialize(nsRefPtr<GLContext> aContext);
|
||||
bool Initialize(nsRefPtr<GLContext> aContext, bool force = false);
|
||||
|
||||
/**
|
||||
* Sets the clipping region for this layer manager. This is important on
|
||||
|
|
|
@ -103,10 +103,9 @@ ScopedGfxFeatureReporter::WriteAppNote(char statusChar)
|
|||
}
|
||||
|
||||
nsCAutoString featureString;
|
||||
featureString.AppendPrintf("%s%c%c",
|
||||
featureString.AppendPrintf("%s%c ",
|
||||
mFeature,
|
||||
statusChar,
|
||||
statusChar == '?' ? ' ' : '\n');
|
||||
statusChar);
|
||||
|
||||
if (!gFeaturesAlreadyReported->Contains(featureString)) {
|
||||
gFeaturesAlreadyReported->AppendElement(featureString);
|
||||
|
|
|
@ -53,9 +53,10 @@ namespace mozilla {
|
|||
class NS_GFX ScopedGfxFeatureReporter
|
||||
{
|
||||
public:
|
||||
ScopedGfxFeatureReporter(const char *aFeature) : mFeature(aFeature), mStatusChar('-')
|
||||
ScopedGfxFeatureReporter(const char *aFeature, bool force = false)
|
||||
: mFeature(aFeature), mStatusChar('-')
|
||||
{
|
||||
WriteAppNote('?');
|
||||
WriteAppNote(force ? '!' : '?');
|
||||
}
|
||||
~ScopedGfxFeatureReporter() {
|
||||
WriteAppNote(mStatusChar);
|
||||
|
|
|
@ -298,6 +298,10 @@ gfxPlatform::Init()
|
|||
#error "No gfxPlatform implementation available"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
mozilla::gl::GLContext::StaticInit();
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN) || defined(ANDROID) // temporary, until this is implemented on others
|
||||
|
|
|
@ -501,7 +501,7 @@ gfxWindowsPlatform::VerifyD2DDevice(bool aAttemptForce)
|
|||
mD2DDevice = nsnull;
|
||||
}
|
||||
|
||||
mozilla::ScopedGfxFeatureReporter reporter("D2D");
|
||||
mozilla::ScopedGfxFeatureReporter reporter("D2D", aAttemptForce);
|
||||
|
||||
HMODULE d3d10module = LoadLibraryA("d3d10_1.dll");
|
||||
D3D10CreateDevice1Func createD3DDevice = (D3D10CreateDevice1Func)
|
||||
|
|
|
@ -128,6 +128,7 @@ struct RuntimeStats
|
|||
, runtimeTemporary(0)
|
||||
, runtimeRegexpCode(0)
|
||||
, runtimeStackCommitted(0)
|
||||
, runtimeGCMarker(0)
|
||||
, gcHeapChunkTotal(0)
|
||||
, gcHeapChunkCleanUnused(0)
|
||||
, gcHeapChunkDirtyUnused(0)
|
||||
|
@ -159,6 +160,7 @@ struct RuntimeStats
|
|||
size_t runtimeTemporary;
|
||||
size_t runtimeRegexpCode;
|
||||
size_t runtimeStackCommitted;
|
||||
size_t runtimeGCMarker;
|
||||
size_t gcHeapChunkTotal;
|
||||
size_t gcHeapChunkCleanUnused;
|
||||
size_t gcHeapChunkDirtyUnused;
|
||||
|
|
|
@ -499,6 +499,17 @@ class Vector : private AllocPolicy
|
|||
* shifting existing elements from |t + 1| onward one position lower.
|
||||
*/
|
||||
void erase(T *t);
|
||||
|
||||
/*
|
||||
* Measure the size of the Vector's heap-allocated storage.
|
||||
*/
|
||||
size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const;
|
||||
|
||||
/*
|
||||
* Like sizeOfExcludingThis, but also measures the size of the Vector
|
||||
* object (which must be heap-allocated) itself.
|
||||
*/
|
||||
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const;
|
||||
};
|
||||
|
||||
/* This does the re-entrancy check plus several other sanity checks. */
|
||||
|
@ -996,6 +1007,20 @@ Vector<T,N,AP>::replaceRawBuffer(T *p, size_t length)
|
|||
#endif
|
||||
}
|
||||
|
||||
template <class T, size_t N, class AP>
|
||||
inline size_t
|
||||
Vector<T,N,AP>::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const
|
||||
{
|
||||
return usingInlineStorage() ? 0 : mallocSizeOf(beginNoCheck());
|
||||
}
|
||||
|
||||
template <class T, size_t N, class AP>
|
||||
inline size_t
|
||||
Vector<T,N,AP>::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const
|
||||
{
|
||||
return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
|
@ -211,10 +211,9 @@ CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats)
|
|||
&rtStats->runtimeNormal,
|
||||
&rtStats->runtimeTemporary,
|
||||
&rtStats->runtimeRegexpCode,
|
||||
&rtStats->runtimeStackCommitted);
|
||||
&rtStats->runtimeStackCommitted,
|
||||
&rtStats->runtimeGCMarker);
|
||||
|
||||
// Nb: we use sizeOfExcludingThis() because atomState.atoms is within
|
||||
// JSRuntime, and so counted when JSRuntime is counted.
|
||||
rtStats->runtimeAtomsTable =
|
||||
rt->atomState.atoms.sizeOfExcludingThis(rtStats->mallocSizeOf);
|
||||
|
||||
|
@ -335,7 +334,8 @@ GetExplicitNonHeapForRuntime(JSRuntime *rt, int64_t *amount,
|
|||
NULL,
|
||||
NULL,
|
||||
®expCode,
|
||||
&stackCommitted);
|
||||
&stackCommitted,
|
||||
NULL);
|
||||
|
||||
*amount += regexpCode;
|
||||
*amount += stackCommitted;
|
||||
|
|
|
@ -243,6 +243,8 @@ UpdateDecomposeLength(BytecodeEmitter *bce, uintN start)
|
|||
ptrdiff_t
|
||||
frontend::Emit1(JSContext *cx, BytecodeEmitter *bce, JSOp op)
|
||||
{
|
||||
JS_ASSERT_IF(op == JSOP_ARGUMENTS, !bce->mayOverwriteArguments());
|
||||
|
||||
ptrdiff_t offset = EmitCheck(cx, bce, 1);
|
||||
|
||||
if (offset >= 0) {
|
||||
|
@ -983,6 +985,14 @@ EmitSlotObjectOp(JSContext *cx, JSOp op, uintN slot, uint32_t index, BytecodeEmi
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitArguments(JSContext *cx, BytecodeEmitter *bce)
|
||||
{
|
||||
if (!bce->mayOverwriteArguments())
|
||||
return Emit1(cx, bce, JSOP_ARGUMENTS) >= 0;
|
||||
return EmitAtomOp(cx, cx->runtime->atomState.argumentsAtom, JSOP_NAME, bce);
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::shouldNoteClosedName(ParseNode *pn)
|
||||
{
|
||||
|
@ -1833,7 +1843,10 @@ EmitNameOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSBool callContex
|
|||
}
|
||||
}
|
||||
|
||||
if (op == JSOP_ARGUMENTS || op == JSOP_CALLEE) {
|
||||
if (op == JSOP_ARGUMENTS) {
|
||||
if (!EmitArguments(cx, bce))
|
||||
return JS_FALSE;
|
||||
} else if (op == JSOP_CALLEE) {
|
||||
if (Emit1(cx, bce, op) < 0)
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
|
@ -3589,7 +3602,7 @@ EmitVariables(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption
|
|||
return JS_FALSE;
|
||||
}
|
||||
if (op == JSOP_ARGUMENTS) {
|
||||
if (Emit1(cx, bce, op) < 0)
|
||||
if (!EmitArguments(cx, bce))
|
||||
return JS_FALSE;
|
||||
} else if (!pn2->pn_cookie.isFree()) {
|
||||
EMIT_UINT16_IMM_OP(op, atomIndex);
|
||||
|
@ -3700,7 +3713,7 @@ EmitAssignment(JSContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp op, Par
|
|||
if (lhs->isOp(JSOP_CALLEE)) {
|
||||
if (Emit1(cx, bce, JSOP_CALLEE) < 0)
|
||||
return false;
|
||||
} else if (lhs->isOp(JSOP_NAME)) {
|
||||
} else if (lhs->isOp(JSOP_NAME) || lhs->isOp(JSOP_GETGNAME)) {
|
||||
if (!EmitIndex32(cx, lhs->getOp(), atomIndex, bce))
|
||||
return false;
|
||||
} else {
|
||||
|
|
|
@ -168,21 +168,20 @@ struct StmtInfo {
|
|||
#define TCF_IN_FOR_INIT 0x10 /* parsing init expr of for; exclude 'in' */
|
||||
#define TCF_FUN_SETS_OUTER_NAME 0x20 /* function set outer name (lexical or free) */
|
||||
#define TCF_FUN_PARAM_ARGUMENTS 0x40 /* function has parameter named arguments */
|
||||
#define TCF_FUN_USES_ARGUMENTS 0x80 /* function uses arguments except as a
|
||||
#define TCF_FUN_LOCAL_ARGUMENTS 0x80 /* function has local named arguments */
|
||||
#define TCF_FUN_USES_ARGUMENTS 0x100 /* function uses arguments except as a
|
||||
parameter name */
|
||||
#define TCF_FUN_HEAVYWEIGHT 0x100 /* function needs Call object per call */
|
||||
#define TCF_FUN_IS_GENERATOR 0x200 /* parsed yield statement in function */
|
||||
#define TCF_FUN_USES_OWN_NAME 0x400 /* named function expression that uses its
|
||||
#define TCF_FUN_HEAVYWEIGHT 0x200 /* function needs Call object per call */
|
||||
#define TCF_FUN_IS_GENERATOR 0x400 /* parsed yield statement in function */
|
||||
#define TCF_FUN_USES_OWN_NAME 0x800 /* named function expression that uses its
|
||||
own name */
|
||||
#define TCF_HAS_FUNCTION_STMT 0x800 /* block contains a function statement */
|
||||
#define TCF_GENEXP_LAMBDA 0x1000 /* flag lambda from generator expression */
|
||||
#define TCF_COMPILE_N_GO 0x2000 /* compile-and-go mode of script, can
|
||||
#define TCF_HAS_FUNCTION_STMT 0x1000 /* block contains a function statement */
|
||||
#define TCF_GENEXP_LAMBDA 0x2000 /* flag lambda from generator expression */
|
||||
#define TCF_COMPILE_N_GO 0x4000 /* compile-and-go mode of script, can
|
||||
optimize name references based on scope
|
||||
chain */
|
||||
#define TCF_NO_SCRIPT_RVAL 0x4000 /* API caller does not want result value
|
||||
#define TCF_NO_SCRIPT_RVAL 0x8000 /* API caller does not want result value
|
||||
from global script */
|
||||
/* bit 0x8000 is unused */
|
||||
|
||||
/*
|
||||
* Set when parsing a declaration-like destructuring pattern. This
|
||||
* flag causes PrimaryExpr to create PN_NAME parse nodes for variable
|
||||
|
@ -273,6 +272,7 @@ struct StmtInfo {
|
|||
#define TCF_FUN_FLAGS (TCF_FUN_SETS_OUTER_NAME | \
|
||||
TCF_FUN_USES_ARGUMENTS | \
|
||||
TCF_FUN_PARAM_ARGUMENTS | \
|
||||
TCF_FUN_LOCAL_ARGUMENTS | \
|
||||
TCF_FUN_HEAVYWEIGHT | \
|
||||
TCF_FUN_IS_GENERATOR | \
|
||||
TCF_FUN_USES_OWN_NAME | \
|
||||
|
@ -434,6 +434,15 @@ struct TreeContext { /* tree context for semantic checks */
|
|||
return flags & TCF_FUN_MUTATES_PARAMETER;
|
||||
}
|
||||
|
||||
bool mayOverwriteArguments() const {
|
||||
JS_ASSERT(inFunction());
|
||||
JS_ASSERT_IF(inStrictMode(),
|
||||
!(flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_LOCAL_ARGUMENTS)));
|
||||
return !inStrictMode() &&
|
||||
(callsEval() ||
|
||||
flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_LOCAL_ARGUMENTS));
|
||||
}
|
||||
|
||||
void noteArgumentsNameUse(ParseNode *node) {
|
||||
JS_ASSERT(inFunction());
|
||||
JS_ASSERT(node->isKind(PNK_NAME));
|
||||
|
|
|
@ -2431,7 +2431,7 @@ NoteLValue(JSContext *cx, ParseNode *pn, TreeContext *tc, uintN dflag = PND_ASSI
|
|||
*/
|
||||
JSAtom *lname = pn->pn_atom;
|
||||
if (lname == cx->runtime->atomState.argumentsAtom) {
|
||||
tc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
|
||||
tc->countArgumentsUse(pn);
|
||||
} else if (tc->inFunction() && lname == tc->fun()->atom) {
|
||||
tc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
|
@ -2453,7 +2453,7 @@ BindDestructuringVar(JSContext *cx, BindData *data, ParseNode *pn, TreeContext *
|
|||
JS_ASSERT(pn->isKind(PNK_NAME));
|
||||
atom = pn->pn_atom;
|
||||
if (atom == cx->runtime->atomState.argumentsAtom)
|
||||
tc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
|
||||
|
||||
data->pn = pn;
|
||||
if (!data->binder(cx, data, atom, tc))
|
||||
|
@ -4424,7 +4424,7 @@ Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext va
|
|||
if (tc->inFunction() && name == context->runtime->atomState.argumentsAtom) {
|
||||
tc->noteArgumentsNameUse(pn2);
|
||||
if (!blockObj)
|
||||
tc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
} while (tokenStream.matchToken(TOK_COMMA));
|
||||
|
|
|
@ -178,8 +178,8 @@ TokenStream::init(const jschar *base, size_t length, const char *fn, uintN ln, J
|
|||
prevLinebase = NULL;
|
||||
sourceMap = NULL;
|
||||
|
||||
JSSourceHandler listener = cx->debugHooks->sourceHandler;
|
||||
void *listenerData = cx->debugHooks->sourceHandlerData;
|
||||
JSSourceHandler listener = cx->runtime->debugHooks.sourceHandler;
|
||||
void *listenerData = cx->runtime->debugHooks.sourceHandlerData;
|
||||
|
||||
if (listener)
|
||||
listener(fn, ln, base, length, &listenerTSData, listenerData);
|
||||
|
@ -521,8 +521,8 @@ TokenStream::reportCompileErrorNumberVA(ParseNode *pn, uintN flags, uintN errorN
|
|||
* sending the error on to the regular error reporter.
|
||||
*/
|
||||
bool reportError = true;
|
||||
if (JSDebugErrorHook hook = cx->debugHooks->debugErrorHook)
|
||||
reportError = hook(cx, message, &report, cx->debugHooks->debugErrorHookData);
|
||||
if (JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook)
|
||||
reportError = hook(cx, message, &report, cx->runtime->debugHooks.debugErrorHookData);
|
||||
|
||||
/* Report the error */
|
||||
if (reportError && cx->errorReporter)
|
||||
|
|
|
@ -46,40 +46,51 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
ClearValueRange(JSCompartment *comp, HeapValue *vec, uintN len, bool useHoles)
|
||||
inline void
|
||||
EncapsulatedValue::writeBarrierPre(const Value &value)
|
||||
{
|
||||
if (useHoles) {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].set(comp, MagicValue(JS_ARRAY_HOLE));
|
||||
} else {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].set(comp, UndefinedValue());
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (value.isMarkable()) {
|
||||
js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing();
|
||||
writeBarrierPre(cell->compartment(), value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
InitValueRange(HeapValue *vec, uintN len, bool useHoles)
|
||||
inline void
|
||||
EncapsulatedValue::writeBarrierPre(JSCompartment *comp, const Value &value)
|
||||
{
|
||||
if (useHoles) {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].init(MagicValue(JS_ARRAY_HOLE));
|
||||
} else {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].init(UndefinedValue());
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (comp->needsBarrier()) {
|
||||
Value tmp(value);
|
||||
js::gc::MarkValueUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
|
||||
JS_ASSERT(tmp == value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
DestroyValueRange(HeapValue *vec, uintN len)
|
||||
inline void
|
||||
EncapsulatedValue::pre()
|
||||
{
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].~HeapValue();
|
||||
writeBarrierPre(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
EncapsulatedValue::pre(JSCompartment *comp)
|
||||
{
|
||||
writeBarrierPre(comp, value);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapValue::HeapValue()
|
||||
: EncapsulatedValue(UndefinedValue())
|
||||
{
|
||||
post();
|
||||
}
|
||||
|
||||
inline
|
||||
HeapValue::HeapValue(const Value &v)
|
||||
: value(v)
|
||||
: EncapsulatedValue(v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
post();
|
||||
|
@ -87,7 +98,7 @@ HeapValue::HeapValue(const Value &v)
|
|||
|
||||
inline
|
||||
HeapValue::HeapValue(const HeapValue &v)
|
||||
: value(v.value)
|
||||
: EncapsulatedValue(v.value)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v.value));
|
||||
post();
|
||||
|
@ -114,61 +125,6 @@ HeapValue::init(JSCompartment *comp, const Value &v)
|
|||
post(comp);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPre(const Value &value)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (value.isMarkable()) {
|
||||
js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing();
|
||||
writeBarrierPre(cell->compartment(), value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPost(const Value &value, void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPre(JSCompartment *comp, const Value &value)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (comp->needsBarrier()) {
|
||||
Value tmp(value);
|
||||
js::gc::MarkValueUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
|
||||
JS_ASSERT(tmp == value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPost(JSCompartment *comp, const Value &value, void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::pre()
|
||||
{
|
||||
writeBarrierPre(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::post()
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::pre(JSCompartment *comp)
|
||||
{
|
||||
writeBarrierPre(comp, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::post(JSCompartment *comp)
|
||||
{
|
||||
}
|
||||
|
||||
inline HeapValue &
|
||||
HeapValue::operator=(const Value &v)
|
||||
{
|
||||
|
@ -206,6 +162,109 @@ HeapValue::set(JSCompartment *comp, const Value &v)
|
|||
post(comp);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPost(const Value &value, void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPost(JSCompartment *comp, const Value &value, void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::post()
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::post(JSCompartment *comp)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
HeapSlot::HeapSlot(JSObject *obj, uint32_t slot, const Value &v)
|
||||
: EncapsulatedValue(v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
post(obj, slot);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapSlot::HeapSlot(JSObject *obj, uint32_t slot, const HeapSlot &s)
|
||||
: EncapsulatedValue(s.value)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(s.value));
|
||||
post(obj, slot);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapSlot::~HeapSlot()
|
||||
{
|
||||
pre();
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::init(JSObject *obj, uint32_t slot, const Value &v)
|
||||
{
|
||||
value = v;
|
||||
post(obj, slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::init(JSCompartment *comp, JSObject *obj, uint32_t slot, const Value &v)
|
||||
{
|
||||
value = v;
|
||||
post(comp, obj, slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::set(JSObject *obj, uint32_t slot, const Value &v)
|
||||
{
|
||||
JS_ASSERT_IF(!obj->isArray(), &obj->getSlotRef(slot) == this);
|
||||
JS_ASSERT_IF(obj->isDenseArray(), &obj->getDenseArrayElement(slot) == (const Value *)this);
|
||||
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(obj, slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::set(JSCompartment *comp, JSObject *obj, uint32_t slot, const Value &v)
|
||||
{
|
||||
JS_ASSERT_IF(!obj->isArray(), &const_cast<JSObject *>(obj)->getSlotRef(slot) == this);
|
||||
JS_ASSERT_IF(obj->isDenseArray(), &obj->getDenseArrayElement(slot) == (const Value *)this);
|
||||
JS_ASSERT(obj->compartment() == comp);
|
||||
|
||||
pre(comp);
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(comp, obj, slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::writeBarrierPost(JSObject *obj, uint32_t slot)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::writeBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t slotno)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::post(JSObject *owner, uint32_t slot)
|
||||
{
|
||||
HeapSlot::writeBarrierPost(owner, slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::post(JSCompartment *comp, JSObject *owner, uint32_t slot)
|
||||
{
|
||||
HeapSlot::writeBarrierPost(comp, owner, slot);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapId::HeapId(jsid id)
|
||||
: value(id)
|
||||
|
|
|
@ -299,31 +299,24 @@ struct HeapPtrHasher
|
|||
template <class T>
|
||||
struct DefaultHasher< HeapPtr<T> >: HeapPtrHasher<T> { };
|
||||
|
||||
class HeapValue
|
||||
class EncapsulatedValue
|
||||
{
|
||||
protected:
|
||||
Value value;
|
||||
|
||||
public:
|
||||
explicit HeapValue() : value(UndefinedValue()) {}
|
||||
explicit inline HeapValue(const Value &v);
|
||||
explicit inline HeapValue(const HeapValue &v);
|
||||
|
||||
inline ~HeapValue();
|
||||
|
||||
inline void init(const Value &v);
|
||||
inline void init(JSCompartment *comp, const Value &v);
|
||||
|
||||
inline HeapValue &operator=(const Value &v);
|
||||
inline HeapValue &operator=(const HeapValue &v);
|
||||
|
||||
/*
|
||||
* This is a faster version of operator=. Normally, operator= has to
|
||||
* determine the compartment of the value before it can decide whether to do
|
||||
* the barrier. If you already know the compartment, it's faster to pass it
|
||||
* in.
|
||||
* Ensure that EncapsulatedValue is not constructable, except by our
|
||||
* implementations.
|
||||
*/
|
||||
inline void set(JSCompartment *comp, const Value &v);
|
||||
EncapsulatedValue() MOZ_DELETE;
|
||||
EncapsulatedValue(const EncapsulatedValue &v) MOZ_DELETE;
|
||||
EncapsulatedValue &operator=(const Value &v) MOZ_DELETE;
|
||||
EncapsulatedValue &operator=(const EncapsulatedValue &v) MOZ_DELETE;
|
||||
|
||||
EncapsulatedValue(const Value &v) : value(v) {}
|
||||
~EncapsulatedValue() {}
|
||||
|
||||
public:
|
||||
const Value &get() const { return value; }
|
||||
Value *unsafeGet() { return &value; }
|
||||
operator const Value &() const { return value; }
|
||||
|
@ -360,38 +353,93 @@ class HeapValue
|
|||
#endif
|
||||
|
||||
static inline void writeBarrierPre(const Value &v);
|
||||
static inline void writeBarrierPost(const Value &v, void *addr);
|
||||
|
||||
static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
|
||||
|
||||
protected:
|
||||
inline void pre();
|
||||
inline void pre(JSCompartment *comp);
|
||||
};
|
||||
|
||||
class HeapValue : public EncapsulatedValue
|
||||
{
|
||||
public:
|
||||
explicit inline HeapValue();
|
||||
explicit inline HeapValue(const Value &v);
|
||||
explicit inline HeapValue(const HeapValue &v);
|
||||
inline ~HeapValue();
|
||||
|
||||
inline void init(const Value &v);
|
||||
inline void init(JSCompartment *comp, const Value &v);
|
||||
|
||||
inline HeapValue &operator=(const Value &v);
|
||||
inline HeapValue &operator=(const HeapValue &v);
|
||||
|
||||
/*
|
||||
* This is a faster version of operator=. Normally, operator= has to
|
||||
* determine the compartment of the value before it can decide whether to do
|
||||
* the barrier. If you already know the compartment, it's faster to pass it
|
||||
* in.
|
||||
*/
|
||||
inline void set(JSCompartment *comp, const Value &v);
|
||||
|
||||
static inline void writeBarrierPost(const Value &v, void *addr);
|
||||
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, void *addr);
|
||||
|
||||
private:
|
||||
inline void pre();
|
||||
inline void post();
|
||||
|
||||
inline void pre(JSCompartment *comp);
|
||||
inline void post(JSCompartment *comp);
|
||||
};
|
||||
|
||||
static inline const Value *
|
||||
Valueify(const HeapValue *array)
|
||||
class HeapSlot : public EncapsulatedValue
|
||||
{
|
||||
JS_ASSERT(sizeof(HeapValue) == sizeof(Value));
|
||||
/*
|
||||
* Operator= is not valid for HeapSlot because is must take the object and
|
||||
* slot offset to provide to the post/generational barrier.
|
||||
*/
|
||||
inline HeapSlot &operator=(const Value &v) MOZ_DELETE;
|
||||
inline HeapSlot &operator=(const HeapValue &v) MOZ_DELETE;
|
||||
inline HeapSlot &operator=(const HeapSlot &v) MOZ_DELETE;
|
||||
|
||||
public:
|
||||
explicit inline HeapSlot() MOZ_DELETE;
|
||||
explicit inline HeapSlot(JSObject *obj, uint32_t slot, const Value &v);
|
||||
explicit inline HeapSlot(JSObject *obj, uint32_t slot, const HeapSlot &v);
|
||||
inline ~HeapSlot();
|
||||
|
||||
inline void init(JSObject *owner, uint32_t slot, const Value &v);
|
||||
inline void init(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
|
||||
|
||||
inline void set(JSObject *owner, uint32_t slot, const Value &v);
|
||||
inline void set(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
|
||||
|
||||
static inline void writeBarrierPost(JSObject *obj, uint32_t slot);
|
||||
static inline void writeBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t slotno);
|
||||
|
||||
private:
|
||||
inline void post(JSObject *owner, uint32_t slot);
|
||||
inline void post(JSCompartment *comp, JSObject *owner, uint32_t slot);
|
||||
};
|
||||
|
||||
static inline const Value *
|
||||
Valueify(const EncapsulatedValue *array)
|
||||
{
|
||||
JS_STATIC_ASSERT(sizeof(HeapValue) == sizeof(Value));
|
||||
JS_STATIC_ASSERT(sizeof(HeapSlot) == sizeof(Value));
|
||||
return (const Value *)array;
|
||||
}
|
||||
|
||||
class HeapValueArray
|
||||
class HeapSlotArray
|
||||
{
|
||||
HeapValue *array;
|
||||
HeapSlot *array;
|
||||
|
||||
public:
|
||||
HeapValueArray(HeapValue *array) : array(array) {}
|
||||
HeapSlotArray(HeapSlot *array) : array(array) {}
|
||||
|
||||
operator const Value *() const { return Valueify(array); }
|
||||
operator HeapValue *() const { return array; }
|
||||
operator HeapSlot *() const { return array; }
|
||||
|
||||
HeapValueArray operator +(int offset) const { return HeapValueArray(array + offset); }
|
||||
HeapValueArray operator +(uint32_t offset) const { return HeapValueArray(array + offset); }
|
||||
HeapSlotArray operator +(int offset) const { return HeapSlotArray(array + offset); }
|
||||
HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); }
|
||||
};
|
||||
|
||||
class HeapId
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
function f() {
|
||||
var a = arguments;
|
||||
eval("assertEq(arguments[0], 42)");
|
||||
eval("assertEq(arguments, a)");
|
||||
arguments = undefined;
|
||||
eval("assertEq(arguments, undefined)");
|
||||
arguments = a;
|
||||
eval("assertEq(arguments[0], 42)");
|
||||
eval("assertEq(arguments, a)");
|
||||
}
|
||||
f(42);
|
||||
|
||||
function f(z) {
|
||||
var a = arguments;
|
||||
eval("assertEq(arguments[0], 42)");
|
||||
eval("assertEq(arguments, a)");
|
||||
arguments = undefined;
|
||||
eval("assertEq(arguments, undefined)");
|
||||
z = 17;
|
||||
eval("assertEq(a[0], 17)");
|
||||
a[0] = 'ponies';
|
||||
eval("assertEq(z, 'ponies')");
|
||||
}
|
||||
f(42);
|
|
@ -110,6 +110,7 @@ bool called = false;
|
|||
static JSTrapStatus
|
||||
ThrowHook(JSContext *cx, JSScript *, jsbytecode *, jsval *rval, void *closure)
|
||||
{
|
||||
JS_ASSERT(!closure);
|
||||
called = true;
|
||||
|
||||
JSObject *global = JS_GetGlobalForScopeChain(cx);
|
||||
|
@ -126,9 +127,7 @@ BEGIN_TEST(testDebugger_throwHook)
|
|||
uint32_t newopts = JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS;
|
||||
uint32_t oldopts = JS_SetOptions(cx, newopts);
|
||||
|
||||
JSDebugHooks hooks = { 0 };
|
||||
hooks.throwHook = ThrowHook;
|
||||
JSDebugHooks *old = JS_SetContextDebugHooks(cx, &hooks);
|
||||
CHECK(JS_SetThrowHook(rt, ThrowHook, NULL));
|
||||
EXEC("function foo() { throw 3 };\n"
|
||||
"for (var i = 0; i < 10; ++i) { \n"
|
||||
" var x = <tag></tag>;\n"
|
||||
|
@ -137,8 +136,7 @@ BEGIN_TEST(testDebugger_throwHook)
|
|||
" } catch(e) {}\n"
|
||||
"}\n");
|
||||
CHECK(called);
|
||||
|
||||
JS_SetContextDebugHooks(cx, old);
|
||||
CHECK(JS_SetThrowHook(rt, NULL, NULL));
|
||||
JS_SetOptions(cx, oldopts);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -800,7 +800,7 @@ JSRuntime::JSRuntime()
|
|||
JS_INIT_CLIST(&contextList);
|
||||
JS_INIT_CLIST(&debuggerList);
|
||||
|
||||
PodZero(&globalDebugHooks);
|
||||
PodZero(&debugHooks);
|
||||
PodZero(&atomState);
|
||||
|
||||
#if JS_STACK_GROWTH_DIRECTION > 0
|
||||
|
|
|
@ -1194,7 +1194,7 @@ array_trace(JSTracer *trc, JSObject *obj)
|
|||
JS_ASSERT(obj->isDenseArray());
|
||||
|
||||
uint32_t initLength = obj->getDenseArrayInitializedLength();
|
||||
MarkValueRange(trc, initLength, obj->getDenseArrayElements(), "element");
|
||||
MarkSlotRange(trc, initLength, obj->getDenseArrayElements(), "element");
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -1377,7 +1377,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
|
|||
this->shape_ = shape;
|
||||
|
||||
/* Take ownership of the dense elements, reset to an empty dense array. */
|
||||
HeapValue *elems = elements;
|
||||
HeapSlot *elems = elements;
|
||||
elements = emptyObjectElements;
|
||||
|
||||
/* Root all values in the array during conversion. */
|
||||
|
@ -1389,7 +1389,8 @@ JSObject::makeDenseArraySlow(JSContext *cx)
|
|||
*/
|
||||
if (!AddLengthProperty(cx, this)) {
|
||||
this->shape_ = oldShape;
|
||||
cx->free_(getElementsHeader());
|
||||
if (elements != emptyObjectElements)
|
||||
cx->free_(getElementsHeader());
|
||||
elements = elems;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -64,7 +64,12 @@ JSObject::ensureDenseArrayInitializedLength(JSContext *cx, uint32_t index, uint3
|
|||
markDenseArrayNotPacked(cx);
|
||||
|
||||
if (initlen < index + extra) {
|
||||
js::InitValueRange(elements + initlen, index + extra - initlen, true);
|
||||
JSCompartment *comp = compartment();
|
||||
size_t offset = initlen;
|
||||
for (js::HeapSlot *sp = elements + initlen;
|
||||
sp != elements + (index + extra);
|
||||
sp++, offset++)
|
||||
sp->init(comp, this, offset, js::MagicValue(JS_ARRAY_HOLE));
|
||||
initlen = index + extra;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ using namespace js::gc;
|
|||
|
||||
void
|
||||
JSRuntime::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
|
||||
size_t *regexpCode, size_t *stackCommitted)
|
||||
size_t *regexpCode, size_t *stackCommitted, size_t *gcMarkerSize)
|
||||
{
|
||||
if (normal)
|
||||
*normal = mallocSizeOf(dtoaState);
|
||||
|
@ -113,6 +113,9 @@ JSRuntime::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, s
|
|||
|
||||
if (stackCommitted)
|
||||
*stackCommitted = stackSpace.sizeOfCommitted();
|
||||
|
||||
if (gcMarkerSize)
|
||||
*gcMarkerSize = gcMarker.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
|
@ -356,11 +359,9 @@ ReportError(JSContext *cx, const char *message, JSErrorReport *reportp,
|
|||
if (!JS_IsRunning(cx) ||
|
||||
!js_ErrorToException(cx, message, reportp, callback, userRef)) {
|
||||
js_ReportErrorAgain(cx, message, reportp);
|
||||
} else if (cx->debugHooks->debugErrorHook && cx->errorReporter) {
|
||||
JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
|
||||
/* test local in case debugErrorHook changed on another thread */
|
||||
if (hook)
|
||||
hook(cx, message, reportp, cx->debugHooks->debugErrorHookData);
|
||||
} else if (JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook) {
|
||||
if (cx->errorReporter)
|
||||
hook(cx, message, reportp, cx->runtime->debugHooks.debugErrorHookData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,9 +420,9 @@ js_ReportOutOfMemory(JSContext *cx)
|
|||
*/
|
||||
cx->clearPendingException();
|
||||
if (onError) {
|
||||
JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
|
||||
JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook;
|
||||
if (hook &&
|
||||
!hook(cx, msg, &report, cx->debugHooks->debugErrorHookData)) {
|
||||
!hook(cx, msg, &report, cx->runtime->debugHooks.debugErrorHookData)) {
|
||||
onError = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -751,12 +752,9 @@ js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
|
|||
* sending the error on to the regular ErrorReporter.
|
||||
*/
|
||||
if (onError) {
|
||||
JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
|
||||
if (hook &&
|
||||
!hook(cx, cx->lastMessage, reportp,
|
||||
cx->debugHooks->debugErrorHookData)) {
|
||||
JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook;
|
||||
if (hook && !hook(cx, cx->lastMessage, reportp, cx->runtime->debugHooks.debugErrorHookData))
|
||||
onError = NULL;
|
||||
}
|
||||
}
|
||||
if (onError)
|
||||
onError(cx, cx->lastMessage, reportp);
|
||||
|
@ -981,7 +979,6 @@ JSContext::JSContext(JSRuntime *rt)
|
|||
outstandingRequests(0),
|
||||
#endif
|
||||
autoGCRooters(NULL),
|
||||
debugHooks(&rt->globalDebugHooks),
|
||||
securityCallbacks(NULL),
|
||||
resolveFlags(0),
|
||||
rngSeed(0),
|
||||
|
|
|
@ -475,7 +475,7 @@ struct JSRuntime : js::RuntimeFriendFields
|
|||
}
|
||||
|
||||
/* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
|
||||
JSDebugHooks globalDebugHooks;
|
||||
JSDebugHooks debugHooks;
|
||||
|
||||
/* If true, new compartments are initially in debug mode. */
|
||||
bool debugMode;
|
||||
|
@ -689,7 +689,7 @@ struct JSRuntime : js::RuntimeFriendFields
|
|||
}
|
||||
|
||||
void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
|
||||
size_t *regexpCode, size_t *stackCommitted);
|
||||
size_t *regexpCode, size_t *stackCommitted, size_t *gcMarker);
|
||||
|
||||
void purge(JSContext *cx);
|
||||
};
|
||||
|
@ -714,8 +714,6 @@ struct JSArgumentFormatMap {
|
|||
};
|
||||
#endif
|
||||
|
||||
extern const JSDebugHooks js_NullDebugHooks; /* defined in jsdbgapi.cpp */
|
||||
|
||||
namespace js {
|
||||
|
||||
template <typename T> class Root;
|
||||
|
@ -1015,9 +1013,6 @@ struct JSContext : js::ContextFriendFields
|
|||
|
||||
#endif /* JSGC_ROOT_ANALYSIS */
|
||||
|
||||
/* Debug hooks associated with the current context. */
|
||||
const JSDebugHooks *debugHooks;
|
||||
|
||||
/* Security callbacks that override any defined on the runtime. */
|
||||
JSSecurityCallbacks *securityCallbacks;
|
||||
|
||||
|
|
|
@ -113,11 +113,11 @@ ScriptDebugPrologue(JSContext *cx, StackFrame *fp)
|
|||
JS_ASSERT(fp == cx->fp());
|
||||
|
||||
if (fp->isFramePushedByExecute()) {
|
||||
if (JSInterpreterHook hook = cx->debugHooks->executeHook)
|
||||
fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->debugHooks->executeHookData));
|
||||
if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
|
||||
fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->runtime->debugHooks.executeHookData));
|
||||
} else {
|
||||
if (JSInterpreterHook hook = cx->debugHooks->callHook)
|
||||
fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->debugHooks->callHookData));
|
||||
if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
|
||||
fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->runtime->debugHooks.callHookData));
|
||||
}
|
||||
|
||||
Value rval;
|
||||
|
@ -148,10 +148,10 @@ ScriptDebugEpilogue(JSContext *cx, StackFrame *fp, bool okArg)
|
|||
|
||||
if (void *hookData = fp->maybeHookData()) {
|
||||
if (fp->isFramePushedByExecute()) {
|
||||
if (JSInterpreterHook hook = cx->debugHooks->executeHook)
|
||||
if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
|
||||
hook(cx, Jsvalify(fp), false, &ok, hookData);
|
||||
} else {
|
||||
if (JSInterpreterHook hook = cx->debugHooks->callHook)
|
||||
if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
|
||||
hook(cx, Jsvalify(fp), false, &ok, hookData);
|
||||
}
|
||||
}
|
||||
|
@ -238,8 +238,8 @@ JS_ClearAllTrapsForCompartment(JSContext *cx)
|
|||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetInterrupt(JSRuntime *rt, JSInterruptHook hook, void *closure)
|
||||
{
|
||||
rt->globalDebugHooks.interruptHook = hook;
|
||||
rt->globalDebugHooks.interruptHookData = closure;
|
||||
rt->debugHooks.interruptHook = hook;
|
||||
rt->debugHooks.interruptHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -247,11 +247,11 @@ JS_PUBLIC_API(JSBool)
|
|||
JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *hoop, void **closurep)
|
||||
{
|
||||
if (hoop)
|
||||
*hoop = rt->globalDebugHooks.interruptHook;
|
||||
*hoop = rt->debugHooks.interruptHook;
|
||||
if (closurep)
|
||||
*closurep = rt->globalDebugHooks.interruptHookData;
|
||||
rt->globalDebugHooks.interruptHook = 0;
|
||||
rt->globalDebugHooks.interruptHookData = 0;
|
||||
*closurep = rt->debugHooks.interruptHookData;
|
||||
rt->debugHooks.interruptHook = 0;
|
||||
rt->debugHooks.interruptHookData = 0;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -589,7 +589,7 @@ JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fpArg)
|
|||
* null returned above or in the #else
|
||||
*/
|
||||
if (!fp->hasCallObj() && fp->isNonEvalFunctionFrame())
|
||||
return CreateFunCallObject(cx, fp);
|
||||
return CallObject::createForFunction(cx, fp);
|
||||
return &fp->callObj();
|
||||
}
|
||||
|
||||
|
@ -728,16 +728,16 @@ JS_GetScriptVersion(JSContext *cx, JSScript *script)
|
|||
JS_PUBLIC_API(void)
|
||||
JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata)
|
||||
{
|
||||
rt->globalDebugHooks.newScriptHook = hook;
|
||||
rt->globalDebugHooks.newScriptHookData = callerdata;
|
||||
rt->debugHooks.newScriptHook = hook;
|
||||
rt->debugHooks.newScriptHookData = callerdata;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
|
||||
void *callerdata)
|
||||
{
|
||||
rt->globalDebugHooks.destroyScriptHook = hook;
|
||||
rt->globalDebugHooks.destroyScriptHookData = callerdata;
|
||||
rt->debugHooks.destroyScriptHook = hook;
|
||||
rt->debugHooks.destroyScriptHookData = callerdata;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -844,10 +844,10 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
|||
| (!shape->writable() ? JSPD_READONLY : 0)
|
||||
| (!shape->configurable() ? JSPD_PERMANENT : 0);
|
||||
pd->spare = 0;
|
||||
if (shape->getter() == GetCallArg) {
|
||||
if (shape->getter() == CallObject::getArgOp) {
|
||||
pd->slot = shape->shortid();
|
||||
pd->flags |= JSPD_ARGUMENT;
|
||||
} else if (shape->getter() == GetCallVar) {
|
||||
} else if (shape->getter() == CallObject::getVarOp) {
|
||||
pd->slot = shape->shortid();
|
||||
pd->flags |= JSPD_VARIABLE;
|
||||
} else {
|
||||
|
@ -928,48 +928,48 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
|
|||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure)
|
||||
{
|
||||
rt->globalDebugHooks.debuggerHandler = handler;
|
||||
rt->globalDebugHooks.debuggerHandlerData = closure;
|
||||
rt->debugHooks.debuggerHandler = handler;
|
||||
rt->debugHooks.debuggerHandlerData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure)
|
||||
{
|
||||
rt->globalDebugHooks.sourceHandler = handler;
|
||||
rt->globalDebugHooks.sourceHandlerData = closure;
|
||||
rt->debugHooks.sourceHandler = handler;
|
||||
rt->debugHooks.sourceHandlerData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
|
||||
{
|
||||
rt->globalDebugHooks.executeHook = hook;
|
||||
rt->globalDebugHooks.executeHookData = closure;
|
||||
rt->debugHooks.executeHook = hook;
|
||||
rt->debugHooks.executeHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
|
||||
{
|
||||
rt->globalDebugHooks.callHook = hook;
|
||||
rt->globalDebugHooks.callHookData = closure;
|
||||
rt->debugHooks.callHook = hook;
|
||||
rt->debugHooks.callHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetThrowHook(JSRuntime *rt, JSThrowHook hook, void *closure)
|
||||
{
|
||||
rt->globalDebugHooks.throwHook = hook;
|
||||
rt->globalDebugHooks.throwHookData = closure;
|
||||
rt->debugHooks.throwHook = hook;
|
||||
rt->debugHooks.throwHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
|
||||
{
|
||||
rt->globalDebugHooks.debugErrorHook = hook;
|
||||
rt->globalDebugHooks.debugErrorHookData = closure;
|
||||
rt->debugHooks.debugErrorHook = hook;
|
||||
rt->debugHooks.debugErrorHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1086,25 +1086,7 @@ js_RevertVersion(JSContext *cx)
|
|||
JS_PUBLIC_API(const JSDebugHooks *)
|
||||
JS_GetGlobalDebugHooks(JSRuntime *rt)
|
||||
{
|
||||
return &rt->globalDebugHooks;
|
||||
}
|
||||
|
||||
const JSDebugHooks js_NullDebugHooks = {};
|
||||
|
||||
JS_PUBLIC_API(JSDebugHooks *)
|
||||
JS_SetContextDebugHooks(JSContext *cx, const JSDebugHooks *hooks)
|
||||
{
|
||||
JS_ASSERT(hooks);
|
||||
|
||||
JSDebugHooks *old = const_cast<JSDebugHooks *>(cx->debugHooks);
|
||||
cx->debugHooks = hooks;
|
||||
return old;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSDebugHooks *)
|
||||
JS_ClearContextDebugHooks(JSContext *cx)
|
||||
{
|
||||
return JS_SetContextDebugHooks(cx, &js_NullDebugHooks);
|
||||
return &rt->debugHooks;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
|
|
@ -477,13 +477,6 @@ js_RevertVersion(JSContext *cx);
|
|||
extern JS_PUBLIC_API(const JSDebugHooks *)
|
||||
JS_GetGlobalDebugHooks(JSRuntime *rt);
|
||||
|
||||
extern JS_PUBLIC_API(JSDebugHooks *)
|
||||
JS_SetContextDebugHooks(JSContext *cx, const JSDebugHooks *hooks);
|
||||
|
||||
/* Disable debug hooks for this context. */
|
||||
extern JS_PUBLIC_API(JSDebugHooks *)
|
||||
JS_ClearContextDebugHooks(JSContext *cx);
|
||||
|
||||
/**
|
||||
* Start any profilers that are available and have been configured on for this
|
||||
* platform. This is NOT thread safe.
|
||||
|
|
|
@ -591,17 +591,17 @@ VersionSetXML(JSVersion version, bool enable)
|
|||
JS_FRIEND_API(bool)
|
||||
CanCallContextDebugHandler(JSContext *cx)
|
||||
{
|
||||
return cx->debugHooks && cx->debugHooks->debuggerHandler;
|
||||
return !!cx->runtime->debugHooks.debuggerHandler;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSTrapStatus)
|
||||
CallContextDebugHandler(JSContext *cx, JSScript *script, jsbytecode *bc, Value *rval)
|
||||
{
|
||||
if (!CanCallContextDebugHandler(cx))
|
||||
if (!cx->runtime->debugHooks.debuggerHandler)
|
||||
return JSTRAP_RETURN;
|
||||
|
||||
return cx->debugHooks->debuggerHandler(cx, script, bc, rval,
|
||||
cx->debugHooks->debuggerHandlerData);
|
||||
return cx->runtime->debugHooks.debuggerHandler(cx, script, bc, rval,
|
||||
cx->runtime->debugHooks.debuggerHandlerData);
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
|
364
js/src/jsfun.cpp
364
js/src/jsfun.cpp
|
@ -101,21 +101,6 @@ using namespace js;
|
|||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
JSBool
|
||||
js_GetArgsValue(JSContext *cx, StackFrame *fp, Value *vp)
|
||||
{
|
||||
JSObject *argsobj;
|
||||
if (fp->hasOverriddenArgs()) {
|
||||
JS_ASSERT(fp->hasCallObj());
|
||||
return fp->callObj().getProperty(cx, cx->runtime->atomState.argumentsAtom, vp);
|
||||
}
|
||||
argsobj = js_GetArgsObject(cx, fp);
|
||||
if (!argsobj)
|
||||
return JS_FALSE;
|
||||
vp->setObject(*argsobj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
js::ArgumentsObject *
|
||||
ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee)
|
||||
{
|
||||
|
@ -148,7 +133,8 @@ ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee)
|
|||
return NULL;
|
||||
|
||||
data->callee.init(ObjectValue(callee));
|
||||
InitValueRange(data->slots, argc, false);
|
||||
for (HeapValue *vp = data->slots; vp != data->slots + argc; vp++)
|
||||
vp->init(UndefinedValue());
|
||||
|
||||
/* We have everything needed to fill in the object, so make the object. */
|
||||
JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyArgumentsShape, type, NULL);
|
||||
|
@ -182,7 +168,7 @@ struct STATIC_SKIP_INFERENCE PutArg
|
|||
}
|
||||
};
|
||||
|
||||
JSObject *
|
||||
ArgumentsObject *
|
||||
js_GetArgsObject(JSContext *cx, StackFrame *fp)
|
||||
{
|
||||
/*
|
||||
|
@ -613,350 +599,6 @@ Class js::StrictArgumentsObjectClass = {
|
|||
}
|
||||
};
|
||||
|
||||
namespace js {
|
||||
|
||||
CallObject *
|
||||
CreateFunCallObject(JSContext *cx, StackFrame *fp)
|
||||
{
|
||||
JS_ASSERT(fp->isNonEvalFunctionFrame());
|
||||
JS_ASSERT(!fp->hasCallObj());
|
||||
|
||||
JSObject *scopeChain = &fp->scopeChain();
|
||||
JS_ASSERT_IF(scopeChain->isWith() || scopeChain->isBlock() || scopeChain->isCall(),
|
||||
scopeChain->getPrivate() != fp);
|
||||
|
||||
/*
|
||||
* For a named function expression Call's parent points to an environment
|
||||
* object holding function's name.
|
||||
*/
|
||||
if (JSAtom *lambdaName = CallObjectLambdaName(fp->fun())) {
|
||||
scopeChain = DeclEnvObject::create(cx, fp);
|
||||
if (!scopeChain)
|
||||
return NULL;
|
||||
|
||||
if (!DefineNativeProperty(cx, scopeChain, ATOM_TO_JSID(lambdaName),
|
||||
ObjectValue(fp->callee()), NULL, NULL,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CallObject *callobj = CallObject::create(cx, fp->script(), *scopeChain, &fp->callee());
|
||||
if (!callobj)
|
||||
return NULL;
|
||||
|
||||
callobj->setStackFrame(fp);
|
||||
fp->setScopeChainWithOwnCallObj(*callobj);
|
||||
return callobj;
|
||||
}
|
||||
|
||||
CallObject *
|
||||
CreateEvalCallObject(JSContext *cx, StackFrame *fp)
|
||||
{
|
||||
CallObject *callobj = CallObject::create(cx, fp->script(), fp->scopeChain(), NULL);
|
||||
if (!callobj)
|
||||
return NULL;
|
||||
|
||||
callobj->setStackFrame(fp);
|
||||
fp->setScopeChainWithOwnCallObj(*callobj);
|
||||
return callobj;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
void
|
||||
js_PutCallObject(StackFrame *fp)
|
||||
{
|
||||
CallObject &callobj = fp->callObj().asCall();
|
||||
JS_ASSERT(callobj.maybeStackFrame() == fp);
|
||||
JS_ASSERT_IF(fp->isEvalFrame(), fp->isStrictEvalFrame());
|
||||
JS_ASSERT(fp->isEvalFrame() == callobj.isForEval());
|
||||
|
||||
/* Get the arguments object to snapshot fp's actual argument values. */
|
||||
if (fp->hasArgsObj()) {
|
||||
if (!fp->hasOverriddenArgs())
|
||||
callobj.initArguments(ObjectValue(fp->argsObj()));
|
||||
js_PutArgsObject(fp);
|
||||
}
|
||||
|
||||
JSScript *script = fp->script();
|
||||
Bindings &bindings = script->bindings;
|
||||
|
||||
if (callobj.isForEval()) {
|
||||
JS_ASSERT(script->strictModeCode);
|
||||
JS_ASSERT(bindings.countArgs() == 0);
|
||||
|
||||
/* This could be optimized as below, but keep it simple for now. */
|
||||
callobj.copyValues(0, NULL, bindings.countVars(), fp->slots());
|
||||
} else {
|
||||
JSFunction *fun = fp->fun();
|
||||
JS_ASSERT(script == callobj.getCalleeFunction()->script());
|
||||
JS_ASSERT(script == fun->script());
|
||||
|
||||
uintN n = bindings.countArgsAndVars();
|
||||
if (n > 0) {
|
||||
uint32_t nvars = bindings.countVars();
|
||||
uint32_t nargs = bindings.countArgs();
|
||||
JS_ASSERT(fun->nargs == nargs);
|
||||
JS_ASSERT(nvars + nargs == n);
|
||||
|
||||
JSScript *script = fun->script();
|
||||
if (script->usesEval
|
||||
#ifdef JS_METHODJIT
|
||||
|| script->debugMode
|
||||
#endif
|
||||
) {
|
||||
callobj.copyValues(nargs, fp->formalArgs(), nvars, fp->slots());
|
||||
} else {
|
||||
/*
|
||||
* For each arg & var that is closed over, copy it from the stack
|
||||
* into the call object. We use initArg/VarUnchecked because,
|
||||
* when you call a getter on a call object, js_NativeGetInline
|
||||
* caches the return value in the slot, so we can't assert that
|
||||
* it's undefined.
|
||||
*/
|
||||
uint32_t nclosed = script->nClosedArgs;
|
||||
for (uint32_t i = 0; i < nclosed; i++) {
|
||||
uint32_t e = script->getClosedArg(i);
|
||||
#ifdef JS_GC_ZEAL
|
||||
callobj.setArg(e, fp->formalArg(e));
|
||||
#else
|
||||
callobj.initArgUnchecked(e, fp->formalArg(e));
|
||||
#endif
|
||||
}
|
||||
|
||||
nclosed = script->nClosedVars;
|
||||
for (uint32_t i = 0; i < nclosed; i++) {
|
||||
uint32_t e = script->getClosedVar(i);
|
||||
#ifdef JS_GC_ZEAL
|
||||
callobj.setVar(e, fp->slots()[e]);
|
||||
#else
|
||||
callobj.initVarUnchecked(e, fp->slots()[e]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the args and vars for the active call if this is an outer
|
||||
* function in a script nesting.
|
||||
*/
|
||||
types::TypeScriptNesting *nesting = script->nesting();
|
||||
if (nesting && script->isOuterFunction) {
|
||||
nesting->argArray = callobj.argArray();
|
||||
nesting->varArray = callobj.varArray();
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear private pointers to fp, which is about to go away. */
|
||||
if (js_IsNamedLambda(fun)) {
|
||||
JSObject &env = callobj.enclosingScope();
|
||||
JS_ASSERT(env.asDeclEnv().maybeStackFrame() == fp);
|
||||
env.setPrivate(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
callobj.setStackFrame(NULL);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
static JSBool
|
||||
GetCallArguments(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
CallObject &callobj = obj->asCall();
|
||||
|
||||
StackFrame *fp = callobj.maybeStackFrame();
|
||||
if (fp && !fp->hasOverriddenArgs()) {
|
||||
JSObject *argsobj = js_GetArgsObject(cx, fp);
|
||||
if (!argsobj)
|
||||
return false;
|
||||
vp->setObject(*argsobj);
|
||||
} else {
|
||||
*vp = callobj.getArguments();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
SetCallArguments(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
{
|
||||
CallObject &callobj = obj->asCall();
|
||||
|
||||
if (StackFrame *fp = callobj.maybeStackFrame())
|
||||
fp->setOverriddenArgs();
|
||||
callobj.setArguments(*vp);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
GetCallArg(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
CallObject &callobj = obj->asCall();
|
||||
JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
|
||||
uintN i = (uint16_t) JSID_TO_INT(id);
|
||||
|
||||
if (StackFrame *fp = callobj.maybeStackFrame())
|
||||
*vp = fp->formalArg(i);
|
||||
else
|
||||
*vp = callobj.arg(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
{
|
||||
CallObject &callobj = obj->asCall();
|
||||
JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
|
||||
uintN i = (uint16_t) JSID_TO_INT(id);
|
||||
|
||||
if (StackFrame *fp = callobj.maybeStackFrame())
|
||||
fp->formalArg(i) = *vp;
|
||||
else
|
||||
callobj.setArg(i, *vp);
|
||||
|
||||
JSFunction *fun = callobj.getCalleeFunction();
|
||||
JSScript *script = fun->script();
|
||||
if (!script->ensureHasTypes(cx))
|
||||
return false;
|
||||
|
||||
TypeScript::SetArgument(cx, script, i, *vp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
CallObject &callobj = obj->asCall();
|
||||
JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
|
||||
uintN i = (uint16_t) JSID_TO_INT(id);
|
||||
|
||||
*vp = callobj.getCallee()->toFunction()->getFlatClosureUpvar(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
{
|
||||
CallObject &callobj = obj->asCall();
|
||||
JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
|
||||
uintN i = (uint16_t) JSID_TO_INT(id);
|
||||
|
||||
callobj.getCallee()->toFunction()->setFlatClosureUpvar(i, *vp);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
GetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
CallObject &callobj = obj->asCall();
|
||||
JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
|
||||
uintN i = (uint16_t) JSID_TO_INT(id);
|
||||
|
||||
if (StackFrame *fp = callobj.maybeStackFrame())
|
||||
*vp = fp->varSlot(i);
|
||||
else
|
||||
*vp = callobj.var(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
{
|
||||
CallObject &callobj = obj->asCall();
|
||||
|
||||
JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
|
||||
uintN i = (uint16_t) JSID_TO_INT(id);
|
||||
|
||||
if (StackFrame *fp = callobj.maybeStackFrame())
|
||||
fp->varSlot(i) = *vp;
|
||||
else
|
||||
callobj.setVar(i, *vp);
|
||||
|
||||
JSFunction *fun = callobj.getCalleeFunction();
|
||||
JSScript *script = fun->script();
|
||||
if (!script->ensureHasTypes(cx))
|
||||
return false;
|
||||
|
||||
TypeScript::SetLocal(cx, script, i, *vp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
static JSBool
|
||||
call_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp)
|
||||
{
|
||||
JS_ASSERT(!obj->getProto());
|
||||
|
||||
if (!JSID_IS_ATOM(id))
|
||||
return true;
|
||||
|
||||
JSObject *callee = obj->asCall().getCallee();
|
||||
#ifdef DEBUG
|
||||
if (callee) {
|
||||
JSScript *script = callee->toFunction()->script();
|
||||
JS_ASSERT(!script->bindings.hasBinding(cx, JSID_TO_ATOM(id)));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Resolve arguments so that we never store a particular Call object's
|
||||
* arguments object reference in a Call prototype's |arguments| slot.
|
||||
*
|
||||
* Include JSPROP_ENUMERATE for consistency with all other Call object
|
||||
* properties; see js::Bindings::add and js::Interpret's JSOP_DEFFUN
|
||||
* rebinding-Call-property logic.
|
||||
*/
|
||||
if (callee && id == ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom)) {
|
||||
if (!DefineNativeProperty(cx, obj, id, UndefinedValue(),
|
||||
GetCallArguments, SetCallArguments,
|
||||
JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE,
|
||||
0, 0, DNP_DONT_PURGE)) {
|
||||
return false;
|
||||
}
|
||||
*objp = obj;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Control flow reaches here only if id was not resolved. */
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
call_trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isCall());
|
||||
|
||||
/* Mark any generator frame, as for arguments objects. */
|
||||
#if JS_HAS_GENERATORS
|
||||
StackFrame *fp = (StackFrame *) obj->getPrivate();
|
||||
if (fp && fp->isFloatingGenerator())
|
||||
MarkObject(trc, &js_FloatingFrameToGenerator(fp)->obj, "generator object");
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_PUBLIC_DATA(Class) js::CallClass = {
|
||||
"Call",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(CallObject::RESERVED_SLOTS) |
|
||||
JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS,
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
(JSResolveOp)call_resolve,
|
||||
NULL, /* convert: Leave it NULL so we notice if calls ever escape */
|
||||
NULL, /* finalize */
|
||||
NULL, /* checkAccess */
|
||||
NULL, /* call */
|
||||
NULL, /* construct */
|
||||
NULL, /* hasInstance */
|
||||
call_trace
|
||||
};
|
||||
|
||||
bool
|
||||
StackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
|
||||
{
|
||||
|
|
|
@ -362,30 +362,6 @@ js_PutCallObject(js::StackFrame *fp);
|
|||
|
||||
namespace js {
|
||||
|
||||
CallObject *
|
||||
CreateFunCallObject(JSContext *cx, StackFrame *fp);
|
||||
|
||||
CallObject *
|
||||
CreateEvalCallObject(JSContext *cx, StackFrame *fp);
|
||||
|
||||
extern JSBool
|
||||
GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
|
||||
|
||||
/*
|
||||
* Function extended with reserved slots for use by various kinds of functions.
|
||||
* Most functions do not have these extensions, but enough are that efficient
|
||||
|
@ -415,9 +391,6 @@ JSFunction::toExtended() const
|
|||
return static_cast<const js::FunctionExtended *>(this);
|
||||
}
|
||||
|
||||
extern JSBool
|
||||
js_GetArgsValue(JSContext *cx, js::StackFrame *fp, js::Value *vp);
|
||||
|
||||
/*
|
||||
* Get the arguments object for the given frame. If the frame is strict mode
|
||||
* code, its current arguments will be copied into the arguments object.
|
||||
|
@ -428,7 +401,7 @@ js_GetArgsValue(JSContext *cx, js::StackFrame *fp, js::Value *vp);
|
|||
* named parameter by synthesizing an arguments access at the start of the
|
||||
* function.
|
||||
*/
|
||||
extern JSObject *
|
||||
extern js::ArgumentsObject *
|
||||
js_GetArgsObject(JSContext *cx, js::StackFrame *fp);
|
||||
|
||||
extern void
|
||||
|
|
|
@ -2118,6 +2118,13 @@ GCMarker::GrayCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
|||
gcmarker->appendGrayRoot(*thingp, kind);
|
||||
}
|
||||
|
||||
size_t
|
||||
GCMarker::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const
|
||||
{
|
||||
return stack.sizeOfExcludingThis(mallocSizeOf) +
|
||||
grayRoots.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
SetMarkStackLimit(JSRuntime *rt, size_t limit)
|
||||
{
|
||||
|
@ -3078,7 +3085,7 @@ ValidateIncrementalMarking(JSContext *cx)
|
|||
JSRuntime *rt = cx->runtime;
|
||||
FullGCMarker *gcmarker = &rt->gcMarker;
|
||||
|
||||
/* Save existing mark bits */
|
||||
/* Save existing mark bits. */
|
||||
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
|
||||
ChunkBitmap *bitmap = &r.front()->bitmap;
|
||||
uintptr_t *entry = (uintptr_t *)js_malloc(sizeof(bitmap->bitmap));
|
||||
|
@ -3090,6 +3097,11 @@ ValidateIncrementalMarking(JSContext *cx)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Save the existing weakmaps. */
|
||||
WeakMapVector weakmaps;
|
||||
if (!WeakMapBase::saveWeakMapList(rt, weakmaps))
|
||||
return;
|
||||
|
||||
/*
|
||||
* After this point, the function should run to completion, so we shouldn't
|
||||
* do anything fallible.
|
||||
|
@ -3099,6 +3111,9 @@ ValidateIncrementalMarking(JSContext *cx)
|
|||
js::gc::State state = rt->gcIncrementalState;
|
||||
rt->gcIncrementalState = NO_INCREMENTAL;
|
||||
|
||||
/* As we're re-doing marking, we need to reset the weak map list. */
|
||||
WeakMapBase::resetWeakMapList(rt);
|
||||
|
||||
JS_ASSERT(gcmarker->isDrained());
|
||||
gcmarker->reset();
|
||||
|
||||
|
@ -3146,6 +3161,10 @@ ValidateIncrementalMarking(JSContext *cx)
|
|||
memcpy(bitmap->bitmap, incBitmap.bitmap, sizeof(incBitmap.bitmap));
|
||||
}
|
||||
|
||||
/* Restore the weak map list. */
|
||||
WeakMapBase::resetWeakMapList(rt);
|
||||
WeakMapBase::restoreWeakMapList(rt, weakmaps);
|
||||
|
||||
rt->gcIncrementalState = state;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1690,6 +1690,14 @@ struct MarkStack {
|
|||
limit = newStack + newcap;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const {
|
||||
size_t n = 0;
|
||||
if (stack != ballast)
|
||||
n += mallocSizeOf(stack);
|
||||
n += mallocSizeOf(ballast);
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1827,6 +1835,8 @@ struct GCMarker : public JSTracer {
|
|||
|
||||
static void GrayCallback(JSTracer *trc, void **thing, JSGCTraceKind kind);
|
||||
|
||||
size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const;
|
||||
|
||||
MarkStack<uintptr_t> stack;
|
||||
|
||||
private:
|
||||
|
|
|
@ -356,6 +356,41 @@ MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name)
|
|||
}
|
||||
}
|
||||
|
||||
/*** Slot Marking ***/
|
||||
|
||||
void
|
||||
MarkSlot(JSTracer *trc, HeapSlot *s, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkValueInternal(trc, s->unsafeGet());
|
||||
}
|
||||
|
||||
void
|
||||
MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
JS_SET_TRACING_INDEX(trc, name, i);
|
||||
MarkValueInternal(trc, vec[i].unsafeGet());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name)
|
||||
{
|
||||
if (s->isMarkable()) {
|
||||
Cell *cell = (Cell *)s->toGCThing();
|
||||
JSRuntime *rt = trc->runtime;
|
||||
if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment)
|
||||
return;
|
||||
|
||||
/* In case we're called from a write barrier. */
|
||||
if (rt->gcIncrementalCompartment && cell->compartment() != rt->gcIncrementalCompartment)
|
||||
return;
|
||||
|
||||
MarkSlot(trc, s, name);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Special Marking ***/
|
||||
|
||||
/*
|
||||
|
@ -376,23 +411,6 @@ MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name)
|
|||
MarkValueInternal(trc, v);
|
||||
}
|
||||
|
||||
void
|
||||
MarkCrossCompartmentValue(JSTracer *trc, HeapValue *v, const char *name)
|
||||
{
|
||||
if (v->isMarkable()) {
|
||||
Cell *cell = (Cell *)v->toGCThing();
|
||||
JSRuntime *rt = trc->runtime;
|
||||
if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment)
|
||||
return;
|
||||
|
||||
/* In case we're called from a write barrier. */
|
||||
if (rt->gcIncrementalCompartment && cell->compartment() != rt->gcIncrementalCompartment)
|
||||
return;
|
||||
|
||||
MarkValue(trc, v, name);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Push Mark Stack ***/
|
||||
|
||||
#define JS_COMPARTMENT_ASSERT(rt, thing) \
|
||||
|
@ -896,21 +914,21 @@ PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
|
|||
|
||||
using namespace js::gc;
|
||||
|
||||
struct ValueArrayLayout
|
||||
struct SlotArrayLayout
|
||||
{
|
||||
union {
|
||||
HeapValue *end;
|
||||
HeapSlot *end;
|
||||
js::Class *clasp;
|
||||
};
|
||||
union {
|
||||
HeapValue *start;
|
||||
HeapSlot *start;
|
||||
uintptr_t index;
|
||||
};
|
||||
JSObject *obj;
|
||||
|
||||
static void staticAsserts() {
|
||||
/* This should have the same layout as three mark stack items. */
|
||||
JS_STATIC_ASSERT(sizeof(ValueArrayLayout) == 3 * sizeof(uintptr_t));
|
||||
JS_STATIC_ASSERT(sizeof(SlotArrayLayout) == 3 * sizeof(uintptr_t));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -933,16 +951,16 @@ GCMarker::saveValueRanges()
|
|||
uintptr_t tag = *--p & StackTagMask;
|
||||
if (tag == ValueArrayTag) {
|
||||
p -= 2;
|
||||
ValueArrayLayout *arr = reinterpret_cast<ValueArrayLayout *>(p);
|
||||
SlotArrayLayout *arr = reinterpret_cast<SlotArrayLayout *>(p);
|
||||
JSObject *obj = arr->obj;
|
||||
|
||||
if (obj->getClass() == &ArrayClass) {
|
||||
HeapValue *vp = obj->getDenseArrayElements();
|
||||
HeapSlot *vp = obj->getDenseArrayElements();
|
||||
JS_ASSERT(arr->start >= vp &&
|
||||
arr->end == vp + obj->getDenseArrayInitializedLength());
|
||||
arr->index = arr->start - vp;
|
||||
} else {
|
||||
HeapValue *vp = obj->fixedSlots();
|
||||
HeapSlot *vp = obj->fixedSlots();
|
||||
unsigned nfixed = obj->numFixedSlots();
|
||||
if (arr->start >= vp && arr->start < vp + nfixed) {
|
||||
JS_ASSERT(arr->end == vp + Min(nfixed, obj->slotSpan()));
|
||||
|
@ -975,7 +993,7 @@ GCMarker::restoreValueArray(JSObject *obj, void **vpp, void **endp)
|
|||
return false;
|
||||
|
||||
uint32_t initlen = obj->getDenseArrayInitializedLength();
|
||||
HeapValue *vp = obj->getDenseArrayElements();
|
||||
HeapSlot *vp = obj->getDenseArrayElements();
|
||||
if (start < initlen) {
|
||||
*vpp = vp + start;
|
||||
*endp = vp + initlen;
|
||||
|
@ -984,7 +1002,7 @@ GCMarker::restoreValueArray(JSObject *obj, void **vpp, void **endp)
|
|||
*vpp = *endp = vp;
|
||||
}
|
||||
} else {
|
||||
HeapValue *vp = obj->fixedSlots();
|
||||
HeapSlot *vp = obj->fixedSlots();
|
||||
unsigned nfixed = obj->numFixedSlots();
|
||||
unsigned nslots = obj->slotSpan();
|
||||
if (start < nfixed) {
|
||||
|
@ -1011,7 +1029,7 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
|||
* object directly. It allows to eliminate the tail recursion and
|
||||
* significantly improve the marking performance, see bug 641025.
|
||||
*/
|
||||
HeapValue *vp, *end;
|
||||
HeapSlot *vp, *end;
|
||||
JSObject *obj;
|
||||
|
||||
uintptr_t addr = stack.pop();
|
||||
|
@ -1026,8 +1044,8 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
|||
uintptr_t addr3 = stack.pop();
|
||||
JS_ASSERT(addr2 <= addr3);
|
||||
JS_ASSERT((addr3 - addr2) % sizeof(Value) == 0);
|
||||
vp = reinterpret_cast<HeapValue *>(addr2);
|
||||
end = reinterpret_cast<HeapValue *>(addr3);
|
||||
vp = reinterpret_cast<HeapSlot *>(addr2);
|
||||
end = reinterpret_cast<HeapSlot *>(addr3);
|
||||
goto scan_value_array;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,18 +114,26 @@ MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name)
|
|||
MarkValueRootRange(trc, end - begin, begin, name);
|
||||
}
|
||||
|
||||
/*** Special Cases ***/
|
||||
/*** Slot Marking ***/
|
||||
|
||||
/* Direct value access used by the write barriers and the methodjit */
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
|
||||
MarkSlot(JSTracer *trc, HeapSlot *s, const char *name);
|
||||
|
||||
void
|
||||
MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name);
|
||||
|
||||
/*
|
||||
* Mark a value that may be in a different compartment from the compartment
|
||||
* being GC'd. (Although it won't be marked if it's in the wrong compartment.)
|
||||
*/
|
||||
void
|
||||
MarkCrossCompartmentValue(JSTracer *trc, HeapValue *v, const char *name);
|
||||
MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name);
|
||||
|
||||
/*** Special Cases ***/
|
||||
|
||||
/* Direct value access used by the write barriers and the methodjit. */
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
|
||||
|
||||
/*
|
||||
* MarkChildren<JSObject> is exposed solely for preWriteBarrier on
|
||||
|
|
|
@ -1688,10 +1688,8 @@ types::MarkArgumentsCreated(JSContext *cx, JSScript *script)
|
|||
*/
|
||||
Value *sp = fp->base() + analysis->getCode(iter.pc()).stackDepth;
|
||||
for (Value *vp = fp->slots(); vp < sp; vp++) {
|
||||
if (vp->isParticularMagic(JS_LAZY_ARGUMENTS)) {
|
||||
if (!js_GetArgsValue(cx, fp, vp))
|
||||
vp->setNull();
|
||||
}
|
||||
if (vp->isParticularMagic(JS_LAZY_ARGUMENTS))
|
||||
*vp = ObjectOrNullValue(js_GetArgsObject(cx, fp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2412,6 +2410,11 @@ ScriptAnalysis::addTypeBarrier(JSContext *cx, const jsbytecode *pc, TypeSet *tar
|
|||
|
||||
barrier = cx->typeLifoAlloc().new_<TypeBarrier>(target, type, (JSObject *) NULL, JSID_VOID);
|
||||
|
||||
if (!barrier) {
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
barrier->next = code.typeBarriers;
|
||||
code.typeBarriers = barrier;
|
||||
}
|
||||
|
@ -2438,6 +2441,11 @@ ScriptAnalysis::addSingletonTypeBarrier(JSContext *cx, const jsbytecode *pc, Typ
|
|||
TypeBarrier *barrier = cx->typeLifoAlloc().new_<TypeBarrier>(target, Type::UndefinedType(),
|
||||
singleton, singletonId);
|
||||
|
||||
if (!barrier) {
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
barrier->next = code.typeBarriers;
|
||||
code.typeBarriers = barrier;
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
|
|||
JSObject *limitBlock, *limitClone;
|
||||
if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj()) {
|
||||
JS_ASSERT_IF(fp->scopeChain().isClonedBlock(), fp->scopeChain().getPrivate() != fp);
|
||||
if (!CreateFunCallObject(cx, fp))
|
||||
if (!CallObject::createForFunction(cx, fp))
|
||||
return NULL;
|
||||
|
||||
/* We know we must clone everything on blockChain. */
|
||||
|
@ -646,7 +646,7 @@ js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const V
|
|||
|
||||
/* Give strict mode eval its own fresh lexical environment. */
|
||||
StackFrame *fp = efg.fp();
|
||||
if (fp->isStrictEvalFrame() && !CreateEvalCallObject(cx, fp))
|
||||
if (fp->isStrictEvalFrame() && !CallObject::createForStrictEval(cx, fp))
|
||||
return false;
|
||||
|
||||
Probes::startExecution(cx, script);
|
||||
|
@ -1444,7 +1444,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
|
|||
|
||||
#define CHECK_INTERRUPT_HANDLER() \
|
||||
JS_BEGIN_MACRO \
|
||||
if (cx->debugHooks->interruptHook) \
|
||||
if (cx->runtime->debugHooks.interruptHook) \
|
||||
ENABLE_INTERRUPTS(); \
|
||||
JS_END_MACRO
|
||||
|
||||
|
@ -1591,12 +1591,12 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
|
|||
moreInterrupts = true;
|
||||
}
|
||||
|
||||
JSInterruptHook hook = cx->debugHooks->interruptHook;
|
||||
JSInterruptHook hook = cx->runtime->debugHooks.interruptHook;
|
||||
if (hook || script->stepModeEnabled()) {
|
||||
Value rval;
|
||||
JSTrapStatus status = JSTRAP_CONTINUE;
|
||||
if (hook)
|
||||
status = hook(cx, script, regs.pc, &rval, cx->debugHooks->interruptHookData);
|
||||
status = hook(cx, script, regs.pc, &rval, cx->runtime->debugHooks.interruptHookData);
|
||||
if (status == JSTRAP_CONTINUE && script->stepModeEnabled())
|
||||
status = Debugger::onSingleStep(cx, &rval);
|
||||
switch (status) {
|
||||
|
@ -1967,7 +1967,7 @@ BEGIN_CASE(JSOP_ITER)
|
|||
{
|
||||
JS_ASSERT(regs.sp > regs.fp()->base());
|
||||
uint8_t flags = GET_UINT8(regs.pc);
|
||||
if (!js_ValueToIterator(cx, flags, ®s.sp[-1]))
|
||||
if (!ValueToIterator(cx, flags, ®s.sp[-1]))
|
||||
goto error;
|
||||
CHECK_INTERRUPT_HANDLER();
|
||||
JS_ASSERT(!regs.sp[-1].isPrimitive());
|
||||
|
@ -2001,7 +2001,7 @@ END_CASE(JSOP_ITERNEXT)
|
|||
BEGIN_CASE(JSOP_ENDITER)
|
||||
{
|
||||
JS_ASSERT(regs.sp - 1 >= regs.fp()->base());
|
||||
bool ok = !!js_CloseIterator(cx, ®s.sp[-1].toObject());
|
||||
bool ok = CloseIterator(cx, ®s.sp[-1].toObject());
|
||||
regs.sp--;
|
||||
if (!ok)
|
||||
goto error;
|
||||
|
@ -3000,14 +3000,18 @@ BEGIN_CASE(JSOP_ARGUMENTS)
|
|||
if (!script->ensureRanInference(cx))
|
||||
goto error;
|
||||
if (script->createdArgs) {
|
||||
if (!js_GetArgsValue(cx, regs.fp(), &rval))
|
||||
ArgumentsObject *arguments = js_GetArgsObject(cx, regs.fp());
|
||||
if (!arguments)
|
||||
goto error;
|
||||
rval = ObjectValue(*arguments);
|
||||
} else {
|
||||
rval = MagicValue(JS_LAZY_ARGUMENTS);
|
||||
}
|
||||
} else {
|
||||
if (!js_GetArgsValue(cx, regs.fp(), &rval))
|
||||
ArgumentsObject *arguments = js_GetArgsObject(cx, regs.fp());
|
||||
if (!arguments)
|
||||
goto error;
|
||||
rval = ObjectValue(*arguments);
|
||||
}
|
||||
PUSH_COPY(rval);
|
||||
}
|
||||
|
@ -3667,8 +3671,8 @@ BEGIN_CASE(JSOP_DEBUGGER)
|
|||
{
|
||||
JSTrapStatus st = JSTRAP_CONTINUE;
|
||||
Value rval;
|
||||
if (JSDebuggerHandler handler = cx->debugHooks->debuggerHandler)
|
||||
st = handler(cx, script, regs.pc, &rval, cx->debugHooks->debuggerHandlerData);
|
||||
if (JSDebuggerHandler handler = cx->runtime->debugHooks.debuggerHandler)
|
||||
st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.debuggerHandlerData);
|
||||
if (st == JSTRAP_CONTINUE)
|
||||
st = Debugger::onDebuggerStatement(cx, &rval);
|
||||
switch (st) {
|
||||
|
@ -4227,13 +4231,13 @@ END_CASE(JSOP_ARRAYPUSH)
|
|||
atoms = script->atoms;
|
||||
|
||||
/* Call debugger throw hook if set. */
|
||||
if (cx->debugHooks->throwHook || !cx->compartment->getDebuggees().empty()) {
|
||||
if (cx->runtime->debugHooks.throwHook || !cx->compartment->getDebuggees().empty()) {
|
||||
Value rval;
|
||||
JSTrapStatus st = Debugger::onExceptionUnwind(cx, &rval);
|
||||
if (st == JSTRAP_CONTINUE) {
|
||||
handler = cx->debugHooks->throwHook;
|
||||
handler = cx->runtime->debugHooks.throwHook;
|
||||
if (handler)
|
||||
st = handler(cx, script, regs.pc, &rval, cx->debugHooks->throwHookData);
|
||||
st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.throwHookData);
|
||||
}
|
||||
|
||||
switch (st) {
|
||||
|
@ -4330,13 +4334,10 @@ END_CASE(JSOP_ARRAYPUSH)
|
|||
case JSTRY_ITER: {
|
||||
/* This is similar to JSOP_ENDITER in the interpreter loop. */
|
||||
JS_ASSERT(JSOp(*regs.pc) == JSOP_ENDITER);
|
||||
Value v = cx->getPendingException();
|
||||
cx->clearPendingException();
|
||||
bool ok = js_CloseIterator(cx, ®s.sp[-1].toObject());
|
||||
bool ok = UnwindIteratorForException(cx, ®s.sp[-1].toObject());
|
||||
regs.sp -= 1;
|
||||
if (!ok)
|
||||
goto error;
|
||||
cx->setPendingException(v);
|
||||
}
|
||||
}
|
||||
} while (++tn != tnlimit);
|
||||
|
|
|
@ -352,6 +352,22 @@ Debug_SetValueRangeToCrashOnTouch(HeapValue *vec, size_t len)
|
|||
#endif
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
Debug_SetSlotRangeToCrashOnTouch(HeapSlot *vec, size_t len)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Debug_SetValueRangeToCrashOnTouch((Value *) begin, end - begin);
|
||||
#endif
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsinterp_h___ */
|
||||
|
|
|
@ -829,7 +829,7 @@ Iterator(JSContext *cx, uintN argc, Value *vp)
|
|||
bool keyonly = argc >= 2 ? js_ValueToBoolean(argv[1]) : false;
|
||||
uintN flags = JSITER_OWNONLY | (keyonly ? 0 : (JSITER_FOREACH | JSITER_KEYVALUE));
|
||||
*vp = argc >= 1 ? argv[0] : UndefinedValue();
|
||||
return js_ValueToIterator(cx, flags, vp);
|
||||
return ValueToIterator(cx, flags, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -871,12 +871,19 @@ static JSFunctionSpec iterator_methods[] = {
|
|||
JS_FS_END
|
||||
};
|
||||
|
||||
#if JS_HAS_GENERATORS
|
||||
static JSBool
|
||||
CloseGenerator(JSContext *cx, JSObject *genobj);
|
||||
#endif
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* Call ToObject(v).__iterator__(keyonly) if ToObject(v).__iterator__ exists.
|
||||
* Otherwise construct the default iterator.
|
||||
*/
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_ValueToIterator(JSContext *cx, uintN flags, Value *vp)
|
||||
JSBool
|
||||
ValueToIterator(JSContext *cx, uintN flags, Value *vp)
|
||||
{
|
||||
/* JSITER_KEYVALUE must always come with JSITER_FOREACH */
|
||||
JS_ASSERT_IF(flags & JSITER_KEYVALUE, flags & JSITER_FOREACH);
|
||||
|
@ -914,13 +921,8 @@ js_ValueToIterator(JSContext *cx, uintN flags, Value *vp)
|
|||
return GetIterator(cx, obj, flags, vp);
|
||||
}
|
||||
|
||||
#if JS_HAS_GENERATORS
|
||||
static JSBool
|
||||
CloseGenerator(JSContext *cx, JSObject *genobj);
|
||||
#endif
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_CloseIterator(JSContext *cx, JSObject *obj)
|
||||
bool
|
||||
CloseIterator(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
cx->iterValue.setMagic(JS_NO_ITER_VALUE);
|
||||
|
||||
|
@ -950,6 +952,19 @@ js_CloseIterator(JSContext *cx, JSObject *obj)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
bool
|
||||
UnwindIteratorForException(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
Value v = cx->getPendingException();
|
||||
cx->clearPendingException();
|
||||
if (!CloseIterator(cx, obj))
|
||||
return false;
|
||||
cx->setPendingException(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
/*
|
||||
* Suppress enumeration of deleted properties. This function must be called
|
||||
* when a property is deleted and there might be active enumerators.
|
||||
|
|
|
@ -181,19 +181,22 @@ VectorToValueIterator(JSContext *cx, JSObject *obj, uintN flags, js::AutoIdVecto
|
|||
bool
|
||||
EnumeratedIdVectorToIterator(JSContext *cx, JSObject *obj, uintN flags, js::AutoIdVector &props, js::Value *vp);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the value stored in *vp to its iteration object. The flags should
|
||||
* contain JSITER_ENUMERATE if js_ValueToIterator is called when enumerating
|
||||
* for-in semantics are required, and when the caller can guarantee that the
|
||||
* iterator will never be exposed to scripts.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_ValueToIterator(JSContext *cx, uintN flags, js::Value *vp);
|
||||
extern JSBool
|
||||
ValueToIterator(JSContext *cx, uintN flags, js::Value *vp);
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_CloseIterator(JSContext *cx, JSObject *iterObj);
|
||||
extern bool
|
||||
CloseIterator(JSContext *cx, JSObject *iterObj);
|
||||
|
||||
extern bool
|
||||
UnwindIteratorForException(JSContext *cx, JSObject *obj);
|
||||
|
||||
}
|
||||
|
||||
extern bool
|
||||
js_SuppressDeletedProperty(JSContext *cx, JSObject *obj, jsid id);
|
||||
|
|
103
js/src/jsobj.cpp
103
js/src/jsobj.cpp
|
@ -2753,7 +2753,7 @@ NewObject(JSContext *cx, Class *clasp, types::TypeObject *type, JSObject *parent
|
|||
if (!shape)
|
||||
return NULL;
|
||||
|
||||
HeapValue *slots;
|
||||
HeapSlot *slots;
|
||||
if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
|
||||
return NULL;
|
||||
|
||||
|
@ -3250,8 +3250,8 @@ struct JSObject::TradeGutsReserved {
|
|||
int newbfixed;
|
||||
Shape *newashape;
|
||||
Shape *newbshape;
|
||||
HeapValue *newaslots;
|
||||
HeapValue *newbslots;
|
||||
HeapSlot *newaslots;
|
||||
HeapSlot *newbslots;
|
||||
|
||||
TradeGutsReserved(JSContext *cx)
|
||||
: cx(cx), avals(cx), bvals(cx),
|
||||
|
@ -3350,16 +3350,16 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b,
|
|||
unsigned bdynamic = dynamicSlotsCount(reserved.newbfixed, a->slotSpan());
|
||||
|
||||
if (adynamic) {
|
||||
reserved.newaslots = (HeapValue *) cx->malloc_(sizeof(HeapValue) * adynamic);
|
||||
reserved.newaslots = (HeapSlot *) cx->malloc_(sizeof(HeapSlot) * adynamic);
|
||||
if (!reserved.newaslots)
|
||||
return false;
|
||||
Debug_SetValueRangeToCrashOnTouch(reserved.newaslots, adynamic);
|
||||
Debug_SetSlotRangeToCrashOnTouch(reserved.newaslots, adynamic);
|
||||
}
|
||||
if (bdynamic) {
|
||||
reserved.newbslots = (HeapValue *) cx->malloc_(sizeof(HeapValue) * bdynamic);
|
||||
reserved.newbslots = (HeapSlot *) cx->malloc_(sizeof(HeapSlot) * bdynamic);
|
||||
if (!reserved.newbslots)
|
||||
return false;
|
||||
Debug_SetValueRangeToCrashOnTouch(reserved.newbslots, bdynamic);
|
||||
Debug_SetSlotRangeToCrashOnTouch(reserved.newbslots, bdynamic);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -3421,11 +3421,10 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
|||
* Trigger post barriers for fixed slots. JSObject bits are barriered
|
||||
* below, in common with the other case.
|
||||
*/
|
||||
JSCompartment *comp = cx->compartment;
|
||||
for (size_t i = 0; i < a->numFixedSlots(); ++i) {
|
||||
HeapValue *slotA = &a->getFixedSlotRef(i);
|
||||
HeapValue *slotB = &b->getFixedSlotRef(i);
|
||||
HeapValue::writeBarrierPost(*slotA, slotA);
|
||||
HeapValue::writeBarrierPost(*slotB, slotB);
|
||||
HeapSlot::writeBarrierPost(comp, a, i);
|
||||
HeapSlot::writeBarrierPost(comp, b, i);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
|
@ -3815,56 +3814,28 @@ js_InitClass(JSContext *cx, HandleObject obj, JSObject *protoProto,
|
|||
ps, fs, static_ps, static_fs, ctorp, ctorKind);
|
||||
}
|
||||
|
||||
void
|
||||
JSObject::getSlotRange(size_t start, size_t length,
|
||||
HeapValue **fixedStart, HeapValue **fixedEnd,
|
||||
HeapValue **slotsStart, HeapValue **slotsEnd)
|
||||
{
|
||||
JS_ASSERT(!isDenseArray());
|
||||
JS_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
|
||||
|
||||
size_t fixed = numFixedSlots();
|
||||
if (start < fixed) {
|
||||
if (start + length < fixed) {
|
||||
*fixedStart = &fixedSlots()[start];
|
||||
*fixedEnd = &fixedSlots()[start + length];
|
||||
*slotsStart = *slotsEnd = NULL;
|
||||
} else {
|
||||
size_t localCopy = fixed - start;
|
||||
*fixedStart = &fixedSlots()[start];
|
||||
*fixedEnd = &fixedSlots()[start + localCopy];
|
||||
*slotsStart = &slots[0];
|
||||
*slotsEnd = &slots[length - localCopy];
|
||||
}
|
||||
} else {
|
||||
*fixedStart = *fixedEnd = NULL;
|
||||
*slotsStart = &slots[start - fixed];
|
||||
*slotsEnd = &slots[start - fixed + length];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSObject::initSlotRange(size_t start, const Value *vector, size_t length)
|
||||
{
|
||||
JSCompartment *comp = compartment();
|
||||
HeapValue *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
|
||||
for (HeapValue *vp = fixedStart; vp != fixedEnd; vp++)
|
||||
vp->init(comp, *vector++);
|
||||
for (HeapValue *vp = slotsStart; vp != slotsEnd; vp++)
|
||||
vp->init(comp, *vector++);
|
||||
for (HeapSlot *sp = fixedStart; sp != fixedEnd; sp++)
|
||||
sp->init(comp, this, start++, *vector++);
|
||||
for (HeapSlot *sp = slotsStart; sp != slotsEnd; sp++)
|
||||
sp->init(comp, this, start++, *vector++);
|
||||
}
|
||||
|
||||
void
|
||||
JSObject::copySlotRange(size_t start, const Value *vector, size_t length)
|
||||
{
|
||||
JSCompartment *comp = compartment();
|
||||
HeapValue *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
|
||||
for (HeapValue *vp = fixedStart; vp != fixedEnd; vp++)
|
||||
vp->set(comp, *vector++);
|
||||
for (HeapValue *vp = slotsStart; vp != slotsEnd; vp++)
|
||||
vp->set(comp, *vector++);
|
||||
for (HeapSlot *sp = fixedStart; sp != fixedEnd; sp++)
|
||||
sp->set(comp, this, start++, *vector++);
|
||||
for (HeapSlot *sp = slotsStart; sp != slotsEnd; sp++)
|
||||
sp->set(comp, this, start++, *vector++);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -3873,20 +3844,10 @@ JSObject::invalidateSlotRange(size_t start, size_t length)
|
|||
#ifdef DEBUG
|
||||
JS_ASSERT(!isDenseArray());
|
||||
|
||||
size_t fixed = numFixedSlots();
|
||||
|
||||
/* No bounds checks, allocated space has been updated but not the shape. */
|
||||
if (start < fixed) {
|
||||
if (start + length < fixed) {
|
||||
Debug_SetValueRangeToCrashOnTouch(fixedSlots() + start, length);
|
||||
} else {
|
||||
size_t localClear = fixed - start;
|
||||
Debug_SetValueRangeToCrashOnTouch(fixedSlots() + start, localClear);
|
||||
Debug_SetValueRangeToCrashOnTouch(slots, length - localClear);
|
||||
}
|
||||
} else {
|
||||
Debug_SetValueRangeToCrashOnTouch(slots + start - fixed, length);
|
||||
}
|
||||
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
|
||||
Debug_SetSlotRangeToCrashOnTouch(fixedStart, fixedEnd);
|
||||
Debug_SetSlotRangeToCrashOnTouch(slotsStart, slotsEnd);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
|
@ -4006,24 +3967,24 @@ JSObject::growSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount)
|
|||
}
|
||||
|
||||
if (!oldCount) {
|
||||
slots = (HeapValue *) cx->malloc_(newCount * sizeof(HeapValue));
|
||||
slots = (HeapSlot *) cx->malloc_(newCount * sizeof(HeapSlot));
|
||||
if (!slots)
|
||||
return false;
|
||||
Debug_SetValueRangeToCrashOnTouch(slots, newCount);
|
||||
Debug_SetSlotRangeToCrashOnTouch(slots, newCount);
|
||||
if (Probes::objectResizeActive())
|
||||
Probes::resizeObject(cx, this, oldSize, newSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
HeapValue *newslots = (HeapValue*) cx->realloc_(slots, oldCount * sizeof(HeapValue),
|
||||
newCount * sizeof(HeapValue));
|
||||
HeapSlot *newslots = (HeapSlot*) cx->realloc_(slots, oldCount * sizeof(HeapSlot),
|
||||
newCount * sizeof(HeapSlot));
|
||||
if (!newslots)
|
||||
return false; /* Leave slots at its old size. */
|
||||
|
||||
bool changed = slots != newslots;
|
||||
slots = newslots;
|
||||
|
||||
Debug_SetValueRangeToCrashOnTouch(slots + oldCount, newCount - oldCount);
|
||||
Debug_SetSlotRangeToCrashOnTouch(slots + oldCount, newCount - oldCount);
|
||||
|
||||
/* Changes in the slots of global objects can trigger recompilation. */
|
||||
if (changed && isGlobal())
|
||||
|
@ -4063,7 +4024,7 @@ JSObject::shrinkSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount)
|
|||
|
||||
JS_ASSERT(newCount >= SLOT_CAPACITY_MIN);
|
||||
|
||||
HeapValue *newslots = (HeapValue*) cx->realloc_(slots, newCount * sizeof(HeapValue));
|
||||
HeapSlot *newslots = (HeapSlot *) cx->realloc_(slots, newCount * sizeof(HeapSlot));
|
||||
if (!newslots)
|
||||
return; /* Leave slots at its old size. */
|
||||
|
||||
|
@ -4136,7 +4097,7 @@ JSObject::growElements(JSContext *cx, uintN newcap)
|
|||
newheader->capacity = actualCapacity;
|
||||
elements = newheader->elements();
|
||||
|
||||
Debug_SetValueRangeToCrashOnTouch(elements + initlen, actualCapacity - initlen);
|
||||
Debug_SetSlotRangeToCrashOnTouch(elements + initlen, actualCapacity - initlen);
|
||||
|
||||
if (Probes::objectResizeActive())
|
||||
Probes::resizeObject(cx, this, oldSize, computedSizeOfThisSlotsElements());
|
||||
|
@ -6538,8 +6499,6 @@ js_DumpStackFrame(JSContext *cx, StackFrame *start)
|
|||
fprintf(stderr, " flags:");
|
||||
if (fp->isConstructing())
|
||||
fprintf(stderr, " constructing");
|
||||
if (fp->hasOverriddenArgs())
|
||||
fprintf(stderr, " overridden_args");
|
||||
if (fp->isDebuggerFrame())
|
||||
fprintf(stderr, " debugger");
|
||||
if (fp->isEvalFrame())
|
||||
|
|
|
@ -434,7 +434,7 @@ struct JSObject : public js::ObjectImpl
|
|||
js::gc::AllocKind kind,
|
||||
js::HandleShape shape,
|
||||
js::HandleTypeObject type,
|
||||
js::HeapValue *slots);
|
||||
js::HeapSlot *slots);
|
||||
|
||||
/* Make a dense array object with the specified initial state. */
|
||||
static inline JSObject *createDenseArray(JSContext *cx,
|
||||
|
@ -546,9 +546,12 @@ struct JSObject : public js::ObjectImpl
|
|||
* Get internal pointers to the range of values starting at start and
|
||||
* running for length.
|
||||
*/
|
||||
void getSlotRange(size_t start, size_t length,
|
||||
js::HeapValue **fixedStart, js::HeapValue **fixedEnd,
|
||||
js::HeapValue **slotsStart, js::HeapValue **slotsEnd);
|
||||
inline void getSlotRangeUnchecked(size_t start, size_t length,
|
||||
js::HeapSlot **fixedStart, js::HeapSlot **fixedEnd,
|
||||
js::HeapSlot **slotsStart, js::HeapSlot **slotsEnd);
|
||||
inline void getSlotRange(size_t start, size_t length,
|
||||
js::HeapSlot **fixedStart, js::HeapSlot **fixedEnd,
|
||||
js::HeapSlot **slotsStart, js::HeapSlot **slotsEnd);
|
||||
public:
|
||||
|
||||
/* Accessors for properties. */
|
||||
|
@ -560,7 +563,7 @@ struct JSObject : public js::ObjectImpl
|
|||
inline size_t dynamicSlotIndex(size_t slot);
|
||||
|
||||
/* Get a raw pointer to the object's properties. */
|
||||
inline const js::HeapValue *getRawSlots();
|
||||
inline const js::HeapSlot *getRawSlots();
|
||||
|
||||
/*
|
||||
* Grow or shrink slots immediately before changing the slot span.
|
||||
|
@ -620,14 +623,16 @@ struct JSObject : public js::ObjectImpl
|
|||
bool slotInRange(uintN slot, SentinelAllowed sentinel = SENTINEL_NOT_ALLOWED) const;
|
||||
#endif
|
||||
|
||||
js::HeapValue *getSlotAddressUnchecked(uintN slot) {
|
||||
private:
|
||||
js::HeapSlot *getSlotAddressUnchecked(uintN slot) {
|
||||
size_t fixed = numFixedSlots();
|
||||
if (slot < fixed)
|
||||
return fixedSlots() + slot;
|
||||
return slots + (slot - fixed);
|
||||
}
|
||||
|
||||
js::HeapValue *getSlotAddress(uintN slot) {
|
||||
public:
|
||||
js::HeapSlot *getSlotAddress(uintN slot) {
|
||||
/*
|
||||
* This can be used to get the address of the end of the slots for the
|
||||
* object, which may be necessary when fetching zero-length arrays of
|
||||
|
@ -637,12 +642,12 @@ struct JSObject : public js::ObjectImpl
|
|||
return getSlotAddressUnchecked(slot);
|
||||
}
|
||||
|
||||
js::HeapValue &getSlotRef(uintN slot) {
|
||||
js::HeapSlot &getSlotRef(uintN slot) {
|
||||
JS_ASSERT(slotInRange(slot));
|
||||
return *getSlotAddress(slot);
|
||||
}
|
||||
|
||||
inline js::HeapValue &nativeGetSlotRef(uintN slot);
|
||||
inline js::HeapSlot &nativeGetSlotRef(uintN slot);
|
||||
|
||||
const js::Value &getSlot(uintN slot) const {
|
||||
JS_ASSERT(slotInRange(slot));
|
||||
|
@ -663,12 +668,13 @@ struct JSObject : public js::ObjectImpl
|
|||
inline void nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value);
|
||||
|
||||
inline const js::Value &getReservedSlot(uintN index) const;
|
||||
inline js::HeapValue &getReservedSlotRef(uintN index);
|
||||
inline js::HeapSlot &getReservedSlotRef(uintN index);
|
||||
inline void initReservedSlot(uintN index, const js::Value &v);
|
||||
inline void setReservedSlot(uintN index, const js::Value &v);
|
||||
|
||||
/* For slots which are known to always be fixed, due to the way they are allocated. */
|
||||
|
||||
js::HeapValue &getFixedSlotRef(uintN slot) {
|
||||
js::HeapSlot &getFixedSlotRef(uintN slot) {
|
||||
JS_ASSERT(slot < numFixedSlots());
|
||||
return fixedSlots()[slot];
|
||||
}
|
||||
|
@ -834,7 +840,7 @@ struct JSObject : public js::ObjectImpl
|
|||
inline void setDenseArrayLength(uint32_t length);
|
||||
inline void setDenseArrayInitializedLength(uint32_t length);
|
||||
inline void ensureDenseArrayInitializedLength(JSContext *cx, uintN index, uintN extra);
|
||||
inline js::HeapValueArray getDenseArrayElements();
|
||||
inline js::HeapSlotArray getDenseArrayElements();
|
||||
inline const js::Value &getDenseArrayElement(uintN idx);
|
||||
inline void setDenseArrayElement(uintN idx, const js::Value &val);
|
||||
inline void initDenseArrayElement(uintN idx, const js::Value &val);
|
||||
|
|
|
@ -101,7 +101,7 @@ JSObject::privateRef(uint32_t nfixed) const
|
|||
*/
|
||||
JS_ASSERT(nfixed == numFixedSlots());
|
||||
JS_ASSERT(hasPrivate());
|
||||
js::HeapValue *end = &fixedSlots()[nfixed];
|
||||
js::HeapSlot *end = &fixedSlots()[nfixed];
|
||||
return *reinterpret_cast<void**>(end);
|
||||
}
|
||||
|
||||
|
@ -406,7 +406,7 @@ JSObject::canRemoveLastProperty()
|
|||
&& previous->getObjectFlags() == lastProperty()->getObjectFlags();
|
||||
}
|
||||
|
||||
inline const js::HeapValue *
|
||||
inline const js::HeapSlot *
|
||||
JSObject::getRawSlots()
|
||||
{
|
||||
JS_ASSERT(isGlobal());
|
||||
|
@ -420,7 +420,7 @@ JSObject::getReservedSlot(uintN index) const
|
|||
return getSlot(index);
|
||||
}
|
||||
|
||||
inline js::HeapValue &
|
||||
inline js::HeapSlot &
|
||||
JSObject::getReservedSlotRef(uintN index)
|
||||
{
|
||||
JS_ASSERT(index < JSSLOT_FREE(getClass()));
|
||||
|
@ -434,6 +434,13 @@ JSObject::setReservedSlot(uintN index, const js::Value &v)
|
|||
setSlot(index, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initReservedSlot(uintN index, const js::Value &v)
|
||||
{
|
||||
JS_ASSERT(index < JSSLOT_FREE(getClass()));
|
||||
initSlot(index, v);
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::hasContiguousSlots(size_t start, size_t count) const
|
||||
{
|
||||
|
@ -449,7 +456,7 @@ inline void
|
|||
JSObject::prepareSlotRangeForOverwrite(size_t start, size_t end)
|
||||
{
|
||||
for (size_t i = start; i < end; i++)
|
||||
getSlotAddressUnchecked(i)->js::HeapValue::~HeapValue();
|
||||
getSlotAddressUnchecked(i)->js::HeapSlot::~HeapSlot();
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -458,7 +465,7 @@ JSObject::prepareElementRangeForOverwrite(size_t start, size_t end)
|
|||
JS_ASSERT(isDenseArray());
|
||||
JS_ASSERT(end <= getDenseArrayInitializedLength());
|
||||
for (size_t i = start; i < end; i++)
|
||||
elements[i].js::HeapValue::~HeapValue();
|
||||
elements[i].js::HeapSlot::~HeapSlot();
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
|
@ -529,11 +536,11 @@ JSObject::ensureElements(JSContext *cx, uint32_t capacity)
|
|||
return true;
|
||||
}
|
||||
|
||||
inline js::HeapValueArray
|
||||
inline js::HeapSlotArray
|
||||
JSObject::getDenseArrayElements()
|
||||
{
|
||||
JS_ASSERT(isDenseArray());
|
||||
return js::HeapValueArray(elements);
|
||||
return js::HeapSlotArray(elements);
|
||||
}
|
||||
|
||||
inline const js::Value &
|
||||
|
@ -547,14 +554,14 @@ inline void
|
|||
JSObject::setDenseArrayElement(uintN idx, const js::Value &val)
|
||||
{
|
||||
JS_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength());
|
||||
elements[idx] = val;
|
||||
elements[idx].set(this, idx, val);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initDenseArrayElement(uintN idx, const js::Value &val)
|
||||
{
|
||||
JS_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength());
|
||||
elements[idx].init(val);
|
||||
elements[idx].init(this, idx, val);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -577,7 +584,7 @@ JSObject::copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN cou
|
|||
JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
|
||||
JSCompartment *comp = compartment();
|
||||
for (unsigned i = 0; i < count; ++i)
|
||||
elements[dstStart + i].set(comp, src[i]);
|
||||
elements[dstStart + i].set(comp, this, dstStart + i, src[i]);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -586,7 +593,7 @@ JSObject::initDenseArrayElements(uintN dstStart, const js::Value *src, uintN cou
|
|||
JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
|
||||
JSCompartment *comp = compartment();
|
||||
for (unsigned i = 0; i < count; ++i)
|
||||
elements[dstStart + i].init(comp, src[i]);
|
||||
elements[dstStart + i].init(comp, this, dstStart + i, src[i]);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -607,20 +614,21 @@ JSObject::moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count)
|
|||
* write barrier is invoked here on B, despite the fact that it exists in
|
||||
* the array before and after the move.
|
||||
*/
|
||||
if (compartment()->needsBarrier()) {
|
||||
JSCompartment *comp = compartment();
|
||||
if (comp->needsBarrier()) {
|
||||
if (dstStart < srcStart) {
|
||||
js::HeapValue *dst = elements + dstStart;
|
||||
js::HeapValue *src = elements + srcStart;
|
||||
js::HeapSlot *dst = elements + dstStart;
|
||||
js::HeapSlot *src = elements + srcStart;
|
||||
for (unsigned i = 0; i < count; i++, dst++, src++)
|
||||
*dst = *src;
|
||||
dst->set(comp, this, dst - elements, *src);
|
||||
} else {
|
||||
js::HeapValue *dst = elements + dstStart + count - 1;
|
||||
js::HeapValue *src = elements + srcStart + count - 1;
|
||||
js::HeapSlot *dst = elements + dstStart + count - 1;
|
||||
js::HeapSlot *src = elements + srcStart + count - 1;
|
||||
for (unsigned i = 0; i < count; i++, dst--, src--)
|
||||
*dst = *src;
|
||||
dst->set(comp, this, dst - elements, *src);
|
||||
}
|
||||
} else {
|
||||
memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value));
|
||||
memmove(elements + dstStart, elements + srcStart, count * sizeof(js::HeapSlot));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -970,6 +978,42 @@ JSObject::isQName() const
|
|||
|| hasClass(&js::AnyNameClass);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::getSlotRangeUnchecked(size_t start, size_t length,
|
||||
js::HeapSlot **fixedStart, js::HeapSlot **fixedEnd,
|
||||
js::HeapSlot **slotsStart, js::HeapSlot **slotsEnd)
|
||||
{
|
||||
JS_ASSERT(!isDenseArray());
|
||||
|
||||
size_t fixed = numFixedSlots();
|
||||
if (start < fixed) {
|
||||
if (start + length < fixed) {
|
||||
*fixedStart = &fixedSlots()[start];
|
||||
*fixedEnd = &fixedSlots()[start + length];
|
||||
*slotsStart = *slotsEnd = NULL;
|
||||
} else {
|
||||
size_t localCopy = fixed - start;
|
||||
*fixedStart = &fixedSlots()[start];
|
||||
*fixedEnd = &fixedSlots()[start + localCopy];
|
||||
*slotsStart = &slots[0];
|
||||
*slotsEnd = &slots[length - localCopy];
|
||||
}
|
||||
} else {
|
||||
*fixedStart = *fixedEnd = NULL;
|
||||
*slotsStart = &slots[start - fixed];
|
||||
*slotsEnd = &slots[start - fixed + length];
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::getSlotRange(size_t start, size_t length,
|
||||
js::HeapSlot **fixedStart, js::HeapSlot **fixedEnd,
|
||||
js::HeapSlot **slotsStart, js::HeapSlot **slotsEnd)
|
||||
{
|
||||
JS_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
|
||||
getSlotRangeUnchecked(start, length, fixedStart, fixedEnd, slotsStart, slotsEnd);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initializeSlotRange(size_t start, size_t length)
|
||||
{
|
||||
|
@ -977,24 +1021,20 @@ JSObject::initializeSlotRange(size_t start, size_t length)
|
|||
* No bounds check, as this is used when the object's shape does not
|
||||
* reflect its allocated slots (updateSlotsForSpan).
|
||||
*/
|
||||
JS_ASSERT(!isDenseArray());
|
||||
size_t fixed = numFixedSlots();
|
||||
if (start < fixed) {
|
||||
if (start + length < fixed) {
|
||||
js::InitValueRange(fixedSlots() + start, length, false);
|
||||
} else {
|
||||
size_t localClear = fixed - start;
|
||||
js::InitValueRange(fixedSlots() + start, localClear, false);
|
||||
js::InitValueRange(slots, length - localClear, false);
|
||||
}
|
||||
} else {
|
||||
js::InitValueRange(slots + start - fixed, length, false);
|
||||
}
|
||||
js::HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
getSlotRangeUnchecked(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
|
||||
|
||||
JSCompartment *comp = compartment();
|
||||
size_t offset = start;
|
||||
for (js::HeapSlot *sp = fixedStart; sp != fixedEnd; sp++)
|
||||
sp->init(comp, this, offset++, js::UndefinedValue());
|
||||
for (js::HeapSlot *sp = slotsStart; sp != slotsEnd; sp++)
|
||||
sp->init(comp, this, offset++, js::UndefinedValue());
|
||||
}
|
||||
|
||||
/* static */ inline JSObject *
|
||||
JSObject::create(JSContext *cx, js::gc::AllocKind kind,
|
||||
js::HandleShape shape, js::HandleTypeObject type, js::HeapValue *slots)
|
||||
js::HandleShape shape, js::HandleTypeObject type, js::HeapSlot *slots)
|
||||
{
|
||||
/*
|
||||
* Callers must use dynamicSlotsCount to size the initial slot array of the
|
||||
|
@ -1102,7 +1142,7 @@ JSObject::slotSpan() const
|
|||
return lastProperty()->slotSpan();
|
||||
}
|
||||
|
||||
inline js::HeapValue &
|
||||
inline js::HeapSlot &
|
||||
JSObject::nativeGetSlotRef(uintN slot)
|
||||
{
|
||||
JS_ASSERT(isNative());
|
||||
|
@ -1344,7 +1384,7 @@ inline JSBool
|
|||
JSObject::getGenericAttributes(JSContext *cx, jsid id, uintN *attrsp)
|
||||
{
|
||||
js::GenericAttributesOp op = getOps()->getGenericAttributes;
|
||||
return (op ? op : js_GetAttributes)(cx, this, id, attrsp);
|
||||
return (op ? op : js_GetAttributes)(cx, this, id, attrsp);
|
||||
}
|
||||
|
||||
inline JSBool
|
||||
|
@ -1813,13 +1853,13 @@ NewObjectGCKind(JSContext *cx, js::Class *clasp)
|
|||
* may or may not need dynamic slots.
|
||||
*/
|
||||
inline bool
|
||||
PreallocateObjectDynamicSlots(JSContext *cx, Shape *shape, HeapValue **slots)
|
||||
PreallocateObjectDynamicSlots(JSContext *cx, Shape *shape, HeapSlot **slots)
|
||||
{
|
||||
if (size_t count = JSObject::dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan())) {
|
||||
*slots = (HeapValue *) cx->malloc_(count * sizeof(HeapValue));
|
||||
*slots = (HeapSlot *) cx->malloc_(count * sizeof(HeapSlot));
|
||||
if (!*slots)
|
||||
return false;
|
||||
Debug_SetValueRangeToCrashOnTouch(*slots, count);
|
||||
Debug_SetSlotRangeToCrashOnTouch(*slots, count);
|
||||
return true;
|
||||
}
|
||||
*slots = NULL;
|
||||
|
@ -1969,7 +2009,7 @@ inline void
|
|||
JSObject::setSlot(uintN slot, const js::Value &value)
|
||||
{
|
||||
JS_ASSERT(slotInRange(slot));
|
||||
getSlotRef(slot).set(compartment(), value);
|
||||
getSlotRef(slot).set(this, slot, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -1983,21 +2023,21 @@ JSObject::initSlot(uintN slot, const js::Value &value)
|
|||
inline void
|
||||
JSObject::initSlotUnchecked(uintN slot, const js::Value &value)
|
||||
{
|
||||
getSlotAddressUnchecked(slot)->init(value);
|
||||
getSlotAddressUnchecked(slot)->init(this, slot, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setFixedSlot(uintN slot, const js::Value &value)
|
||||
{
|
||||
JS_ASSERT(slot < numFixedSlots());
|
||||
fixedSlots()[slot] = value;
|
||||
fixedSlots()[slot].set(this, slot, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initFixedSlot(uintN slot, const js::Value &value)
|
||||
{
|
||||
JS_ASSERT(slot < numFixedSlots());
|
||||
fixedSlots()[slot].init(value);
|
||||
fixedSlots()[slot].init(this, slot, value);
|
||||
}
|
||||
|
||||
#endif /* jsobjinlines_h___ */
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
static inline HeapValue &
|
||||
static inline HeapSlot &
|
||||
GetCall(JSObject *proxy)
|
||||
{
|
||||
JS_ASSERT(IsFunctionProxy(proxy));
|
||||
|
@ -74,7 +74,7 @@ GetConstruct(JSObject *proxy)
|
|||
return proxy->getSlot(JSSLOT_PROXY_CONSTRUCT);
|
||||
}
|
||||
|
||||
static inline HeapValue &
|
||||
static inline HeapSlot &
|
||||
GetFunctionProxyConstruct(JSObject *proxy)
|
||||
{
|
||||
JS_ASSERT(IsFunctionProxy(proxy));
|
||||
|
@ -1248,12 +1248,12 @@ static void
|
|||
proxy_TraceObject(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
GetProxyHandler(obj)->trace(trc, obj);
|
||||
MarkCrossCompartmentValue(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "private");
|
||||
MarkCrossCompartmentValue(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 0), "extra0");
|
||||
MarkCrossCompartmentValue(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 1), "extra1");
|
||||
MarkCrossCompartmentSlot(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "private");
|
||||
MarkCrossCompartmentSlot(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 0), "extra0");
|
||||
MarkCrossCompartmentSlot(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 1), "extra1");
|
||||
if (IsFunctionProxy(obj)) {
|
||||
MarkCrossCompartmentValue(trc, &GetCall(obj), "call");
|
||||
MarkCrossCompartmentValue(trc, &GetFunctionProxyConstruct(obj), "construct");
|
||||
MarkCrossCompartmentSlot(trc, &GetCall(obj), "call");
|
||||
MarkCrossCompartmentSlot(trc, &GetFunctionProxyConstruct(obj), "construct");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1261,8 +1261,8 @@ static void
|
|||
proxy_TraceFunction(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
proxy_TraceObject(trc, obj);
|
||||
MarkCrossCompartmentValue(trc, &GetCall(obj), "call");
|
||||
MarkCrossCompartmentValue(trc, &GetFunctionProxyConstruct(obj), "construct");
|
||||
MarkCrossCompartmentSlot(trc, &GetCall(obj), "call");
|
||||
MarkCrossCompartmentSlot(trc, &GetFunctionProxyConstruct(obj), "construct");
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
|
|
@ -98,9 +98,9 @@ Bindings::lookup(JSContext *cx, JSAtom *name, uintN *indexp) const
|
|||
if (indexp)
|
||||
*indexp = shape->shortid();
|
||||
|
||||
if (shape->getter() == GetCallArg)
|
||||
if (shape->getter() == CallObject::getArgOp)
|
||||
return ARGUMENT;
|
||||
if (shape->getter() == GetCallUpvar)
|
||||
if (shape->getter() == CallObject::getUpvarOp)
|
||||
return UPVAR;
|
||||
|
||||
return shape->writable() ? VARIABLE : CONSTANT;
|
||||
|
@ -128,13 +128,13 @@ Bindings::add(JSContext *cx, JSAtom *name, BindingKind kind)
|
|||
JS_ASSERT(nvars == 0);
|
||||
JS_ASSERT(nupvars == 0);
|
||||
indexp = &nargs;
|
||||
getter = GetCallArg;
|
||||
setter = SetCallArg;
|
||||
getter = CallObject::getArgOp;
|
||||
setter = CallObject::setArgOp;
|
||||
slot += nargs;
|
||||
} else if (kind == UPVAR) {
|
||||
indexp = &nupvars;
|
||||
getter = GetCallUpvar;
|
||||
setter = SetCallUpvar;
|
||||
getter = CallObject::getUpvarOp;
|
||||
setter = CallObject::setUpvarOp;
|
||||
slot = lastBinding->maybeSlot();
|
||||
attrs |= JSPROP_SHARED;
|
||||
} else {
|
||||
|
@ -142,8 +142,8 @@ Bindings::add(JSContext *cx, JSAtom *name, BindingKind kind)
|
|||
JS_ASSERT(nupvars == 0);
|
||||
|
||||
indexp = &nvars;
|
||||
getter = GetCallVar;
|
||||
setter = SetCallVar;
|
||||
getter = CallObject::getVarOp;
|
||||
setter = CallObject::setVarOp;
|
||||
if (kind == CONSTANT)
|
||||
attrs |= JSPROP_READONLY;
|
||||
slot += nargs + nvars;
|
||||
|
@ -248,9 +248,9 @@ Bindings::getLocalNameArray(JSContext *cx, Vector<JSAtom *> *namesp)
|
|||
const Shape &shape = r.front();
|
||||
uintN index = uint16_t(shape.shortid());
|
||||
|
||||
if (shape.getter() == GetCallArg) {
|
||||
if (shape.getter() == CallObject::getArgOp) {
|
||||
JS_ASSERT(index < nargs);
|
||||
} else if (shape.getter() == GetCallUpvar) {
|
||||
} else if (shape.getter() == CallObject::getUpvarOp) {
|
||||
JS_ASSERT(index < nupvars);
|
||||
index += nargs + nvars;
|
||||
} else {
|
||||
|
@ -262,7 +262,7 @@ Bindings::getLocalNameArray(JSContext *cx, Vector<JSAtom *> *namesp)
|
|||
names[index] = JSID_TO_ATOM(shape.propid());
|
||||
} else {
|
||||
JS_ASSERT(JSID_IS_INT(shape.propid()));
|
||||
JS_ASSERT(shape.getter() == GetCallArg);
|
||||
JS_ASSERT(shape.getter() == CallObject::getArgOp);
|
||||
names[index] = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ Bindings::lastArgument() const
|
|||
|
||||
const js::Shape *shape = lastVariable();
|
||||
if (nvars > 0) {
|
||||
while (shape->previous() && shape->getter() != GetCallArg)
|
||||
while (shape->previous() && shape->getter() != CallObject::getArgOp)
|
||||
shape = shape->previous();
|
||||
}
|
||||
return shape;
|
||||
|
@ -295,7 +295,7 @@ Bindings::lastVariable() const
|
|||
|
||||
const js::Shape *shape = lastUpvar();
|
||||
if (nupvars > 0) {
|
||||
while (shape->getter() == GetCallUpvar)
|
||||
while (shape->getter() == CallObject::getUpvarOp)
|
||||
shape = shape->previous();
|
||||
}
|
||||
return shape;
|
||||
|
@ -1433,10 +1433,10 @@ JS_FRIEND_API(void)
|
|||
js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun)
|
||||
{
|
||||
JS_ASSERT(!script->callDestroyHook);
|
||||
if (JSNewScriptHook hook = cx->debugHooks->newScriptHook) {
|
||||
if (JSNewScriptHook hook = cx->runtime->debugHooks.newScriptHook) {
|
||||
AutoKeepAtoms keep(cx->runtime);
|
||||
hook(cx, script->filename, script->lineno, script, fun,
|
||||
cx->debugHooks->newScriptHookData);
|
||||
cx->runtime->debugHooks.newScriptHookData);
|
||||
}
|
||||
script->callDestroyHook = true;
|
||||
}
|
||||
|
@ -1447,8 +1447,8 @@ js_CallDestroyScriptHook(JSContext *cx, JSScript *script)
|
|||
if (!script->callDestroyHook)
|
||||
return;
|
||||
|
||||
if (JSDestroyScriptHook hook = cx->debugHooks->destroyScriptHook)
|
||||
hook(cx, script, cx->debugHooks->destroyScriptHookData);
|
||||
if (JSDestroyScriptHook hook = cx->runtime->debugHooks.destroyScriptHook)
|
||||
hook(cx, script, cx->runtime->debugHooks.destroyScriptHookData);
|
||||
script->callDestroyHook = false;
|
||||
JS_ClearScriptTraps(cx, script);
|
||||
}
|
||||
|
|
|
@ -1099,7 +1099,7 @@ class TypedArrayTemplate
|
|||
static void
|
||||
obj_trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
MarkValue(trc, &obj->getFixedSlotRef(FIELD_BUFFER), "typedarray.buffer");
|
||||
MarkSlot(trc, &obj->getFixedSlotRef(FIELD_BUFFER), "typedarray.buffer");
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
|
|
@ -286,6 +286,7 @@ typedef enum JSWhyMagic
|
|||
JS_ARG_POISON, /* used in debug builds to catch tracing errors */
|
||||
JS_SERIALIZE_NO_NODE, /* an empty subnode in the AST serializer */
|
||||
JS_LAZY_ARGUMENTS, /* lazy arguments value on the stack */
|
||||
JS_UNASSIGNED_ARGUMENTS, /* the initial value of callobj.arguments */
|
||||
JS_IS_CONSTRUCTING, /* magic value passed to natives to indicate construction */
|
||||
JS_GENERIC_MAGIC /* for local use */
|
||||
} JSWhyMagic;
|
||||
|
|
|
@ -102,6 +102,30 @@ WeakMapBase::resetWeakMapList(JSRuntime *rt)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WeakMapBase::saveWeakMapList(JSRuntime *rt, WeakMapVector &vector)
|
||||
{
|
||||
WeakMapBase *m = rt->gcWeakMapList;
|
||||
while (m) {
|
||||
if (!vector.append(m))
|
||||
return false;
|
||||
m = m->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WeakMapBase::restoreWeakMapList(JSRuntime *rt, WeakMapVector &vector)
|
||||
{
|
||||
JS_ASSERT(!rt->gcWeakMapList);
|
||||
for (WeakMapBase **p = vector.begin(); p != vector.end(); p++) {
|
||||
WeakMapBase *m = *p;
|
||||
JS_ASSERT(m->next == WeakMapNotInList);
|
||||
m->next = rt->gcWeakMapList;
|
||||
rt->gcWeakMapList = m;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
typedef WeakMap<HeapPtr<JSObject>, HeapValue> ObjectValueMap;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче