Merge mozilla-central into tracemonkey

This commit is contained in:
Blake Kaplan 2010-10-13 17:54:54 -07:00
Родитель 309019725a 828b4d7fa9
Коммит 312e4e1e90
383 изменённых файлов: 12852 добавлений и 15544 удалений

Просмотреть файл

@ -180,7 +180,6 @@ _BROWSER_FILES = \
browser_pinnedTabs.js \
browser_plainTextLinks.js \
browser_pluginnotification.js \
browser_popupUI.js \
browser_relatedTabs.js \
browser_sanitize-passwordDisabledHosts.js \
browser_sanitize-sitepermissions.js \
@ -188,7 +187,6 @@ _BROWSER_FILES = \
browser_sanitizeDialog.js \
browser_scope.js \
browser_selectTabAtIndex.js \
browser_tab_dragdrop.js \
browser_tab_dragdrop2.js \
browser_tab_dragdrop2_frame1.xul \
browser_tabfocus.js \
@ -220,6 +218,10 @@ _BROWSER_FILES = \
browser_aboutHome.js \
$(NULL)
# compartment-disabled
# browser_popupUI.js \
# browser_tab_dragdrop.js \
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
_BROWSER_FILES += \
browser_bug462289.js \

Просмотреть файл

@ -34,8 +34,7 @@ function test()
window_B.close();
var doc = window_C.gBrowser.getBrowserForTab(window_C.gBrowser.tabs[0])
.docShell.contentViewer.DOMDocument.wrappedJSObject;
var elems = document.documentElement.childNodes;
.docShell.contentViewer.DOMDocument;
var calls = doc.defaultView.test_panels();
window_C.close();
finish();

Просмотреть файл

@ -60,7 +60,6 @@ _BROWSER_FILES = \
browser_tabview_exit_button.js \
browser_tabview_group.js \
browser_tabview_launch.js \
browser_tabview_multiwindow_search.js \
browser_tabview_orphaned_tabs.js \
browser_tabview_privatebrowsing.js \
browser_tabview_search.js \
@ -72,5 +71,8 @@ _BROWSER_FILES = \
search2.html \
$(NULL)
# compartments: test disabled
# browser_tabview_multiwindow_search.js \
libs:: $(_BROWSER_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)

Просмотреть файл

@ -1690,7 +1690,7 @@ SessionStoreService.prototype = {
aTabData._formDataSaved = true;
if (aBrowser.currentURI.spec == "about:config")
aTabData.entries[tabIndex].formdata = {
"#textbox": aBrowser.contentDocument.getElementById("textbox").wrappedJSObject.value
"#textbox": aBrowser.contentDocument.getElementById("textbox").value
};
},
@ -2844,11 +2844,6 @@ SessionStoreService.prototype = {
// away before the loading completed (except for in-page navigation)
if (hasExpectedURL(aEvent.originalTarget, aBrowser.__SS_restore_data.url)) {
var content = aEvent.originalTarget.defaultView;
if (aBrowser.currentURI.spec == "about:config") {
// unwrap the document for about:config because otherwise the properties
// of the XBL bindings - as the textbox - aren't accessible (see bug 350718)
content = content.wrappedJSObject;
}
restoreTextDataAndScrolling(content, aBrowser.__SS_restore_data, "");
aBrowser.markupDocumentViewer.authorStyleDisabled = selectedPageStyle == "_nostyle";

Просмотреть файл

@ -59,7 +59,7 @@ function test() {
// add text data
let textbox = this.contentDocument.getElementById("textbox");
textbox.wrappedJSObject.value = value3;
textbox.value = value3;
// duplicate the tab
let duplicateTab = ss.duplicateTab(window, tab2);
@ -71,7 +71,7 @@ function test() {
ok(ss.getTabValue(duplicateTab, key2) == value2 && this.currentURI.spec == testURL,
"correctly duplicated the tab's state");
let textbox = this.contentDocument.getElementById("textbox");
is(textbox.wrappedJSObject.value, value3, "also duplicated text data");
is(textbox.value, value3, "also duplicated text data");
// clean up
tabbrowser.removeTab(duplicateTab);

Просмотреть файл

@ -80,7 +80,7 @@ function test() {
// mark the window with some unique data to be restored later on
ss.setWindowValue(newWin, uniqueKey, uniqueValue);
let textbox = newWin.content.document.getElementById("textbox");
textbox.wrappedJSObject.value = uniqueText;
textbox.value = uniqueText;
newWin.close();
@ -108,7 +108,7 @@ function test() {
"The window correctly restored the URL");
let textbox = newWin2.content.document.getElementById("textbox");
is(textbox.wrappedJSObject.value, uniqueText,
is(textbox.value, uniqueText,
"The window correctly restored the form");
is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
"The window correctly restored the data associated with it");

Просмотреть файл

@ -2465,10 +2465,19 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
jsClass = aObj->getClass();
} while (1);
NS_ASSERTION(!aAllowShortCircuit ||
result == doGetObjectPrincipal(origObj, PR_FALSE),
"Principal mismatch. Not good");
#ifdef DEBUG
if (aAllowShortCircuit) {
nsIPrincipal *principal = doGetObjectPrincipal(origObj, PR_FALSE);
// Location is always wrapped (even for same-compartment), so we can
// loosen the check to same-origin instead of same-principal.
NS_ASSERTION(strcmp(jsClass->name, "Location") == 0 ?
NS_SUCCEEDED(CheckSameOriginPrincipal(result, principal)) :
result == principal,
"Principal mismatch. Not good");
}
#endif
return result;
}

Просмотреть файл

@ -52,6 +52,7 @@
#include "nsString.h"
#include "nsNetCID.h"
#include "nsIClassInfoImpl.h"
#include "jsobj.h"
///////////////////////
// nsSecurityNameSet //
@ -294,6 +295,7 @@ nsSecurityNameSet::InitializeNameSet(nsIScriptContext* aScriptContext)
{
JSContext *cx = (JSContext *) aScriptContext->GetNativeContext();
JSObject *global = JS_GetGlobalObject(cx);
OBJ_TO_INNER_OBJECT(cx, global);
/*
* Find Object.prototype's class by walking up the global object's

Просмотреть файл

@ -189,7 +189,7 @@ nsSystemPrincipal::GetURI(nsIURI** aURI)
NS_IMETHODIMP
nsSystemPrincipal::GetOrigin(char** aOrigin)
{
*aOrigin = ToNewCString(NS_LITERAL_CSTRING("[System]"));
*aOrigin = ToNewCString(NS_LITERAL_CSTRING("[System Principal]"));
return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}

Просмотреть файл

@ -414,6 +414,11 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
nsAutoGCRoot resultGCRoot3(&thisValue, &rv);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoEnterCompartment ac;
if (!ac.enter(ctx, object))
return PR_FALSE;
jsval funval = JSVAL_VOID;
if (JS_ObjectIsFunction(ctx, object)) {
// If the listener is a JS function:
@ -449,15 +454,24 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
js::AutoValueRooter argv(ctx);
argv.set(OBJECT_TO_JSVAL(param));
JSObject* thisObject = JSVAL_TO_OBJECT(thisValue);
JS_CallFunctionValue(ctx, thisObject,
funval, 1, argv.jsval_addr(), &rval);
if (aJSONRetVal) {
nsString json;
if (JS_TryJSON(ctx, &rval) &&
JS_Stringify(ctx, &rval, nsnull, JSVAL_NULL,
JSONCreator, &json)) {
aJSONRetVal->AppendElement(json);
{
JSAutoEnterCompartment tac;
JSObject* thisObject = JSVAL_TO_OBJECT(thisValue);
if (!tac.enter(ctx, thisObject) ||
!JS_WrapValue(ctx, argv.jsval_addr()))
return NS_ERROR_UNEXPECTED;
JS_CallFunctionValue(ctx, thisObject,
funval, 1, argv.jsval_addr(), &rval);
if (aJSONRetVal) {
nsString json;
if (JS_TryJSON(ctx, &rval) &&
JS_Stringify(ctx, &rval, nsnull, JSVAL_NULL,
JSONCreator, &json)) {
aJSONRetVal->AppendElement(json);
}
}
}
}

Просмотреть файл

@ -62,6 +62,8 @@
#include "nsHTMLMediaElement.h"
#endif // MOZ_MEDIA
#include "nsImageLoadingContent.h"
#include "jsobj.h"
#include "jsgc.h"
using namespace mozilla::dom;
@ -515,6 +517,11 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
}
}
else if (nodeInfoManager) {
// FIXME Bug 601803 Need to support adopting a node cross-compartment
if (aCx && aOldScope->compartment() != aNewScope->compartment()) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
nsIDocument* oldDoc = aNode->GetOwnerDoc();
PRBool wasRegistered = PR_FALSE;
if (oldDoc && aNode->IsElement()) {

Просмотреть файл

@ -427,6 +427,9 @@ _TEST_FILES2 = \
test_bug600466.html \
test_bug600468.html \
test_bug600471.html \
test_bug601803.html \
file_bug601803a.html \
file_bug601803b.html \
$(NULL)
# This test fails on the Mac for some reason

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 601803</title>
<script type="application/javascript">
function runTest() {
document.domain = "example.org";
var thrown = false;
try {
document.getElementById("frame").contentDocument.adoptNode(document.createTextNode("foo"));
}
catch (e) {
thrown = true;
}
parent.postMessage(thrown, "*");
}
</script>
</head>
<body>
<iframe id="frame" src="http://test1.example.org/tests/content/base/test/file_bug601803b.html" onload="runTest();"></iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 601803</title>
</head>
<body>
<script type="application/javascript">
document.domain = "example.org";
</script>
</body>
</html>

Просмотреть файл

@ -1,32 +1,32 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=484459
https://bugzilla.mozilla.org/show_bug.cgi?id=601803
-->
<head>
<title>Test for Bug 484459</title>
<title>Test for Bug 601803</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=484459">Mozilla Bug 484459</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=601803">Mozilla Bug 601803</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id="frame"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 484459 **/
var x = 3;
var w = new XPCSafeJSObjectWrapper(window);
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var sandbox = new Components.utils.Sandbox(w);
sandbox.__proto__ = w;
is(Components.utils.evalInSandbox("x * 4", sandbox), 12,
"Unexpected return from the sandbox");
/** Test for Bug 601803 **/
SimpleTest.waitForExplicitFinish();
window.onmessage = function (event) {
todo(event.data == "false", "Shouldn't throw when adopting a node cross-compartment");
SimpleTest.finish();
}
document.getElementById("frame").src = "http://example.org/tests/content/base/test/file_bug601803a.html";

Просмотреть файл

@ -74,6 +74,8 @@ public:
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
// nsIDOMHTMLOptionElement
using nsGenericElement::SetText;
using nsGenericElement::GetText;
NS_DECL_NSIDOMHTMLOPTIONELEMENT
// nsIJSNativeInitializer

Просмотреть файл

@ -3231,8 +3231,9 @@ nsHTMLDocument::EditingStateChanged()
mParentDocument->FlushPendingNotifications(Flush_Style);
}
// get editing session
nsPIDOMWindow *window = GetWindow();
// get editing session, make sure this is a strong reference so the
// window can't get deleted during the rest of this call.
nsCOMPtr<nsPIDOMWindow> window = GetWindow();
if (!window)
return NS_ERROR_FAILURE;

Просмотреть файл

@ -1114,6 +1114,11 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen
JSObject* base = scriptObject;
JSObject* proto;
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, scriptObject)) {
return;
}
for ( ; true; base = proto) { // Will break out on null proto
proto = ::JS_GetPrototype(cx, base);
if (!proto) {
@ -1246,6 +1251,11 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
nsCAutoString className(aClassName);
JSObject* parent_proto = nsnull; // If we have an "obj" we can set this
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, global))
return NS_ERROR_FAILURE;
if (obj) {
// Retrieve the current prototype of obj.
parent_proto = ::JS_GetPrototype(cx, obj);

Просмотреть файл

@ -332,7 +332,7 @@ nsXBLDocGlobalObject::EnsureScriptEnvironment(PRUint32 aLangID)
principal->GetOrigin(getter_Copies(origin));
rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, origin, principal,
&mJSObject, &compartment);
false, &mJSObject, &compartment);
NS_ENSURE_SUCCESS(rv, nsnull);
::JS_SetGlobalObject(cx, mJSObject);

Просмотреть файл

@ -149,6 +149,12 @@ nsXBLProtoImplMethod::InstallMember(nsIScriptContext* aContext,
if (mJSMethodObject && targetClassObject) {
nsDependentString name(mName);
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, globalObject)) {
return NS_ERROR_UNEXPECTED;
}
JSObject * method = ::JS_CloneFunctionObject(cx, mJSMethodObject, globalObject);
if (!method) {
return NS_ERROR_OUT_OF_MEMORY;
@ -306,6 +312,10 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement)
JSObject* thisObject = JSVAL_TO_OBJECT(v);
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, thisObject))
return NS_ERROR_UNEXPECTED;
// Clone the function object, using thisObject as the parent so "this" is in
// the scope chain of the resulting function (for backwards compat to the

Просмотреть файл

@ -176,6 +176,11 @@ nsXBLProtoImplProperty::InstallMember(nsIScriptContext* aContext,
if ((mJSGetterObject || mJSSetterObject) && targetClassObject) {
JSObject * getter = nsnull;
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, globalObject))
return NS_ERROR_UNEXPECTED;
if (mJSGetterObject)
if (!(getter = ::JS_CloneFunctionObject(cx, mJSGetterObject, globalObject)))
return NS_ERROR_OUT_OF_MEMORY;

Просмотреть файл

@ -738,7 +738,7 @@ nsXULPDGlobalObject::EnsureScriptEnvironment(PRUint32 lang_id)
principal->GetOrigin(getter_Copies(origin));
rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, origin, principal,
&newGlob, &compartment);
false, &newGlob, &compartment);
NS_ENSURE_SUCCESS(rv, nsnull);
::JS_SetGlobalObject(cx, newGlob);

Просмотреть файл

@ -852,6 +852,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocShell)
NS_INTERFACE_MAP_ENTRY(nsIWebShellServices)
NS_INTERFACE_MAP_ENTRY(nsILinkHandler)
NS_INTERFACE_MAP_ENTRY(nsIClipboardCommands)
NS_INTERFACE_MAP_ENTRY(nsIDocShell_MOZILLA_2_0_BRANCH)
NS_INTERFACE_MAP_END_INHERITING(nsDocLoader)
///*****************************************************************************
@ -6463,6 +6464,12 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
return rv;
}
NS_IMETHODIMP
nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal *aPrincipal)
{
return CreateAboutBlankContentViewer(aPrincipal, nsnull);
}
PRBool
nsDocShell::CanSavePresentation(PRUint32 aLoadType,
nsIRequest *aNewRequest,

Просмотреть файл

@ -186,7 +186,8 @@ class nsDocShell : public nsDocLoader,
public nsILoadContext,
public nsIWebShellServices,
public nsILinkHandler,
public nsIClipboardCommands
public nsIClipboardCommands,
public nsIDocShell_MOZILLA_2_0_BRANCH
{
friend class nsDSURIContentListener;
@ -201,6 +202,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOCSHELL
NS_DECL_NSIDOCSHELL_MOZILLA_2_0_BRANCH
NS_DECL_NSIDOCSHELLTREEITEM
NS_DECL_NSIDOCSHELLTREENODE
NS_DECL_NSIDOCSHELLHISTORY

Просмотреть файл

@ -535,3 +535,12 @@ interface nsIDocShell : nsISupports
*/
readonly attribute unsigned long long historyID;
};
[uuid(5f7a2184-31b6-4d67-9c75-0c17477766e2)]
interface nsIDocShell_MOZILLA_2_0_BRANCH : nsISupports {
/**
* Create a new about:blank document and content viewer.
* @param aPrincipal the principal to use for the new document.
*/
void createAboutBlankContentViewer(in nsIPrincipal aPrincipal);
};

Просмотреть файл

@ -39,11 +39,11 @@ function doTest() {
offScreenBrowser.contentWindow.focus();
ok(offScreenBrowser.contentDocument.hasFocus(),"offscreen browser is not visible");
offScreenSubBrowser.wrappedJSObject.contentWindow.focus();
todo(offScreenSubBrowser.wrappedJSObject.contentDocument.hasFocus(),"visible browser in offscreen browser is not visible");
offScreenSubBrowser.contentWindow.focus();
todo(offScreenSubBrowser.contentDocument.hasFocus(),"visible browser in offscreen browser is not visible");
offScreenBurriedBrowser.wrappedJSObject.contentWindow.focus();
ok(!offScreenBurriedBrowser.wrappedJSObject.contentDocument.hasFocus(),"hidden browser in offscreen browser is visible");
offScreenBurriedBrowser.contentWindow.focus();
ok(!offScreenBurriedBrowser.contentDocument.hasFocus(),"hidden browser in offscreen browser is visible");
SimpleTest.finish();
}

Просмотреть файл

@ -125,6 +125,10 @@ endif
include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += \
-I$(srcdir)/../../js/src/xpconnect/wrappers \
$(NULL)
ifdef MOZ_X11
CXXFLAGS += $(TK_CFLAGS)
LDFLAGS += $(TK_LIBS)

Просмотреть файл

@ -82,6 +82,10 @@ DOM_MSG_DEF(NS_ERROR_DOM_SVG_MATRIX_NOT_INVERTABLE, "The matrix could not be com
DOM_MSG_DEF(NS_ERROR_DOM_INVALID_EXPRESSION_ERR, "The expression is not a legal expression.")
DOM_MSG_DEF(NS_ERROR_DOM_TYPE_ERR, "The expression cannot be converted to return the specified type.")
/* HTML5 error codes http://dev.w3.org/html5/spec/Overview.html */
DOM_MSG_DEF(NS_ERROR_DOM_DATA_CLONE_ERR, "The object could not be cloned.")
/* DOM error codes defined by us */
/* XXX string should be specified by norris */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -177,24 +177,6 @@ public:
static nsresult ThrowJSException(JSContext *cx, nsresult aResult);
static JSPropertyOp GetXPCNativeWrapperGetPropertyOp() {
return sXPCNativeWrapperGetPropertyOp;
}
static void SetXPCNativeWrapperGetPropertyOp(JSPropertyOp getPropertyOp) {
NS_ASSERTION(!sXPCNativeWrapperGetPropertyOp,
"Double set of sXPCNativeWrapperGetPropertyOp");
sXPCNativeWrapperGetPropertyOp = getPropertyOp;
}
static JSPropertyOp GetXrayWrapperPropertyHolderGetPropertyOp() {
return sXrayWrapperPropertyHolderGetPropertyOp;
}
static void SetXrayWrapperPropertyHolderGetPropertyOp(JSPropertyOp getPropertyOp) {
sXrayWrapperPropertyHolderGetPropertyOp = getPropertyOp;
}
static PRBool ObjectIsNativeWrapper(JSContext* cx, JSObject* obj);
static nsISupports *GetNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj);
@ -345,7 +327,6 @@ protected:
static jsid sEnumerate_id;
static jsid sNavigator_id;
static jsid sDocument_id;
static jsid sWindow_id;
static jsid sFrames_id;
static jsid sSelf_id;
static jsid sOpener_id;
@ -383,6 +364,7 @@ protected:
static jsid sOnmessage_id;
static jsid sOnbeforescriptexecute_id;
static jsid sOnafterscriptexecute_id;
static jsid sWrappedJSObject_id;
static JSPropertyOp sXPCNativeWrapperGetPropertyOp;
static JSPropertyOp sXrayWrapperPropertyHolderGetPropertyOp;
@ -501,14 +483,14 @@ public:
// Window scriptable helper
class nsCommonWindowSH : public nsEventReceiverSH
class nsWindowSH : public nsEventReceiverSH
{
protected:
nsCommonWindowSH(nsDOMClassInfoData *aData) : nsEventReceiverSH(aData)
nsWindowSH(nsDOMClassInfoData *aData) : nsEventReceiverSH(aData)
{
}
virtual ~nsCommonWindowSH()
virtual ~nsWindowSH()
{
}
@ -517,6 +499,8 @@ protected:
PRBool *did_resolve);
public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj);
#ifdef DEBUG
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
@ -552,6 +536,8 @@ public:
JSObject *obj);
NS_IMETHOD Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
JSObject * obj, const jsval &val, PRBool *bp);
NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
JSObject * obj, JSObject * *_retval);
static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
jsid id, uintN flags,
@ -563,66 +549,12 @@ public:
static void InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
nsIHTMLDocument *doc);
};
class nsOuterWindowSH : public nsCommonWindowSH
{
protected:
nsOuterWindowSH(nsDOMClassInfoData* aData) : nsCommonWindowSH(aData)
{
}
virtual ~nsOuterWindowSH()
{
}
static PRBool sResolving;
public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj);
NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, PRUint32 flags,
JSObject **objp, PRBool *_retval);
NS_IMETHOD NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 enum_op, jsval *statep,
jsid *idp, PRBool *_retval);
NS_IMETHOD InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
JSObject * obj, JSObject * *_retval);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{
return new nsOuterWindowSH(aData);
return new nsWindowSH(aData);
}
};
class nsInnerWindowSH : public nsCommonWindowSH
{
protected:
nsInnerWindowSH(nsDOMClassInfoData* aData) : nsCommonWindowSH(aData)
{
}
virtual ~nsInnerWindowSH()
{
}
public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj);
// We WANT_ADDPROPERTY, but are content to inherit it from nsEventReceiverSH.
NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
JSObject * obj, JSObject * *_retval);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{
return new nsInnerWindowSH(aData);
}
};
// Location scriptable helper
class nsLocationSH : public nsDOMGenericSH

Просмотреть файл

@ -37,7 +37,6 @@
* ***** END LICENSE BLOCK ***** */
DOMCI_CLASS(Window)
DOMCI_CLASS(InnerWindow)
DOMCI_CLASS(Location)
DOMCI_CLASS(Navigator)
DOMCI_CLASS(Plugin)
@ -189,7 +188,6 @@ DOMCI_CLASS(CSSRect)
// DOM Chrome Window class, almost identical to Window
DOMCI_CLASS(ChromeWindow)
DOMCI_CLASS(InnerChromeWindow)
// RGBColor object used by getComputedStyle
DOMCI_CLASS(CSSRGBColor)
@ -410,7 +408,6 @@ DOMCI_CLASS(FileReader)
// DOM modal content window class, almost identical to Window
DOMCI_CLASS(ModalContentWindow)
DOMCI_CLASS(InnerModalContentWindow)
// Data Events
DOMCI_CLASS(DataContainerEvent)

Просмотреть файл

@ -87,6 +87,10 @@
#define NS_ERROR_DOM_INVALID_EXPRESSION_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_XPATH, 51)
#define NS_ERROR_DOM_TYPE_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_XPATH, 52)
/* HTML5 error codes http://dev.w3.org/html5/spec/Overview.html */
#define NS_ERROR_DOM_DATA_CLONE_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,18)
/* DOM error codes defined by us */
#define NS_ERROR_DOM_SECURITY_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,1000)

Просмотреть файл

@ -979,64 +979,6 @@ nsDOMWindowUtils::GetScreenPixelsPerCSSPixel(float* aScreenPixels)
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetCOWForObject()
{
if (!IsUniversalXPConnectCapable()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsIXPConnect> xpc = nsContentUtils::XPConnect();
// get the xpconnect native call context
nsAXPCNativeCallContext *cc = nsnull;
xpc->GetCurrentNativeCallContext(&cc);
if(!cc)
return NS_ERROR_FAILURE;
// Get JSContext of current call
JSContext* cx;
nsresult rv = cc->GetJSContext(&cx);
if(NS_FAILED(rv) || !cx)
return NS_ERROR_FAILURE;
// get place for return value
jsval *rval = nsnull;
rv = cc->GetRetValPtr(&rval);
if(NS_FAILED(rv) || !rval)
return NS_ERROR_FAILURE;
// get argc and argv and verify arg count
PRUint32 argc;
rv = cc->GetArgc(&argc);
if(NS_FAILED(rv))
return NS_ERROR_FAILURE;
if(argc < 2)
return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
jsval* argv;
rv = cc->GetArgvPtr(&argv);
if(NS_FAILED(rv) || !argv)
return NS_ERROR_FAILURE;
// first and second params must be JSObjects
if(JSVAL_IS_PRIMITIVE(argv[0]) ||
JSVAL_IS_PRIMITIVE(argv[1]))
return NS_ERROR_XPC_BAD_CONVERT_JS;
JSObject *scope = JSVAL_TO_OBJECT(argv[0]);
JSObject *object = JSVAL_TO_OBJECT(argv[1]);
rv = xpc->GetCOWForObject(cx, JS_GetGlobalForObject(cx, scope),
object, rval);
if (NS_FAILED(rv))
return rv;
cc->SetReturnValueWasSet(PR_TRUE);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::DispatchDOMEventViaPresShell(nsIDOMNode* aTarget,
nsIDOMEvent* aEvent,

Просмотреть файл

@ -328,7 +328,8 @@ nsFocusManager::SetActiveWindow(nsIDOMWindow* aWindow)
{
// only top-level windows can be made active
nsCOMPtr<nsPIDOMWindow> piWindow = do_QueryInterface(aWindow);
NS_ASSERTION(!piWindow || piWindow->IsOuterWindow(), "outer window expected");
if (piWindow)
piWindow = piWindow->GetOuterWindow();
NS_ENSURE_TRUE(piWindow && (piWindow == piWindow->GetPrivateRoot()),
NS_ERROR_INVALID_ARG);

Просмотреть файл

@ -656,6 +656,35 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
nsPIDOMWindow::~nsPIDOMWindow() {}
//*****************************************************************************
// nsOuterWindowProxy: Outer Window Proxy
//*****************************************************************************
JSString *
nsOuterWindowProxy::obj_toString(JSContext *cx, JSObject *proxy)
{
JS_ASSERT(proxy->isProxy());
return JS_NewStringCopyZ(cx, "[object Window]");
}
nsOuterWindowProxy
nsOuterWindowProxy::singleton;
JSObject *
NS_NewOuterWindowProxy(JSContext *cx, JSObject *parent)
{
JSAutoEnterCompartment ac;
if (!ac.enter(cx, parent)) {
return nsnull;
}
JSObject *obj = JSWrapper::New(cx, parent, parent->getProto(), parent,
&nsOuterWindowProxy::singleton);
NS_ASSERTION(obj->getClass()->ext.innerObject, "bad class");
return obj;
}
//*****************************************************************************
//*** nsGlobalWindow: Object Management
//*****************************************************************************
@ -740,6 +769,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
Freeze();
mObserver = nsnull;
SetIsProxy();
}
// We could have failed the first time through trying
@ -803,7 +833,7 @@ nsGlobalWindow::~nsGlobalWindow()
printf("--DOMWINDOW == %d (%p) [serial = %d] [outer = %p] [url = %s]\n",
gRefCnt, static_cast<void*>(static_cast<nsIScriptGlobalObject*>(this)),
mSerial, static_cast<void*>(mOuterWindow), url.get());
mSerial, static_cast<void*>(mOuterWindow.get()), url.get());
#endif
#ifdef PR_LOGGING
@ -834,10 +864,6 @@ nsGlobalWindow::~nsGlobalWindow()
nsGlobalWindow *w;
while ((w = (nsGlobalWindow *)PR_LIST_HEAD(this)) != this) {
NS_ASSERTION(w->mOuterWindow == this, "Uh, bad outer window pointer?");
w->mOuterWindow = nsnull;
PR_REMOVE_AND_INIT_LINK(w);
}
} else {
@ -1144,22 +1170,16 @@ nsGlobalWindow::FreeInnerObjects(PRBool aClearScope)
// nsGlobalWindow::nsISupports
//*****************************************************************************
#define WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(_class) \
if (aIID.Equals(NS_GET_IID(nsIClassInfo)) || \
aIID.Equals(NS_GET_IID(nsXPCClassInfo))) { \
foundInterface = NS_GetDOMClassInfoInstance(IsInnerWindow() \
? eDOMClassInfo_Inner##_class##_id \
: eDOMClassInfo_##_class##_id);\
if (!foundInterface) { \
*aInstancePtr = nsnull; \
return NS_ERROR_OUT_OF_MEMORY; \
} \
#define OUTER_WINDOW_ONLY \
if (IsOuterWindow()) {
#define END_OUTER_WINDOW_ONLY \
foundInterface = 0; \
} else
NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindow)
DOMCI_DATA(Window, nsGlobalWindow)
DOMCI_DATA(InnerWindow, nsGlobalWindow)
// QueryInterface implementation for nsGlobalWindow
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
@ -1181,7 +1201,10 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
NS_INTERFACE_MAP_ENTRY(nsIDOMStorageWindow)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window)
OUTER_WINDOW_ONLY
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
END_OUTER_WINDOW_ONLY
NS_INTERFACE_MAP_END
@ -1203,6 +1226,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgumentsLast)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInnerWindowHolder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOuterWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListenerManager)
@ -1239,6 +1263,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArgumentsLast)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInnerWindowHolder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOuterWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOpenerScriptPrincipal)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager)
@ -1447,7 +1472,7 @@ nsGlobalWindow::SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal)
// Do NOT set mOpenerScriptPrincipal in this case, just to be safe.
return;
}
#ifdef DEBUG
// We better have an about:blank document loaded at this point. Otherwise,
// something is really weird.
@ -1457,13 +1482,11 @@ nsGlobalWindow::SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal)
IsAboutBlank(mDoc->GetDocumentURI()),
"Unexpected original document");
#endif
// Set the opener principal on our document; given the above check, this
// is safe.
mDoc->SetPrincipal(aPrincipal);
nsCOMPtr<nsIDocShell_MOZILLA_2_0_BRANCH> ds(do_QueryInterface(GetDocShell()));
ds->CreateAboutBlankContentViewer(aPrincipal);
mDoc->SetIsInitialDocument(PR_TRUE);
}
mOpenerScriptPrincipal = aPrincipal;
}
nsIPrincipal*
@ -1632,8 +1655,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
Thaw();
}
// XXX Brain transplant outer window JSObject and create new one!
NS_ASSERTION(!GetCurrentInnerWindow() ||
GetCurrentInnerWindow()->GetExtantDocument() == mDocument,
"Uh, mDocument doesn't match the current inner window "
@ -1771,7 +1792,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
newInnerWindow = currentInner;
if (aDocument != oldDoc) {
nsCommonWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
}
} else {
if (aState) {
@ -1898,39 +1919,65 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
if (!mJSObject) {
mContext->CreateOuterObject(this, newInnerWindow);
mContext->DidInitializeContext();
mJSObject = (JSObject *)mContext->GetNativeGlobal();
} else {
// XXX New global object and brain transplant!
rv = xpc->GetWrappedNativeOfJSObject(cx, mJSObject,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
// Restore our object's prototype to its original value so we're sure to
// update it under ReparentWrappedNativeIfFound.
JSObject *proto;
wrapper->GetJSObjectPrototype(&proto);
if (!JS_SetPrototype(cx, mJSObject, proto)) {
NS_ERROR("Can't set prototype");
return NS_ERROR_UNEXPECTED;
mJSObject = (JSObject *)mContext->GetNativeGlobal();
SetWrapper(mJSObject);
} else {
JSObject *outerObject =
NS_NewOuterWindowProxy(cx, newInnerWindow->mJSObject);
if (!outerObject) {
NS_ERROR("out of memory");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
xpc->ReparentWrappedNativeIfFound(cx, currentInner->mJSObject,
newInnerWindow->mJSObject,
ToSupports(this),
getter_AddRefs(holder));
outerObject = JS_TransplantWrapper(cx, mJSObject, outerObject);
if (!outerObject) {
NS_ERROR("unable to transplant wrappers, probably OOM");
return NS_ERROR_FAILURE;
}
if (aState) {
if (nsIXPConnectJSObjectHolder *holder = wsh->GetOuterRealProto()) {
holder->GetJSObject(&proto);
} else {
proto = nsnull;
}
mJSObject = outerObject;
SetWrapper(mJSObject);
if (!JS_SetPrototype(cx, mJSObject, proto)) {
NS_ERROR("can't set prototype");
{
JSAutoEnterCompartment ac;
if (!ac.enter(cx, mJSObject)) {
NS_ERROR("unable to enter a compartment");
return NS_ERROR_FAILURE;
}
JS_SetParent(cx, mJSObject, newInnerWindow->mJSObject);
}
mContext->SetOuterObject(mJSObject);
}
JSAutoEnterCompartment ac;
if (!ac.enter(cx, mJSObject)) {
NS_ERROR("unable to enter a compartment");
return NS_ERROR_FAILURE;
}
// XXX Not sure if this is needed.
if (aState) {
JSObject *proto;
if (nsIXPConnectJSObjectHolder *holder = wsh->GetOuterRealProto()) {
holder->GetJSObject(&proto);
} else {
proto = nsnull;
}
if (!JS_SetPrototype(cx, mJSObject, proto)) {
NS_ERROR("can't set prototype");
return NS_ERROR_FAILURE;
}
} else {
if (!JS_DefineProperty(cx, newInnerWindow->mJSObject, "window",
OBJECT_TO_JSVAL(mJSObject),
JS_PropertyStub, JS_PropertyStub,
JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)) {
NS_ERROR("can't create the 'window' property");
return NS_ERROR_FAILURE;
}
}
}
@ -1939,16 +1986,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
// Loading a new page and creating a new inner window, *not*
// restoring from session history.
// InitClassesWithNewWrappedGlobal() (via CreateNativeGlobalForInner)
// for the new inner window
// sets the global object in cx to be the new wrapped global. We
// don't want that, but re-initializing the outer window will
// fix that for us. And perhaps more importantly, this will
// ensure that the outer window gets a new prototype so we don't
// leak prototype properties from the old inner window to the
// new one.
mContext->InitOuterWindow();
// Now that both the the inner and outer windows are initialized
// let the script context do its magic to hook them together.
mContext->ConnectToInner(newInnerWindow, mJSObject);
@ -1981,8 +2018,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
if ((!reUseInnerWindow || aDocument != oldDoc) && !aState) {
nsCOMPtr<nsIHTMLDocument> html_doc(do_QueryInterface(mDocument));
nsCommonWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject,
html_doc);
nsWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject,
html_doc);
}
if (aDocument) {
@ -2007,29 +2044,33 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
NS_ENSURE_SUCCESS(rv, rv);
// Initialize DOM classes etc on the inner window.
rv = mContext->InitClasses(mJSObject);
rv = mContext->InitClasses(newInnerWindow->mJSObject);
NS_ENSURE_SUCCESS(rv, rv);
if (navigatorHolder) {
// Restore window.navigator onto the new inner window.
JS_ASSERT(JSVAL_IS_OBJECT(nav));
::JS_DefineProperty(cx, newInnerWindow->mJSObject, "navigator",
nav, nsnull, nsnull,
JSPROP_ENUMERATE | JSPROP_PERMANENT |
JSPROP_READONLY);
if (JSVAL_TO_OBJECT(nav)->compartment() == newInnerWindow->mJSObject->compartment()) {
// Restore window.navigator onto the new inner window.
// The Navigator's prototype object keeps a reference to the
// window in which it was first created and can thus cause that
// window to stay alive for too long. Reparenting it here allows
// the window to be collected sooner.
nsIDOMNavigator* navigator =
static_cast<nsIDOMNavigator*>(mNavigator);
::JS_DefineProperty(cx, newInnerWindow->mJSObject, "navigator",
nav, nsnull, nsnull,
JSPROP_ENUMERATE | JSPROP_PERMANENT |
JSPROP_READONLY);
xpc->
ReparentWrappedNativeIfFound(cx, JSVAL_TO_OBJECT(nav),
newInnerWindow->mJSObject,
navigator,
getter_AddRefs(navigatorHolder));
// The Navigator's prototype object keeps a reference to the
// window in which it was first created and can thus cause that
// window to stay alive for too long. Reparenting it here allows
// the window to be collected sooner.
nsIDOMNavigator* navigator =
static_cast<nsIDOMNavigator*>(mNavigator);
xpc->
ReparentWrappedNativeIfFound(cx, JSVAL_TO_OBJECT(nav),
newInnerWindow->mJSObject,
navigator,
getter_AddRefs(navigatorHolder));
}
}
}
@ -2050,16 +2091,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
mContext->GC();
mContext->DidInitializeContext();
if (!wrapper) {
rv = xpc->GetWrappedNativeOfJSObject(cx, mJSObject,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = xpc->UpdateXOWs((JSContext *)GetContextInternal()->GetNativeContext(),
wrapper, nsIXPConnect::XPC_XOW_NAVIGATED);
NS_ENSURE_SUCCESS(rv, rv);
if (!aState && !reUseInnerWindow) {
nsContentUtils::AddScriptRunner(
NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated));
@ -2157,7 +2188,8 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
for (nsRefPtr<nsGlobalWindow> inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
inner != this;
inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
NS_ASSERTION(inner->mOuterWindow == this, "bad outer window pointer");
NS_ASSERTION(!inner->mOuterWindow || inner->mOuterWindow == this,
"bad outer window pointer");
inner->FreeInnerObjects(PR_TRUE);
}
@ -2407,6 +2439,8 @@ nsGlobalWindow::AreDialogsBlocked()
bool
nsGlobalWindow::ConfirmDialogAllowed()
{
FORWARD_TO_OUTER(ConfirmDialogAllowed, (), NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_TRUE(mDocShell, false);
nsCOMPtr<nsIPromptService> promptSvc =
do_GetService("@mozilla.org/embedcomp/prompt-service;1");
@ -2600,7 +2634,7 @@ nsGlobalWindow::DefineArgumentsProperty(nsIArray *aArguments)
if (mIsModalContentWindow) {
// Modal content windows don't have an "arguments" property, they
// have a "dialogArguments" property which is handled
// separately. See nsCommonWindowSH::NewResolve().
// separately. See nsWindowSH::NewResolve().
return NS_OK;
}
@ -5540,8 +5574,24 @@ nsGlobalWindow::CallerInnerWindow()
return nsnull;
}
JSObject *scope = ::JS_GetScopeChain(cx);
JSObject *scope = nsnull;
JSStackFrame *fp = nsnull;
JS_FrameIterator(cx, &fp);
if (fp) {
while (fp->isDummyFrame()) {
if (!JS_FrameIterator(cx, &fp))
break;
}
if (fp)
scope = &fp->scopeChain();
}
if (!scope)
scope = JS_GetScopeChain(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, scope))
return nsnull;
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
@ -5703,15 +5753,7 @@ PostMessageEvent::Run()
NS_IMETHODIMP
nsGlobalWindow::PostMessageMoz(const nsAString& aMessage, const nsAString& aOrigin)
{
// NB: Since much of what this method does must happen at event dispatch time,
// this method does not forward to the inner window, unlike most other
// methods. We do this because the only time we need to refer to this
// window, we need a reference to the outer window (the PostMessageEvent
// ctor call), and we don't want to pay the price of forwarding to the
// inner window for no actual benefit. Furthermore, this function must
// only be called from script anyway, which should only have references to
// outer windows (and if script has an inner window we've already lost).
NS_ABORT_IF_FALSE(IsOuterWindow(), "only call this method on outer windows");
FORWARD_TO_OUTER(PostMessageMoz, (aMessage, aOrigin), NS_ERROR_NOT_INITIALIZED);
//
// Window.postMessage is an intentional subversion of the same-origin policy.
@ -7203,14 +7245,15 @@ nsGlobalWindow::SetChromeEventHandler(nsPIDOMEventTarget* aChromeEventHandler)
for (nsGlobalWindow *inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
inner != this;
inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
NS_ASSERTION(inner->mOuterWindow == this, "bad outer window pointer");
NS_ASSERTION(!inner->mOuterWindow || inner->mOuterWindow == this,
"bad outer window pointer");
inner->SetChromeEventHandlerInternal(aChromeEventHandler);
}
} else if (mOuterWindow) {
// Need the cast to be able to call the protected method on a
// superclass. We could make the method public instead, but it's really
// better this way.
static_cast<nsGlobalWindow*>(mOuterWindow)->
static_cast<nsGlobalWindow*>(mOuterWindow.get())->
SetChromeEventHandlerInternal(aChromeEventHandler);
}
}
@ -9683,12 +9726,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
DOMCI_DATA(ChromeWindow, nsGlobalChromeWindow)
DOMCI_DATA(InnerChromeWindow, nsGlobalChromeWindow)
// QueryInterface implementation for nsGlobalChromeWindow
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalChromeWindow)
NS_INTERFACE_MAP_ENTRY(nsIDOMChromeWindow)
WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ChromeWindow)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ChromeWindow)
NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
NS_IMPL_ADDREF_INHERITED(nsGlobalChromeWindow, nsGlobalWindow)
@ -9967,11 +10009,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalModalWindow,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
DOMCI_DATA(ModalContentWindow, nsGlobalModalWindow)
DOMCI_DATA(InnerModalContentWindow, nsGlobalModalWindow)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalModalWindow)
NS_INTERFACE_MAP_ENTRY(nsIDOMModalContentWindow)
WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ModalContentWindow)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ModalContentWindow)
NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow, nsGlobalWindow)

Просмотреть файл

@ -110,6 +110,10 @@
#include "nsFrameMessageManager.h"
#include "mozilla/TimeStamp.h"
// JS includes
#include "jsapi.h"
#include "jswrapper.h"
#define DEFAULT_HOME_PAGE "www.mozilla.org"
#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
@ -226,6 +230,25 @@ private:
nsAutoRefCnt mRefCnt;
};
//*****************************************************************************
// nsOuterWindow: Outer Window Proxy
//*****************************************************************************
class nsOuterWindowProxy : public JSWrapper
{
public:
nsOuterWindowProxy() : JSWrapper((uintN)0) {}
virtual bool isOuterWindow() {
return true;
}
JSString *obj_toString(JSContext *cx, JSObject *wrapper);
static nsOuterWindowProxy singleton;
};
JSObject *NS_NewOuterWindowProxy(JSContext *cx, JSObject *parent);
//*****************************************************************************
// nsGlobalWindow: Global Object for Scripting
//*****************************************************************************
@ -257,6 +280,7 @@ class nsGlobalWindow : public nsPIDOMWindow,
public nsIDOMStorageWindow,
public nsSupportsWeakReference,
public nsIInterfaceRequestor,
public nsWrapperCache,
public PRCListStr
{
public:

Просмотреть файл

@ -72,10 +72,10 @@ public:
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
NS_ISCRIPTCONTEXTPRINCIPAL_IID)
// 5b6d04a3-f095-4924-ad84-4f44f9b3fae0
// a7139c0e-962c-44b6-bec3-e4166bfe84eb
#define NS_ISCRIPTCONTEXT_IID \
{ 0x5b6d04a3, 0xf095, 0x4924, \
{ 0xad, 0x84, 0x4f, 0x44, 0xf9, 0xb3, 0xfa, 0xe0 } }
{ 0xa7139c0e, 0x962c, 0x44b6, \
{ 0xbe, 0xc3, 0xe4, 0x16, 0x6b, 0xfe, 0x84, 0xeb } }
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
know what language we have is a little silly... */
@ -346,6 +346,11 @@ public:
virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
nsIScriptGlobalObject *aCurrentInner) = 0;
/**
* Given an outer object, updates this context with that outer object.
*/
virtual nsresult SetOuterObject(void *aOuterObject) = 0;
/**
* Prepares this context for use with the current inner window for the
* context's global object. This must be called after CreateOuterObject.

Просмотреть файл

@ -102,10 +102,8 @@
#include "nsITimelineService.h"
#include "nsDOMScriptObjectHolder.h"
#include "prmem.h"
#ifdef NS_DEBUG
#include "WrapperFactory.h"
#include "nsGlobalWindow.h"
#endif
#ifdef MOZ_JSDEBUGGER
#include "jsdIDebuggerService.h"
@ -1317,7 +1315,7 @@ nsJSContext::~nsJSContext()
#endif
NS_PRECONDITION(!mTerminations, "Shouldn't have termination funcs by now");
mGlobalWrapperRef = nsnull;
mGlobalObjectRef = nsnull;
DestroyJSContext();
@ -1375,11 +1373,11 @@ NS_IMPL_CYCLE_COLLECTION_ROOT_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSContext)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobalWrapperRef)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobalObjectRef)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSContext)
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsJSContext, tmp->GetCCRefcnt())
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGlobalWrapperRef)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGlobalObjectRef)
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mContext");
nsContentUtils::XPConnect()->NoteJSContext(tmp->mContext, cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -1718,6 +1716,10 @@ nsJSContext::EvaluateString(const nsAString& aScript,
// If all went well, convert val to a string if one is wanted.
if (ok) {
JSAutoRequest ar(mContext);
JSAutoEnterCompartment ac;
if (!ac.enter(mContext, (JSObject *)aScopeObject)) {
stack->Pop(nsnull);
}
rv = JSValueToAString(mContext, val, aRetValue, aIsUndefined);
}
else {
@ -2192,11 +2194,25 @@ nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, void *aScope,
NS_ENSURE_SUCCESS(rv, rv);
JSObject *funobj = (JSObject*) aHandler;
JSAutoRequest ar(mContext);
NS_ASSERTION(JS_TypeOfValue(mContext, OBJECT_TO_JSVAL(funobj)) == JSTYPE_FUNCTION,
"Event handler object not a function");
#ifdef DEBUG
{
JSAutoEnterCompartment ac;
if (!ac.enter(mContext, funobj)) {
return NS_ERROR_FAILURE;
}
NS_ASSERTION(JS_TypeOfValue(mContext,
OBJECT_TO_JSVAL(funobj)) == JSTYPE_FUNCTION,
"Event handler object not a function");
}
#endif
JSAutoEnterCompartment ac;
if (!ac.enter(mContext, target)) {
return NS_ERROR_FAILURE;
}
// Push our JSContext on our thread's context stack, in case native code
// called from JS calls back into JS via XPConnect.
@ -2247,6 +2263,11 @@ nsJSContext::GetBoundEventHandler(nsISupports* aTarget, void *aScope,
rv = JSObjectFromInterface(aTarget, aScope, &obj);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoEnterCompartment ac;
if (!ac.enter(mContext, obj)) {
return NS_ERROR_FAILURE;
}
jsval funval;
if (!JS_LookupProperty(mContext, obj,
nsAtomCString(aName).get(), &funval))
@ -2407,7 +2428,11 @@ nsJSContext::GetGlobalObject()
JSObject *global = ::JS_GetGlobalObject(mContext);
if (!global) {
NS_WARNING("Context has no global.");
return nsnull;
}
OBJ_TO_INNER_OBJECT(mContext, global);
if (!global) {
return nsnull;
}
@ -2418,6 +2443,12 @@ nsJSContext::GetGlobalObject()
return nsnull;
}
JSAutoEnterCompartment ac;
// NB: This AutoCrossCompartmentCall is only here to silence a warning. If
// it fails, nothing bad will happen.
ac.enterAndIgnoreErrors(mContext, global);
nsCOMPtr<nsIScriptGlobalObject> sgo;
nsISupports *priv =
(nsISupports *)::JS_GetPrivate(mContext, global);
@ -2436,7 +2467,11 @@ nsJSContext::GetGlobalObject()
// This'll return a pointer to something we're about to release, but
// that's ok, the JS object will hold it alive long enough.
return sgo;
nsCOMPtr<nsPIDOMWindow> pwin(do_QueryInterface(sgo));
if (!pwin)
return sgo;
return static_cast<nsGlobalWindow *>(pwin->GetOuterWindow());
}
void *
@ -2455,11 +2490,18 @@ nsJSContext::CreateNativeGlobalForInner(
nsIXPConnect *xpc = nsContentUtils::XPConnect();
PRUint32 flags = aIsChrome? nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT : 0;
nsCOMPtr<nsIXPConnectJSObjectHolder> jsholder;
nsCOMPtr<nsIPrincipal> systemPrincipal;
if (aIsChrome) {
nsIScriptSecurityManager *ssm = nsContentUtils::GetSecurityManager();
ssm->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
}
nsresult rv = xpc->
InitClassesWithNewWrappedGlobal(mContext,
aNewInner, NS_GET_IID(nsISupports),
aPrincipal, EmptyCString(),
flags,
aIsChrome ? systemPrincipal.get() : aPrincipal,
EmptyCString(), flags,
getter_AddRefs(jsholder));
if (NS_FAILED(rv))
return rv;
@ -2488,6 +2530,12 @@ nsJSContext::ConnectToInner(nsIScriptGlobalObject *aNewInner, void *aOuterGlobal
// outer (through the JSExtendedClass hook outerObject), so this
// prototype sharing works.
// Now that we're connecting the outer global to the inner one,
// we must have transplanted it. The JS engine tries to maintain
// the global object's compartment as its default compartment,
// so update that now since it might have changed.
JS_SetGlobalObject(mContext, outerGlobal);
// We do *not* want to use anything else out of the outer
// object's prototype chain than the first prototype, which is
// the XPConnect prototype. The rest we want from the inner
@ -2502,11 +2550,6 @@ nsJSContext::ConnectToInner(nsIScriptGlobalObject *aNewInner, void *aOuterGlobal
JS_SetPrototype(mContext, newInnerJSObject, proto);
JS_SetPrototype(mContext, proto, innerProtoProto);
// Now that we're connecting the outer global to the inner one,
// we must have transplanted it. The JS engine tries to maintain
// the global object's compartment as its default compartment,
// so update that now since it might have changed.
JS_SetGlobalObject(mContext, outerGlobal);
return NS_OK;
}
@ -2528,19 +2571,6 @@ nsJSContext::InitContext()
::JS_SetErrorReporter(mContext, NS_ScriptErrorReporter);
nsIXPConnect *xpc = nsContentUtils::XPConnect();
if (!nsDOMClassInfo::GetXPCNativeWrapperGetPropertyOp()) {
JSPropertyOp getProperty;
xpc->GetNativeWrapperGetPropertyOp(&getProperty);
nsDOMClassInfo::SetXPCNativeWrapperGetPropertyOp(getProperty);
}
if (!nsDOMClassInfo::GetXrayWrapperPropertyHolderGetPropertyOp()) {
JSPropertyOp getProperty;
xpc->GetXrayWrapperPropertyHolderGetPropertyOp(&getProperty);
nsDOMClassInfo::SetXrayWrapperPropertyHolderGetPropertyOp(getProperty);
}
return NS_OK;
}
@ -2548,6 +2578,8 @@ nsresult
nsJSContext::CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
nsIScriptGlobalObject *aCurrentInner)
{
mGlobalObjectRef = aGlobalObject;
nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(aGlobalObject));
PRUint32 flags = 0;
@ -2566,20 +2598,33 @@ nsJSContext::CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = xpc->WrapNative(mContext, aCurrentInner->GetGlobalJSObject(),
aGlobalObject, NS_GET_IID(nsISupports),
aCurrentInner, NS_GET_IID(nsISupports),
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
// Force our context's global object to be the outer.
JSObject *globalObj;
holder->GetJSObject(&globalObj);
JS_SetGlobalObject(mContext, globalObj);
nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(holder));
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
// Hold a strong reference to the wrapper for the global to avoid
// rooting and unrooting the global object every time its AddRef()
// or Release() methods are called
mGlobalWrapperRef = holder;
wrapper->RefreshPrototype();
JSObject *outer =
NS_NewOuterWindowProxy(mContext, aCurrentInner->GetGlobalJSObject());
if (!outer) {
return NS_ERROR_FAILURE;
}
return SetOuterObject(outer);
}
nsresult
nsJSContext::SetOuterObject(void *aOuterObject)
{
JSObject *outer = static_cast<JSObject *>(aOuterObject);
// Force our context's global object to be the outer.
JS_SetGlobalObject(mContext, outer);
return NS_OK;
}
@ -2587,32 +2632,9 @@ nsresult
nsJSContext::InitOuterWindow()
{
JSObject *global = JS_GetGlobalObject(mContext);
nsIScriptGlobalObject *sgo = GetGlobalObject();
OBJ_TO_INNER_OBJECT(mContext, global);
// Call ClearScope to nuke any properties (e.g. Function and Object) on the
// outer object. From now on, anybody asking the outer object for these
// properties will be forwarded to the inner window.
JS_ClearScope(mContext, global);
nsresult rv = NS_OK;
nsCOMPtr<nsIClassInfo> ci(do_QueryInterface(sgo));
if (ci) {
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = nsContentUtils::WrapNative(mContext, global, sgo, &v,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(holder));
NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
rv = wrapper->RefreshPrototype();
NS_ENSURE_SUCCESS(rv, rv);
}
rv = InitClasses(global); // this will complete global object initialization
nsresult rv = InitClasses(global); // this will complete global object initialization
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
@ -2652,6 +2674,12 @@ nsJSContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aArg
if (strcmp(aPropName, "dialogArguments") == 0 && argc <= 1) {
vargs = argc ? argv[0] : JSVAL_VOID;
} else {
for (PRUint32 i = 0; i < argc; ++i) {
if (!JS_WrapValue(mContext, &argv[i])) {
return NS_ERROR_FAILURE;
}
}
JSObject *args = ::JS_NewArrayObject(mContext, argc, argv);
vargs = OBJECT_TO_JSVAL(args);
}
@ -3341,7 +3369,14 @@ nsJSContext::ClearScope(void *aGlobalObj, PRBool aClearFromProtoChain)
if (aGlobalObj) {
JSObject *obj = (JSObject *)aGlobalObj;
JSAutoRequest ar(mContext);
JSAutoEnterCompartment ac;
ac.enterAndIgnoreErrors(mContext, obj);
JS_ClearScope(mContext, obj);
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ClearScope(mContext, &obj->getProxyExtra().toObject());
}
if (!obj->getParent()) {
JS_ClearRegExpStatics(mContext, obj);
}
@ -3363,7 +3398,7 @@ nsJSContext::ClearScope(void *aGlobalObj, PRBool aClearFromProtoChain)
// chain when we're clearing an outer window whose current inner we
// still want.
if (aClearFromProtoChain) {
nsCommonWindowSH::InvalidateGlobalScopePolluter(mContext, obj);
nsWindowSH::InvalidateGlobalScopePolluter(mContext, obj);
// Clear up obj's prototype chain, but not Object.prototype.
for (JSObject *o = ::JS_GetPrototype(mContext, obj), *next;
@ -3932,6 +3967,35 @@ ObjectPrincipalFinder(JSContext *cx, JSObject *obj)
return jsPrincipals;
}
static JSObject*
DOMReadStructuredClone(JSContext* cx,
JSStructuredCloneReader* reader,
uint32 tag,
uint32 data)
{
// We don't currently support any extensions to structured cloning.
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
return nsnull;
}
static JSBool
DOMWriteStructuredClone(JSContext* cx,
JSStructuredCloneWriter* writer,
JSObject* obj)
{
// We don't currently support any extensions to structured cloning.
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
return JS_FALSE;
}
static void
DOMStructuredCloneError(JSContext* cx,
uint32 errorid)
{
// We don't currently support any extensions to structured cloning.
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
}
//static
nsresult
nsJSRuntime::Init()
@ -3970,6 +4034,14 @@ nsJSRuntime::Init()
callbacks->findObjectPrincipals = ObjectPrincipalFinder;
// Set up the structured clone callbacks.
static JSStructuredCloneCallbacks cloneCallbacks = {
DOMReadStructuredClone,
DOMWriteStructuredClone,
DOMStructuredCloneError
};
JS_SetStructuredCloneCallbacks(sRuntime, &cloneCallbacks);
// Set these global xpconnect options...
nsContentUtils::RegisterPrefCallback("dom.max_script_run_time",
MaxScriptRunTimePrefChangedCallback,

Просмотреть файл

@ -143,6 +143,7 @@ public:
virtual nsresult InitContext();
virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
nsIScriptGlobalObject *aCurrentInner);
virtual nsresult SetOuterObject(void *aOuterObject);
virtual nsresult InitOuterWindow();
virtual PRBool IsContextInitialized();
virtual void FinalizeContext();
@ -311,12 +312,9 @@ private:
PRTime mModalStateTime;
PRUint32 mModalStateDepth;
// mGlobalWrapperRef is used only to hold a strong reference to the
// global object wrapper while the nsJSContext is alive. This cuts
// down on the number of rooting and unrooting calls XPConnect has
// to make when the global object is touched in JS.
nsCOMPtr<nsISupports> mGlobalWrapperRef;
// mGlobalObjectRef ensures that the outer window stays alive as long as the
// context does. It is eventually collected by the cycle collector.
nsCOMPtr<nsISupports> mGlobalObjectRef;
static int JSOptionChangedCallback(const char *pref, void *data);

Просмотреть файл

@ -316,7 +316,7 @@ public:
nsPIDOMWindow *GetOuterWindow()
{
return mIsInnerWindow ? mOuterWindow : this;
return mIsInnerWindow ? mOuterWindow.get() : this;
}
nsPIDOMWindow *GetCurrentInnerWindow() const
@ -606,7 +606,7 @@ protected:
// And these are the references between inner and outer windows.
nsPIDOMWindow *mInnerWindow;
nsPIDOMWindow *mOuterWindow;
nsCOMPtr<nsPIDOMWindow> mOuterWindow;
// the element within the document that is currently focused when this
// window is active

Просмотреть файл

@ -78,7 +78,8 @@ public:
void SetWrapper(JSObject* aWrapper)
{
NS_ASSERTION(!PreservingWrapper(), "Clearing a preserved wrapper!");
mWrapperPtrBits = reinterpret_cast<PtrBits>(aWrapper);
mWrapperPtrBits = reinterpret_cast<PtrBits>(aWrapper) |
(mWrapperPtrBits & WRAPPER_IS_PROXY);
}
void ClearWrapper()
@ -99,12 +100,23 @@ public:
PRBool PreservingWrapper()
{
return mWrapperPtrBits & WRAPPER_BIT_PRESERVED;
return (mWrapperPtrBits & WRAPPER_BIT_PRESERVED) != 0;
}
void SetIsProxy()
{
mWrapperPtrBits |= WRAPPER_IS_PROXY;
}
PRBool IsProxy()
{
return (mWrapperPtrBits & WRAPPER_IS_PROXY) != 0;
}
private:
enum { WRAPPER_BIT_PRESERVED = 1 << 0 };
enum { kWrapperBitMask = 0x1 };
enum { WRAPPER_IS_PROXY = 1 << 1 };
enum { kWrapperBitMask = (WRAPPER_BIT_PRESERVED | WRAPPER_IS_PROXY) };
PtrBits mWrapperPtrBits;
};

Просмотреть файл

@ -465,6 +465,8 @@ IDBCursor::Update(const jsval &aValue,
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsresult rv;
if (mType != OBJECTSTORE) {
NS_NOTYETIMPLEMENTED("Implement me!");
return NS_ERROR_NOT_IMPLEMENTED;
@ -483,12 +485,7 @@ IDBCursor::Update(const jsval &aValue,
JSAutoRequest ar(aCx);
js::AutoValueRooter clone(aCx);
nsresult rv = nsContentUtils::CreateStructuredClone(aCx, aValue,
clone.jsval_addr());
if (NS_FAILED(rv)) {
return rv;
}
js::AutoValueRooter clone(aCx, aValue);
if (!mObjectStore->KeyPath().IsEmpty()) {
// Make sure the object given has the correct keyPath value set on it or
@ -506,6 +503,9 @@ IDBCursor::Update(const jsval &aValue,
rv = IDBObjectStore::GetJSValFromKey(key, aCx, prop.jsval_addr());
NS_ENSURE_SUCCESS(rv, rv);
ok = JS_StructuredClone(aCx, clone.jsval_value(), clone.jsval_addr());
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
ok = JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(clone.jsval_value()),
keyPathChars, keyPathLen, prop.jsval_value(), nsnull,
nsnull, JSPROP_ENUMERATE);

Просмотреть файл

@ -497,15 +497,9 @@ IDBObjectStore::GetJSONFromArg0(/* jsval arg0, */
JSAutoRequest ar(cx);
js::AutoValueRooter clone(cx);
rv = nsContentUtils::CreateStructuredClone(cx, argv[0], clone.jsval_addr());
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIJSON> json(new nsJSON());
rv = json->EncodeFromJSVal(clone.jsval_addr(), cx, aJSON);
rv = json->EncodeFromJSVal(&argv[0], cx, aJSON);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
@ -775,14 +769,9 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
Key& aKey,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray)
{
JSAutoRequest ar(aCx);
nsresult rv;
js::AutoValueRooter clone(aCx);
nsresult rv = nsContentUtils::CreateStructuredClone(aCx, aValue,
clone.jsval_addr());
if (NS_FAILED(rv)) {
return rv;
}
JSAutoRequest ar(aCx);
if (mKeyPath.IsEmpty()) {
rv = GetKeyFromJSVal(aKeyVal, aKey);
@ -790,11 +779,11 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
}
else {
// Inline keys live on the object. Make sure it is an object.
if (JSVAL_IS_PRIMITIVE(clone.jsval_value())) {
if (JSVAL_IS_PRIMITIVE(aValue)) {
return NS_ERROR_INVALID_ARG;
}
rv = GetKeyFromObject(aCx, JSVAL_TO_OBJECT(clone.jsval_value()), mKeyPath, aKey);
rv = GetKeyFromObject(aCx, JSVAL_TO_OBJECT(aValue), mKeyPath, aKey);
NS_ENSURE_SUCCESS(rv, rv);
// Except if null was passed, in which case we're supposed to generate the
@ -812,11 +801,11 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
ObjectStoreInfo* objectStoreInfo = GetObjectStoreInfo();
NS_ENSURE_TRUE(objectStoreInfo, NS_ERROR_FAILURE);
rv = GetIndexUpdateInfo(objectStoreInfo, aCx, clone.jsval_value(), aUpdateInfoArray);
rv = GetIndexUpdateInfo(objectStoreInfo, aCx, aValue, aUpdateInfoArray);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIJSON> json(new nsJSON());
rv = json->EncodeFromJSVal(clone.jsval_addr(), aCx, aJSON);
rv = json->EncodeFromJSVal(&aValue, aCx, aJSON);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;

Просмотреть файл

@ -60,7 +60,7 @@ interface nsIDOMEvent;
interface nsITransferable;
interface nsIQueryContentEventResult;
[scriptable, uuid(8707ed93-3277-42a5-a235-533aa661a263)]
[scriptable, uuid(43fd9eb5-9e08-4d60-a305-3f87b1d5c398)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -470,17 +470,6 @@ interface nsIDOMWindowUtils : nsISupports {
*/
void getScrollXY(in boolean aFlushLayout, out long aScrollX, out long aScrollY);
/**
* Creates a ChromeObjectWrapper for the object and returns it.
*
* @param scope The JavaScript object whose scope we'll use as the
* parent of the wrapper.
* @param objToWrap The JavaScript object to wrap.
* @return the wrapped object.
*/
void getCOWForObject(/* scope, objToWrap */);
/**
* Get IME open state. TRUE means 'Open', otherwise, 'Close'.
* This property works only when IMEEnabled is IME_STATUS_ENABLED.

Просмотреть файл

@ -202,6 +202,13 @@ nsJSON::EncodeFromJSVal(jsval *value, JSContext *cx, nsAString &result)
// Begin a new request
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
JSObject *obj;
if (JSVAL_IS_OBJECT(*value) && (obj = JSVAL_TO_OBJECT(*value)) &&
!ac.enter(cx, obj)) {
return NS_ERROR_FAILURE;
}
nsJSONWriter writer;
JSBool ok = JS_Stringify(cx, value, NULL, JSVAL_NULL,
WriteCallback, &writer);

Просмотреть файл

@ -1539,14 +1539,10 @@ nsDOMWorker::PostMessageInternal(PRBool aToInner)
JSAutoRequest ar(cx);
nsAutoJSValHolder val;
if (!val.Hold(cx)) {
return NS_ERROR_FAILURE;
}
JSAutoStructuredCloneBuffer buffer(cx);
rv = nsContentUtils::CreateStructuredClone(cx, argv[0], val.ToJSValPtr());
if (NS_FAILED(rv)) {
return rv;
if (!buffer.write(argv[0])) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
nsRefPtr<nsDOMWorkerMessageEvent> message = new nsDOMWorkerMessageEvent();
@ -1557,7 +1553,7 @@ nsDOMWorker::PostMessageInternal(PRBool aToInner)
nsnull);
NS_ENSURE_SUCCESS(rv, rv);
rv = message->SetJSVal(cx, val);
rv = message->SetJSData(cx, buffer);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsDOMFireEventRunnable> runnable =

Просмотреть файл

@ -264,15 +264,17 @@ NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerMessageEvent, nsIDOMEvent,
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerMessageEvent)
nsresult
nsDOMWorkerMessageEvent::SetJSVal(JSContext* aCx,
jsval aData)
nsDOMWorkerMessageEvent::SetJSData(JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer)
{
NS_ASSERTION(aCx, "Null context!");
if (!mDataVal.Hold(aCx)) {
NS_WARNING("Failed to hold jsval!");
return NS_ERROR_FAILURE;
}
mDataVal = aData;
aBuffer.steal(&mData, &mDataLen);
return NS_OK;
}
@ -287,19 +289,21 @@ nsDOMWorkerMessageEvent::GetData(nsAString& aData)
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(cc, NS_ERROR_UNEXPECTED);
if (!mDataValWasReparented) {
if (JSVAL_IS_OBJECT(mDataVal) && !JSVAL_IS_NULL(mDataVal)) {
JSContext* cx;
rv = cc->GetJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
if (mData) {
JSContext* cx;
rv = cc->GetJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
rv =
nsContentUtils::ReparentClonedObjectToScope(cx,
JSVAL_TO_OBJECT(mDataVal),
JS_GetGlobalObject(cx));
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(cx);
JSAutoStructuredCloneBuffer buffer(cx);
buffer.adopt(mData, mDataLen);
mData = nsnull;
mDataLen = 0;
if (!buffer.read(mDataVal.ToJSValPtr())) {
NS_WARNING("Failed to deserialize!");
return NS_ERROR_FAILURE;
}
mDataValWasReparented = PR_TRUE;
}
jsval* retval;

Просмотреть файл

@ -47,6 +47,7 @@
#include "nsIRunnable.h"
#include "jsapi.h"
#include "jsutil.h"
#include "nsAutoJSValHolder.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
@ -210,17 +211,18 @@ public:
NS_DECL_NSIWORKERMESSAGEEVENT
NS_DECL_NSICLASSINFO_GETINTERFACES
nsDOMWorkerMessageEvent() : mDataValWasReparented(PR_FALSE) { }
nsDOMWorkerMessageEvent() : mData(nsnull) { }
nsresult SetJSVal(JSContext* aCx,
jsval aData);
nsresult SetJSData(JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer);
protected:
nsString mOrigin;
nsCOMPtr<nsISupports> mSource;
nsAutoJSValHolder mDataVal;
PRBool mDataValWasReparented;
uint64* mData;
size_t mDataLen;
};
class nsDOMWorkerProgressEvent : public nsDOMWorkerEvent,
@ -269,11 +271,6 @@ protected:
nsAutoRefCnt mRefCnt;
};
enum SnapshotChoice {
WANT_SNAPSHOT,
NO_SNAPSHOT
};
class nsDOMWorkerXHREvent : public nsDOMWorkerProgressEvent,
public nsIRunnable
{

Просмотреть файл

@ -315,6 +315,9 @@ function onmessage(event) {
postMessage(messages[index].value);
}
catch (e) {
if (e.result != 2152923154) {
throw "Exception of the wrong type: " + e.result;
}
exception = e;
}

Просмотреть файл

@ -35,26 +35,35 @@ function runTest() {
is(lastlocation.iframeprop, 42, 'can read the new prop');
ok(firstlocation !== lastlocation, 'got a new location object');
// firstlocation should still work.
ok(firstlocation.href.indexOf('file_location.html'), 'can read location.href');
firstlocation.href = 'http://example.com/tests/dom/tests/mochitest/dom-level0/file_location.html';
return;
}
if (count == 3) {
var permissionDenied = false;
try {
isnot($('ifr').contentWindow.location.iframeprop, 42, "shouldn't see this");
var foo = $('ifr').contentWindow.location.href == '';
} catch (e) {
ok(/Permission denied/.test(e), "correctly threw a security error");
permissionDenied = /Permission denied/.test(e.message);
}
ok(permissionDenied, 'correctly threw a permission denied security error when reading location.href');
// XXX this doesn't work - file a bug on me!
//firstlocation.href = 'http://mochi.test:8888/tests/dom/tests/mochitest/dom-level0/file_location.html';
todo(false, 'can use old same-origin location object to set cross-origin frame');
$('ifr').contentWindow.location = 'file_location.html';
permissionDenied = false;
try {
var foo = $('ifr').contentWindow.location.iframeprop == 42;
} catch (e) {
permissionDenied = /Permission denied/.test(e.message);
}
ok(permissionDenied, 'correctly threw a permission denied security error an expando on location');
firstlocation.href = 'http://mochi.test:8888/tests/dom/tests/mochitest/dom-level0/file_location.html';
return;
}
is(lastlocation.iframeprop, 42, 'can still read old values of the location object');
ok(lastlocation !== $('ifr').contentWindow.location, 'location objects are distinct');
ok(firstlocation.href.indexOf('file_location.html'), 'can read location.href');
SimpleTest.finish();
}

Просмотреть файл

@ -1,10 +1,10 @@
<html>
<script>
function check(elt, expectXOW, message) {
function check(elt, expectProxy, message) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var result = ((utils.getClassName(elt) === 'XPCCrossOriginWrapper') === expectXOW)
var result = ((utils.getClassName(elt) === 'Proxy') === expectProxy)
? "PASS"
: "FAIL";

Просмотреть файл

@ -173,23 +173,23 @@ const js::Class ObjectWrapperParent::sCPOW_JSClass = {
"CrossProcessObjectWrapper",
JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE |
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(sNumSlots),
js::Valueify(ObjectWrapperParent::CPOW_AddProperty),
js::Valueify(ObjectWrapperParent::CPOW_DelProperty),
js::Valueify(ObjectWrapperParent::CPOW_GetProperty),
js::Valueify(ObjectWrapperParent::CPOW_SetProperty),
JS_VALUEIFY(js::PropertyOp, ObjectWrapperParent::CPOW_AddProperty),
JS_VALUEIFY(js::PropertyOp, ObjectWrapperParent::CPOW_DelProperty),
JS_VALUEIFY(js::PropertyOp, ObjectWrapperParent::CPOW_GetProperty),
JS_VALUEIFY(js::PropertyOp, ObjectWrapperParent::CPOW_SetProperty),
(JSEnumerateOp) ObjectWrapperParent::CPOW_NewEnumerate,
(JSResolveOp) ObjectWrapperParent::CPOW_NewResolve,
js::Valueify(ObjectWrapperParent::CPOW_Convert),
JS_VALUEIFY(js::ConvertOp, ObjectWrapperParent::CPOW_Convert),
ObjectWrapperParent::CPOW_Finalize,
nsnull, // reserved1
nsnull, // checkAccess
js::Valueify(ObjectWrapperParent::CPOW_Call),
js::Valueify(ObjectWrapperParent::CPOW_Construct),
JS_VALUEIFY(js::CallOp, ObjectWrapperParent::CPOW_Call),
JS_VALUEIFY(js::CallOp, ObjectWrapperParent::CPOW_Construct),
nsnull, // xdrObject
js::Valueify(ObjectWrapperParent::CPOW_HasInstance),
JS_VALUEIFY(js::HasInstanceOp, ObjectWrapperParent::CPOW_HasInstance),
nsnull, // mark
{
js::Valueify(ObjectWrapperParent::CPOW_Equality),
JS_VALUEIFY(js::EqualityOp, ObjectWrapperParent::CPOW_Equality),
nsnull, // outerObject
nsnull, // innerObject
nsnull, // iteratorObject

Просмотреть файл

@ -452,6 +452,10 @@ JetpackActorCommon::RecvMessage(JSContext* cx,
JSObject* implGlobal = JS_GetGlobalObject(cx);
js::AutoValueRooter rval(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, implGlobal))
return false;
for (PRUint32 i = 0; i < snapshot.Length(); ++i) {
Variant* vp = results ? results->AppendElement() : NULL;
rval.set(JSVAL_VOID);

Просмотреть файл

@ -448,11 +448,15 @@ JetpackChild::CreateSandbox(JSContext* cx, uintN argc, jsval* vp)
if (!obj)
return JS_FALSE;
jsval rval = OBJECT_TO_JSVAL(obj);
if (!JS_WrapValue(cx, &rval))
return JS_FALSE;
JSAutoEnterCompartment ac;
if (!ac.enter(cx, obj))
return JS_FALSE;
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
JS_SET_RVAL(cx, vp, rval);
return JS_InitStandardClasses(cx, obj);
}
@ -466,23 +470,32 @@ JetpackChild::EvalInSandbox(JSContext* cx, uintN argc, jsval* vp)
jsval* argv = JS_ARGV(cx, vp);
JSObject* obj;
if (!JSVAL_IS_OBJECT(argv[0]) ||
!(obj = JSVAL_TO_OBJECT(argv[0])) ||
&sGlobalClass != JS_GetClass(cx, obj) ||
obj == JS_GetGlobalObject(cx)) {
JS_ReportError(cx, "The first argument to evalInSandbox must be a global object created using createSandbox.");
return JS_FALSE;
}
JSString* str = JS_ValueToString(cx, argv[1]);
if (!str)
return JS_FALSE;
JSObject* obj;
if (!JSVAL_IS_OBJECT(argv[0]) ||
!(obj = JSVAL_TO_OBJECT(argv[0]))) {
JS_ReportError(cx, "The first argument to evalInSandbox must be a global object created using createSandbox.");
JS_ASSERT(JS_FALSE);
return JS_FALSE;
}
// Unwrap, and switch compartments
obj = obj->unwrap();
JSAutoEnterCompartment ac;
if (!ac.enter(cx, obj))
return JS_FALSE;
if (&sGlobalClass != JS_GetClass(cx, obj) ||
obj == JS_GetGlobalObject(cx)) {
JS_ReportError(cx, "The first argument to evalInSandbox must be a global object created using createSandbox.");
JS_ASSERT(JS_FALSE);
return JS_FALSE;
}
js::AutoValueRooter ignored(cx);
return JS_EvaluateUCScript(cx, obj, JS_GetStringChars(str), JS_GetStringLength(str), "", 1,
ignored.jsval_addr());

Просмотреть файл

@ -1001,6 +1001,17 @@ interface jsdIScript : jsdIEphemeral
* The |pcmap| argument specifies which pc to source line map to use.
*/
boolean isLineExecutable (in unsigned long line, in unsigned long pcmap);
/**
* Get the first valid PC in the script. This will be either
* (a) the first bytecode in the script, or (b) the next bytecode
* in the script, iff the first bytecode is a JSOP_BEGIN.
*/
unsigned long getFirstValidPC ();
/**
* Return the last valid PC in the script (i.e., the PC just after
* the last bytecode).
*/
unsigned long getEndValidPC ();
/**
* Set a breakpoint at a PC in this script.
*/

Просмотреть файл

@ -478,6 +478,12 @@ jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata)
extern jsuword
jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line);
extern jsuword
jsd_GetFirstValidPC(JSDContext* jsdc, JSDScript* jsdscript);
extern jsuword
jsd_GetEndPC(JSDContext* jsdc, JSDScript* jsdscript);
extern uintN
jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc);

Просмотреть файл

@ -500,20 +500,22 @@ jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript)
jsuword
jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line)
{
#ifdef LIVEWIRE
if( jsdscript && jsdscript->lwscript )
{
uintN newline;
jsdlw_RawToProcessedLineNumber(jsdc, jsdscript, line, &newline);
if( line != newline )
line = newline;
}
#endif
return (jsuword) JS_LineNumberToPC(jsdc->dumbContext,
jsdscript->script, line );
}
jsuword
jsd_GetFirstValidPC(JSDContext* jsdc, JSDScript* jsdscript)
{
return (jsuword) JS_FirstValidPC(jsdc->dumbContext, jsdscript->script );
}
jsuword
jsd_GetEndPC(JSDContext* jsdc, JSDScript* jsdscript)
{
return (jsuword) JS_EndPC(jsdc->dumbContext, jsdscript->script );
}
uintN
jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
{

Просмотреть файл

@ -125,13 +125,14 @@ jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
{
JSScript* script = JS_GetFrameScript(cx, fp);
jsuword pc = (jsuword) JS_GetFramePC(cx, fp);
jsval dummyThis;
/*
* don't construct a JSDStackFrame for dummy frames (those without a
* |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES
* isn't set.
*/
if (JS_GetFrameThis(cx, fp) &&
if (JS_GetFrameThis(cx, fp, &dummyThis) &&
((jsdc->flags & JSD_INCLUDE_NATIVE_FRAMES) ||
JS_IsScriptFrame(cx, fp)))
{
@ -342,11 +343,13 @@ jsd_GetThisForStackFrame(JSDContext* jsdc,
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
{
JSBool ok;
jsval thisval;
JS_BeginRequest(jsdthreadstate->context);
obj = JS_GetFrameThis(jsdthreadstate->context, jsdframe->fp);
ok = JS_GetFrameThis(jsdthreadstate->context, jsdframe->fp, &thisval);
JS_EndRequest(jsdthreadstate->context);
if(obj)
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
if(ok)
jsdval = JSD_NewValue(jsdc, thisval);
}
JSD_UNLOCK_THREADSTATES(jsdc);

Просмотреть файл

@ -69,7 +69,6 @@ _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
JSDScript* jsdscript = NULL;
JSScript * script;
static indent = 0;
char* buf;
const char* funName = NULL;
script = JS_GetFrameScript(cx, fp);
@ -86,25 +85,23 @@ _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
if(before)
{
buf = JS_smprintf("%sentering %s %s this: %0x\n",
_indentSpaces(indent++),
funName,
JS_IsConstructorFrame(cx, fp) ? "constructing":"",
(int)JS_GetFrameThis(cx, fp));
jsval thisVal;
printf("%sentering %s %s this: ",
_indentSpaces(indent++),
funName,
JS_IsConstructorFrame(cx, fp) ? "constructing":"");
if (JS_GetFrameThis(cx, fp, &thisVal))
printf("0x%0llx\n", (JSUword) thisVal);
else
puts("<unavailable>");
}
else
{
buf = JS_smprintf("%sleaving %s\n",
_indentSpaces(--indent),
funName);
printf("%sleaving %s\n", _indentSpaces(--indent), funName);
}
JS_ASSERT(indent >= 0);
if(!buf)
return;
printf(buf);
free(buf);
}
#endif
@ -127,8 +124,12 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
return hookresult;
}
if (before && JS_IsConstructorFrame(cx, fp))
jsd_Constructing(jsdc, cx, JS_GetFrameThis(cx, fp), fp);
if (before && JS_IsConstructorFrame(cx, fp)) {
jsval newObj;
if (!JS_GetFrameThis(cx, fp, &newObj))
return JS_FALSE;
jsd_Constructing(jsdc, cx, JSVAL_TO_OBJECT(newObj), fp);
}
jsscript = JS_GetFrameScript(cx, fp);
if (jsscript)

Просмотреть файл

@ -958,7 +958,9 @@ jsdScript::jsdScript (JSDContext *aCx, JSDScript *aScript) : mValid(PR_FALSE),
mBaseLineNumber(0),
mLineExtent(0),
mPPLineMap(0),
mFirstPC(0)
mFirstValidPC(0),
mFirstPC(0),
mEndPC(0)
{
DEBUG_CREATE ("jsdScript", gScriptCount);
@ -972,6 +974,8 @@ jsdScript::jsdScript (JSDContext *aCx, JSDScript *aScript) : mValid(PR_FALSE),
mBaseLineNumber = JSD_GetScriptBaseLineNumber(mCx, mScript);
mLineExtent = JSD_GetScriptLineExtent(mCx, mScript);
mFirstPC = JSD_GetClosestPC(mCx, mScript, 0);
mFirstValidPC = JSD_GetFirstValidPC(mCx, mScript);
mEndPC = JSD_GetEndPC(mCx, mScript);
JSD_UnlockScriptSubsystem(mCx);
mValid = PR_TRUE;
@ -1475,6 +1479,22 @@ jsdScript::IsLineExecutable(PRUint32 aLine, PRUint32 aPcmap, PRBool *_rval)
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetFirstValidPC(PRUint32 *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = PRUint32(mFirstValidPC - mFirstPC);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetEndValidPC(PRUint32 *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = PRUint32(mEndPC - mFirstPC);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::SetBreakpoint(PRUint32 aPC)
{

Просмотреть файл

@ -182,7 +182,9 @@ class jsdScript : public jsdIScript
PRUint32 mBaseLineNumber, mLineExtent;
PCMapEntry *mPPLineMap;
PRUint32 mPCMapSize;
jsuword mFirstPC;
jsuword mFirstPC; /* address of first PC in script */
jsuword mFirstValidPC; /* address of first valid bkpt PC */
jsuword mEndPC; /* address of end of script code */
};
PRUint32 jsdScript::LastTag = 0;

Просмотреть файл

@ -348,6 +348,22 @@ JSD_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line)
return jsd_GetClosestPC(jsdc, jsdscript, line);
}
JSD_PUBLIC_API(jsuword)
JSD_GetFirstValidPC(JSDContext* jsdc, JSDScript* jsdscript)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
JSD_ASSERT_VALID_SCRIPT(jsdscript);
return jsd_GetFirstValidPC(jsdc, jsdscript);
}
JSD_PUBLIC_API(jsuword)
JSD_GetEndPC(JSDContext* jsdc, JSDScript* jsdscript)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
JSD_ASSERT_VALID_SCRIPT(jsdscript);
return jsd_GetEndPC(jsdc, jsdscript);
}
JSD_PUBLIC_API(uintN)
JSD_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
{

Просмотреть файл

@ -486,6 +486,19 @@ JSD_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata)
extern JSD_PUBLIC_API(jsuword)
JSD_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line);
/*
* Get the first 'Program Counter' value where a breakpoint can be set.
*/
extern JSD_PUBLIC_API(jsuword)
JSD_GetFirstValidPC(JSDContext* jsdc, JSDScript* jsdscript);
/*
* Get the 'Program Counter' value just after the last byte of the script.
* 0 is returned for invalid scripts.
*/
extern JSD_PUBLIC_API(jsuword)
JSD_GetEndPC(JSDContext* jsdc, JSDScript* jsdscript);
/*
* Get the source line number for a given 'Program Counter' location.
* Returns 0 if no source line information is appropriate (or available) for

Просмотреть файл

@ -48,6 +48,7 @@ MODULE = jsdebug
include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_bug507448.html \
test_bug602003.html \
$(NULL)
libs:: $(_TEST_FILES)

Просмотреть файл

@ -0,0 +1,62 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=507448
-->
<head>
<title>Test for Bug 602003</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=507448">Mozilla Bug 507448</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 602003 **/
// This is somewhat unfortunate: jsd only deals with scripts that have a
// nonzero line number, so we can't just createElement a script here.
// So break the test up into three <script>s, of which the middle one has our test functions.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var jsdIDebuggerService = Components.interfaces.jsdIDebuggerService;
var jsd = Components.classes['@mozilla.org/js/jsd/debugger-service;1']
.getService(jsdIDebuggerService);
var jsdOn = jsd.isOn;
if (!jsdOn) {
jsd.on();
ok(jsd.isOn, "JSD should be running.");
}
</script>
<script>
function g(a,b) { return a + b }
</script>
<script>
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var script = jsd.wrapValue(g).script;
// Test the script start/end PC APIs.
var start = script.getFirstValidPC();
var end = script.getEndValidPC();
// Start PC should be 1 for a function because it starts with JSOP_BEGIN.
is(start, 1, "Start PC should be 1");
// End PC should be something greater than 1, and not huge. Changes
// in the bytecode will change this, so we'll just be approximate.
ok(1 < end && end < 100, "End PC doesn't seem sane.");
if (!jsdOn) {
jsd.off();
ok(!jsd.isOn, "JSD shouldn't be running anymore.");
}
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -313,8 +313,8 @@ Narcissus.interpreter = (function() {
return;
for (var i = 0, j = ps.length; i < j; i++) {
// If the thing we're valuating is already equal to the thing we want
// to valuate it to, we have fully saturated (and have a cycle), and
// If the thing we're evaluating is already equal to the thing we want
// to evaluate it to, we have fully saturated (and have a cycle), and
// thus we should break.
if (ps[i].v === v)
break;
@ -324,7 +324,7 @@ Narcissus.interpreter = (function() {
}
function execute(n, x) {
var a, f, i, j, r, s, t, u, v;
var a, c, f, i, j, r, s, t, u, v;
switch (n.type) {
case FUNCTION:
@ -370,8 +370,9 @@ Narcissus.interpreter = (function() {
// FALL THROUGH
case BLOCK:
for (i = 0, j = n.length; i < j; i++)
execute(n[i], x);
c = n.children;
for (i = 0, j = c.length; i < j; i++)
execute(c[i], x);
break;
case IF:
@ -405,7 +406,7 @@ Narcissus.interpreter = (function() {
}
if (u === s) {
for (;;) { // this loop exits switch_loop
if (t.statements.length) {
if (t.statements.children.length) {
try {
execute(t.statements, x);
} catch (e if e === BREAK && x.target === n) {
@ -532,11 +533,12 @@ Narcissus.interpreter = (function() {
case VAR:
case CONST:
for (i = 0, j = n.length; i < j; i++) {
u = n[i].initializer;
c = n.children;
for (i = 0, j = c.length; i < j; i++) {
u = c[i].initializer;
if (!u)
continue;
t = n[i].name;
t = c[i].name;
for (s = x.scope; s; s = s.parent) {
if (hasDirectProperty(s.object, t))
break;
@ -565,16 +567,18 @@ Narcissus.interpreter = (function() {
break;
case COMMA:
for (i = 0, j = n.length; i < j; i++)
v = getValue(execute(n[i], x));
c = n.children;
for (i = 0, j = c.length; i < j; i++)
v = getValue(execute(c[i], x));
break;
case ASSIGN:
r = execute(n[0], x);
c = n.children;
r = execute(c[0], x);
t = n.assignOp;
if (t)
u = getValue(r);
v = getValue(execute(n[1], x));
v = getValue(execute(c[1], x));
if (t) {
switch (t) {
case BITWISE_OR: v = u | v; break;
@ -590,73 +594,89 @@ Narcissus.interpreter = (function() {
case MOD: v = u % v; break;
}
}
putValue(r, v, n[0]);
putValue(r, v, c[0]);
break;
case HOOK:
v = getValue(execute(n[0], x)) ? getValue(execute(n[1], x))
: getValue(execute(n[2], x));
c = n.children;
v = getValue(execute(c[0], x)) ? getValue(execute(c[1], x))
: getValue(execute(c[2], x));
break;
case OR:
v = getValue(execute(n[0], x)) || getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) || getValue(execute(c[1], x));
break;
case AND:
v = getValue(execute(n[0], x)) && getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) && getValue(execute(c[1], x));
break;
case BITWISE_OR:
v = getValue(execute(n[0], x)) | getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) | getValue(execute(c[1], x));
break;
case BITWISE_XOR:
v = getValue(execute(n[0], x)) ^ getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) ^ getValue(execute(c[1], x));
break;
case BITWISE_AND:
v = getValue(execute(n[0], x)) & getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) & getValue(execute(c[1], x));
break;
case EQ:
v = getValue(execute(n[0], x)) == getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) == getValue(execute(c[1], x));
break;
case NE:
v = getValue(execute(n[0], x)) != getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) != getValue(execute(c[1], x));
break;
case STRICT_EQ:
v = getValue(execute(n[0], x)) === getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) === getValue(execute(c[1], x));
break;
case STRICT_NE:
v = getValue(execute(n[0], x)) !== getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) !== getValue(execute(c[1], x));
break;
case LT:
v = getValue(execute(n[0], x)) < getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) < getValue(execute(c[1], x));
break;
case LE:
v = getValue(execute(n[0], x)) <= getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) <= getValue(execute(c[1], x));
break;
case GE:
v = getValue(execute(n[0], x)) >= getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) >= getValue(execute(c[1], x));
break;
case GT:
v = getValue(execute(n[0], x)) > getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) > getValue(execute(c[1], x));
break;
case IN:
v = getValue(execute(n[0], x)) in getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) in getValue(execute(c[1], x));
break;
case INSTANCEOF:
t = getValue(execute(n[0], x));
u = getValue(execute(n[1], x));
c = n.children;
t = getValue(execute(c[0], x));
u = getValue(execute(c[1], x));
if (isObject(u) && typeof u.__hasInstance__ === "function")
v = u.__hasInstance__(t);
else
@ -664,111 +684,122 @@ Narcissus.interpreter = (function() {
break;
case LSH:
v = getValue(execute(n[0], x)) << getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) << getValue(execute(c[1], x));
break;
case RSH:
v = getValue(execute(n[0], x)) >> getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) >> getValue(execute(c[1], x));
break;
case URSH:
v = getValue(execute(n[0], x)) >>> getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) >>> getValue(execute(c[1], x));
break;
case PLUS:
v = getValue(execute(n[0], x)) + getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) + getValue(execute(c[1], x));
break;
case MINUS:
v = getValue(execute(n[0], x)) - getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) - getValue(execute(c[1], x));
break;
case MUL:
v = getValue(execute(n[0], x)) * getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) * getValue(execute(c[1], x));
break;
case DIV:
v = getValue(execute(n[0], x)) / getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) / getValue(execute(c[1], x));
break;
case MOD:
v = getValue(execute(n[0], x)) % getValue(execute(n[1], x));
c = n.children;
v = getValue(execute(c[0], x)) % getValue(execute(c[1], x));
break;
case DELETE:
t = execute(n[0], x);
t = execute(n.children[0], x);
v = !(t instanceof Reference) || delete t.base[t.propertyName];
break;
case VOID:
getValue(execute(n[0], x));
getValue(execute(n.children[0], x));
break;
case TYPEOF:
t = execute(n[0], x);
t = execute(n.children[0], x);
if (t instanceof Reference)
t = t.base ? t.base[t.propertyName] : undefined;
v = typeof t;
break;
case NOT:
v = !getValue(execute(n[0], x));
v = !getValue(execute(n.children[0], x));
break;
case BITWISE_NOT:
v = ~getValue(execute(n[0], x));
v = ~getValue(execute(n.children[0], x));
break;
case UNARY_PLUS:
v = +getValue(execute(n[0], x));
v = +getValue(execute(n.children[0], x));
break;
case UNARY_MINUS:
v = -getValue(execute(n[0], x));
v = -getValue(execute(n.children[0], x));
break;
case INCREMENT:
case DECREMENT:
t = execute(n[0], x);
t = execute(n.children[0], x);
u = Number(getValue(t));
if (n.postfix)
v = u;
putValue(t, (n.type === INCREMENT) ? ++u : --u, n[0]);
putValue(t, (n.type === INCREMENT) ? ++u : --u, n.children[0]);
if (!n.postfix)
v = u;
break;
case DOT:
r = execute(n[0], x);
c = n.children;
r = execute(c[0], x);
t = getValue(r);
u = n[1].value;
v = new Reference(toObject(t, r, n[0]), u, n);
u = c[1].value;
v = new Reference(toObject(t, r, c[0]), u, n);
break;
case INDEX:
r = execute(n[0], x);
c = n.children;
r = execute(c[0], x);
t = getValue(r);
u = getValue(execute(n[1], x));
v = new Reference(toObject(t, r, n[0]), String(u), n);
u = getValue(execute(c[1], x));
v = new Reference(toObject(t, r, c[0]), String(u), n);
break;
case LIST:
// Curse ECMA for specifying that arguments is not an Array object!
v = {};
for (i = 0, j = n.length; i < j; i++) {
u = getValue(execute(n[i], x));
c = n.children;
for (i = 0, j = c.length; i < j; i++) {
u = getValue(execute(c[i], x));
definitions.defineProperty(v, i, u, false, false, true);
}
definitions.defineProperty(v, "length", i, false, false, true);
break;
case CALL:
r = execute(n[0], x);
a = execute(n[1], x);
c = n.children;
r = execute(c[0], x);
a = execute(c[1], x);
f = getValue(r);
if (isPrimitive(f) || typeof f.__call__ !== "function") {
throw new TypeError(r + " is not callable",
n[0].filename, n[0].lineno);
throw new TypeError(r + " is not callable", c[0].filename, c[0].lineno);
}
t = (r instanceof Reference) ? r.base : null;
if (t instanceof Activation)
@ -778,36 +809,39 @@ Narcissus.interpreter = (function() {
case NEW:
case NEW_WITH_ARGS:
r = execute(n[0], x);
c = n.children;
r = execute(c[0], x);
f = getValue(r);
if (n.type === NEW) {
a = {};
definitions.defineProperty(a, "length", 0, false, false, true);
} else {
a = execute(n[1], x);
a = execute(c[1], x);
}
if (isPrimitive(f) || typeof f.__construct__ !== "function") {
throw new TypeError(r + " is not a constructor",
n[0].filename, n[0].lineno);
throw new TypeError(r + " is not a constructor", c[0].filename, c[0].lineno);
}
v = f.__construct__(a, x);
break;
case ARRAY_INIT:
v = [];
for (i = 0, j = n.length; i < j; i++) {
if (n[i])
v[i] = getValue(execute(n[i], x));
c = n.children;
for (i = 0, j = c.length; i < j; i++) {
if (c[i])
v[i] = getValue(execute(c[i], x));
}
v.length = j;
break;
case OBJECT_INIT:
v = {};
for (i = 0, j = n.length; i < j; i++) {
t = n[i];
c = n.children;
for (i = 0, j = c.length; i < j; i++) {
t = c[i];
if (t.type === PROPERTY_INIT) {
v[t[0].value] = getValue(execute(t[1], x));
let c2 = t.children;
v[c2[0].value] = getValue(execute(c2[1], x));
} else {
f = newFunction(t, x);
u = (t.type === GETTER) ? '__defineGetter__'
@ -834,6 +868,9 @@ Narcissus.interpreter = (function() {
break;
case IDENTIFIER:
if (typeof n.resolve !== "function")
throw n;
// Identifiers with forward pointers that weren't intervened can't be
// lvalues, so we safely get the cached value directly.
var resolved = n.resolve();
@ -859,7 +896,7 @@ Narcissus.interpreter = (function() {
break;
case GROUP:
v = execute(n[0], x);
v = execute(n.children[0], x);
break;
default:
@ -1132,6 +1169,22 @@ Narcissus.interpreter = (function() {
print(e.toString());
} catch (e) {
print("internal Narcissus error");
if (typeof e === "object" && e.stack) {
let st = String(e.stack).split(/\n/);
// beautify stack trace:
// - eliminate blank lines
// - sanitize confusing trace lines for getters and js -e expressions
// - simplify source location reporting
// - indent
for (let i = 0; i < st.length; i++) {
let line = st[i].trim();
if (line) {
line = line.replace(/^(\(\))?@/, "<unknown>@");
line = line.replace(/@(.*\/|\\)?([^\/\\]+:[0-9]+)/, " at $2");
print(" in " + line);
}
}
}
throw e;
}
}

Просмотреть файл

@ -657,15 +657,15 @@ Narcissus.parser = (function() {
},
setCondition: function(n, e) {
n[0] = e;
n.children[0] = e;
},
setThenPart: function(n, n2) {
n[1] = n2;
n.children[1] = n2;
},
setElsePart: function(n, n2) {
n[2] = n2;
n.children[2] = n2;
},
finish: function(n) {
@ -906,11 +906,12 @@ Narcissus.parser = (function() {
// Nodes use a tokenizer for debugging (getSource, filename getter).
this.tokenizer = t;
this.children = [];
for (var i = 2; i < arguments.length; i++)
this.push(arguments[i]);
}
var Np = Node.prototype = new Array;
var Np = Node.prototype = {};
Np.constructor = Node;
Np.toSource = Object.prototype.toSource;
@ -923,7 +924,7 @@ Narcissus.parser = (function() {
if (this.end < kid.end)
this.end = kid.end;
}
return Array.prototype.push.call(this, kid);
return this.children.push(kid);
}
Node.indentLevel = 0;
@ -959,6 +960,11 @@ Narcissus.parser = (function() {
return this.tokenizer.filename;
});
definitions.defineGetter(Np, "length",
function() {
throw new Error("Node.prototype.length is gone; use n.children.length instead");
});
definitions.defineProperty(String.prototype, "repeat",
function(n) {
var s = "", t = this + s;
@ -1027,7 +1033,7 @@ Narcissus.parser = (function() {
* Parses a Statement.
*/
function Statement(t, x) {
var i, label, n, n2, ss, tt = t.get(true);
var i, label, n, n2, c, ss, tt = t.get(true);
var builder = x.builder, b, b2, b3;
// Cases for statements ending in a right curly return early, avoiding the
@ -1141,17 +1147,19 @@ Narcissus.parser = (function() {
b.rebuildForIn(n);
b.setObject(n, Expression(t, x));
if (n2.type === VAR || n2.type === LET) {
c = n2.children;
// Destructuring turns one decl into multiples, so either
// there must be only one destructuring or only one
// decl.
if (n2.length !== 1 && n2.destructurings.length !== 1) {
if (c.length !== 1 && n2.destructurings.length !== 1) {
throw new SyntaxError("Invalid for..in left-hand side",
t.filename, n2.lineno);
}
if (n2.destructurings.length > 0) {
b.setIterator(n, n2.destructurings[0], n2, forBlock);
} else {
b.setIterator(n, n2[0], n2, forBlock);
b.setIterator(n, c[0], n2, forBlock);
}
} else {
if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) {
@ -1181,8 +1189,9 @@ Narcissus.parser = (function() {
if (forBlock) {
builder.BLOCK.finish(forBlock);
x.stmtStack.pop();
for (var i = 0, j = forBlock.length; i < j; i++) {
n.body.unshift(forBlock[i]);
c = forBlock.children;
for (var i = 0, j = c.length; i < j; i++) {
n.body.unshift(c[i]);
}
}
return n;
@ -1726,13 +1735,14 @@ Narcissus.parser = (function() {
return;
var lhss = {};
var nn, n2, idx, sub;
for (var i = 0, j = n.length; i < j; i++) {
if (!(nn = n[i]))
var nn, n2, idx, sub, cc, c = n.children;
for (var i = 0, j = c.length; i < j; i++) {
if (!(nn = c[i]))
continue;
if (nn.type === PROPERTY_INIT) {
sub = nn[1];
idx = nn[0].value;
cc = nn.children;
sub = cc[1];
idx = cc[0].value;
} else if (n.type === OBJECT_INIT) {
// Do we have destructuring shorthand {foo, bar}?
sub = nn;
@ -1891,7 +1901,7 @@ Narcissus.parser = (function() {
b.addOperand(n2, n);
n = n2;
do {
n2 = n[n.length-1];
n2 = n.children[n.children.length-1];
if (n2.type === YIELD && !n2.parenthesized)
throw t.newSyntaxError("Yield expression must be parenthesized");
b.addOperand(n, AssignExpression(t, x));
@ -2233,7 +2243,7 @@ Narcissus.parser = (function() {
throw t.newSyntaxError("Yield " + err);
if (t.match(FOR)) {
n2 = GeneratorExpression(t, x, n2);
if (n.length > 1 || t.peek(true) === COMMA)
if (n.children.length > 1 || t.peek(true) === COMMA)
throw t.newSyntaxError("Generator " + err);
}
b.addOperand(n, n2);
@ -2274,9 +2284,9 @@ Narcissus.parser = (function() {
// If we matched exactly one element and got a FOR, we have an
// array comprehension.
if (n.length === 1 && t.match(FOR)) {
if (n.children.length === 1 && t.match(FOR)) {
n2 = bArrayComp.build(t);
bArrayComp.setExpression(n2, n[0]);
bArrayComp.setExpression(n2, n.children[0]);
bArrayComp.setTail(n2, comprehensionTail(t, x));
n = n2;
}
@ -2379,9 +2389,6 @@ Narcissus.parser = (function() {
parse: parse,
Node: Node,
DefaultBuilder: DefaultBuilder,
get SSABuilder() {
throw new Error("SSA builder not yet supported");
},
bindSubBuilders: bindSubBuilders,
DECLARED_FORM: DECLARED_FORM,
EXPRESSED_FORM: EXPRESSED_FORM,

Просмотреть файл

@ -41,7 +41,7 @@
* SSA builder and optimizations.
*/
(function() {
Narcissus.parser.SSABuilder = (function() {
const parser = Narcissus.parser;
const definitions = Narcissus.definitions;
@ -717,7 +717,7 @@
if (allDashes) {
return null;
}
rhs.reverse();
rhs.children.reverse();
e = new Node(ft, ASSIGN);
e.push(lhs);
@ -732,20 +732,21 @@
continue;
}
rhs = e2[1];
rhs = e2.children[1];
// Optimize away phis that are only one branch, but we still need
// to propagate them!
if (branches == 1) {
rhs = rhs[0];
rhs = rhs.children[0];
} else {
// Push a phi use for each operand so the phis can be filled
// in during exec.
for (var i = 0, j = rhs.length; i < j; i++) {
if (rhs[i].type == INTERVENED) {
var rhsc = rhs.children;
for (var i = 0, j = rhsc.length; i < j; i++) {
if (rhsc[i].type == INTERVENED) {
rhs.intervened = true;
}
rhs[i].pushPhiUse(rhs);
rhsc[i].pushPhiUse(rhs);
}
e.push(e2);
}
@ -753,7 +754,7 @@
propagate(x, rhs);
}
return e.length > 0 ? e : null;
return e.children.length > 0 ? e : null;
}
SSAJoin.prototype = {
@ -904,9 +905,10 @@
uu = u[i];
// Phi nodes might have stale branches.
if (uu.type == PHI) {
for (var k = 0, l = uu.length; k < l; k++) {
if (uu[k] === old.def) {
uu[k] = rhs;
var uuc = uu.children;
for (var k = 0, l = uuc.length; k < l; k++) {
if (uuc[k] === old.def) {
uuc[k] = rhs;
rhs.pushPhiUse(uu);
}
}
@ -1279,7 +1281,7 @@
// do.
var bComma = this.COMMA;
e2.push(n.setup[0]);
e2.push(n.setup.children[0]);
n.setup = e2;
var comma = bComma.build(t);
@ -1318,7 +1320,7 @@
this.join = breakJoin.parent;
// Add update to the top if we were a for-in
if (n.type == FOR_IN) {
n.body.unshift(n.update);
n.body.children.unshift(n.update);
n.update = null;
n.type = FOR;
}
@ -1973,7 +1975,7 @@
ASSIGN: {
addOperand: function(n, n2) {
if (n.length == 0) {
if (n.children.length === 0) {
this.binds.inRHS++;
}
@ -1981,15 +1983,16 @@
},
finish: function(n) {
if (n.length == 0) {
if (n.children.length === 0) {
return;
}
var join = this.join;
var binds = this.binds;
var fb = binds.nearestFunction;
var lhs = n[0];
var init = n[1];
var nc = n.children;
var lhs = nc[0];
var init = nc[1];
var upvars = init.upvars || new Upvars;
if (--binds.inRHS > 0) {
@ -2001,7 +2004,7 @@
var t = n.tokenizer;
// Rebuild as COMMA.
n.type = COMMA;
n.length = 0;
n.children = [];
desugarDestructuringAssign(this, n, lhs, init);
return;
}
@ -2053,12 +2056,11 @@
// Transform op= into a normal assignment only if the
// lhs is an identifier we _know_ to be from a var.
var nt = n.tokenizer;
var lhs = n[0];
var n2 = mkRawIdentifier(nt, name, null, true);
this.PRIMARY.finish(n2);
var o = n.assignOp;
n.assignOp = undefined;
n.length = 0;
n.children = [];
n.push(lhs);
n.push(new Node(nt, o, n2, init));
n2.setForward(c.def);
@ -2066,17 +2068,17 @@
}
// Clear the forward pointer and upvars on lefthand side.
if (n[0].forward) {
n[0].forward = null;
n[0].upvars = null;
if (lhs.forward) {
lhs.forward = null;
lhs.upvars = null;
}
// Set local to help decomp to do value numbering.
n[0].local = c.type;
lhs.local = c.type;
// Get the rightmost expression in case of compound
// assignment.
while (init.type == ASSIGN)
init = init[1];
init = init.children[1];
if (join) {
// If the name is not a local let, we need a phi.
@ -2124,21 +2126,21 @@
},
setCondition: function(n, e) {
n[0] = e;
n.children[0] = e;
n.rhsUnionUpvars(e);
this.join = new SSAJoin(this.join, this.binds, false);
},
setThenPart: function(n, n2) {
var join = this.join;
n[1] = n2;
n.children[1] = n2;
n.rhsUnionUpvars(n2);
join.finishBranch();
join.restore(this.binds);
},
setElsePart: function(n, n2) {
n[2] = n2;
n.children[2] = n2;
n.rhsUnionUpvars(n2);
},
@ -2158,7 +2160,7 @@
},
addOperand: function(n, n2) {
if (n.length == 0) {
if (n.children.length == 0) {
// Short circuiting means the right hand expression needs
// to be parsed in a new context.
var join = this.join = new SSAJoin(this.join, this.binds, false);
@ -2186,7 +2188,7 @@
},
addOperand: function(n, n2) {
if (n.length == 0) {
if (n.children.length == 0) {
// Short circuiting means the right hand expression needs
// to be parsed in a new context.
var join = this.join = new SSAJoin(this.join, this.binds, false);
@ -2213,7 +2215,9 @@
var join = this.join;
var binds = this.binds;
if (!(n[0].type == IDENTIFIER && binds.hasCurrent(n[0].value)))
var nc = n.children;
var lhs = nc[0];
if (!(lhs.type == IDENTIFIER && binds.hasCurrent(lhs.value)))
return;
//
@ -2230,7 +2234,7 @@
// effect, so we do not duplicate side effects in an unsafe
// fashion.
//
var name = n[0].value;
var name = lhs.value;
var c = binds.current(name);
// Don't transform vars inside of withs
if (binds.isWith && c.type == VAR)
@ -2255,7 +2259,7 @@
if (n.postfix) {
n.parenthesized = true;
n.type = COMMA;
n.length = 0;
n.children = [];
n.push(mkAssignSimple(this, t, ptmp,
mkIdentifier(this, t, name)));
}
@ -2270,9 +2274,11 @@
n.push(mkIdentifier(this, t, ptmp));
} else {
n.type = ASSIGN;
n.length = 0;
n.push(assign[0]);
n.push(assign[1]);
n.children = [];
var assignc = assign.children;
n.push(assignc[0]);
n.push(assignc[1]);
}
}
},
@ -2296,12 +2302,13 @@
var join = this.join;
var binds = this.binds;
var fb = binds.nearestFunction;
var nc = n.children;
if (--binds.inRHS > 0) {
if (unionOnRight) {
n.upvars = n[1].upvars;
n.upvars = nc[1].upvars;
} else {
n.upvars = n[0].upvars;
n.upvars = nc[0].upvars;
}
}
@ -2357,8 +2364,9 @@
// local ones, so blast away context.
//
var inners = this.binds.inners;
var base = baseOfCall(n[0]);
var target = targetOfCall(n[0], IDENTIFIER);
var call = nc[0];
var base = baseOfCall(call);
var target = targetOfCall(call, IDENTIFIER);
if (target == "eval") {
escapeEval(join, binds);
@ -2454,7 +2462,7 @@
var unionOnRight = n.type == CALL || n.type == NEW_WITH_ARGS ||
n.type == INDEX;
if (unionOnRight) {
escapeVars(join, binds, n[1].upvars || new Upvars);
escapeVars(join, binds, nc[1].upvars || new Upvars);
}
}
},
@ -2581,7 +2589,7 @@
},
finish: function(n) {
n.rhsUnionUpvars(n[1]);
n.rhsUnionUpvars(n.children[1]);
}
},
@ -2837,9 +2845,9 @@
function baseOfCall(n) {
switch (n.type) {
case DOT:
return baseOfCall(n[0]);
return baseOfCall(n.children[0]);
case INDEX:
return baseOfCall(n[0]);
return baseOfCall(n.children[0]);
default:
return n;
}
@ -2850,9 +2858,9 @@
case ident:
return n.value;
case DOT:
return targetOfCall(n[1], IDENTIFIER);
return targetOfCall(n.children[1], IDENTIFIER);
case INDEX:
return targetOfCall(n[1], STRING);
return targetOfCall(n.children[1], STRING);
default:
return null;
}
@ -2948,9 +2956,9 @@
builder.genDestructuringSym(),
e, false);
builder.binds.block.push(decl);
decl[0].setForward(e);
go(n.destructuredNames, decl[0]);
var declc = decl.children[0];
declc[0].setForward(e);
go(n.destructuredNames, declc[0]);
}
function desugarDestructuringInit(builder, n, e) {
@ -2984,8 +2992,9 @@
var dtmp = builder.genDestructuringSym();
var decl = mkDecl(builder, "LET", t, dtmp, e, false);
block.push(decl);
decl[0].setForward(e);
go(ddecls, decl[0]);
var declc = decl.children[0];
declc[0].setForward(e);
go(ddecls, declc[0]);
} else {
// This only happens when we have destructuring for a catch var,
// in which case that catch var already has let-scoping, so we
@ -3139,6 +3148,6 @@
this.phiUses.push(p);
};
parser.SSABuilder = SSABuilder;
return SSABuilder;
}());

Просмотреть файл

@ -254,6 +254,7 @@ INSTALLED_HEADERS += \
avmplus.h \
Fragmento.h \
Native.h \
NativeCommon.h \
Native$(NANOJIT_ARCH).h \
njconfig.h \
RegAlloc.h \
@ -569,11 +570,11 @@ endif
ifdef ENABLE_TRACEJIT
ifndef WINCE
check::
$(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/trace-test/trace-test.py \
$(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/trace-test/trace_test.py \
--no-slow --no-progress --tinderbox $(DIST)/bin/js$(BIN_SUFFIX)
check-valgrind::
$(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/trace-test/trace-test.py \
$(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/trace-test/trace_test.py \
--valgrind --no-slow --no-progress --tinderbox $(DIST)/bin/js$(BIN_SUFFIX)
endif
endif

Просмотреть файл

@ -132,7 +132,7 @@ namespace JSC {
class ARMAssembler {
public:
#ifdef DEBUG
#ifdef JS_METHODJIT_SPEW
bool isOOLPath;
// Assign a default value to keep Valgrind quiet.
ARMAssembler() : isOOLPath(false) { }

Просмотреть файл

@ -67,7 +67,7 @@ public:
// m_code uses m_executablePool, *not* executablePool, since this is no longer valid.
LinkBuffer(MacroAssembler* masm, ExecutablePool* executablePool)
: m_executablePool(executablePool)
, m_code(masm->m_assembler.executableCopy(m_executablePool))
, m_code(executableCopy(*masm, executablePool))
, m_size(masm->m_assembler.size())
#ifndef NDEBUG
, m_completed(false)
@ -75,6 +75,16 @@ public:
{
}
LinkBuffer()
: m_executablePool(NULL)
, m_code(NULL)
, m_size(0)
#ifndef NDEBUG
, m_completed(false)
#endif
{
}
LinkBuffer(uint8* ncode, size_t size)
: m_executablePool(NULL)
, m_code(ncode)
@ -179,7 +189,7 @@ public:
return CodeLocationLabel(code());
}
private:
protected:
// Keep this private! - the underlying code should only be obtained externally via
// finalizeCode() or finalizeCodeAddendum().
void* code()
@ -187,6 +197,11 @@ private:
return m_code;
}
void *executableCopy(MacroAssembler &masm, ExecutablePool *pool)
{
return masm.m_assembler.executableCopy(pool);
}
void performFinalization()
{
#ifndef NDEBUG

Просмотреть файл

@ -307,7 +307,7 @@ private:
class X86InstructionFormatter;
public:
#ifdef DEBUG
#ifdef JS_METHODJIT_SPEW
bool isOOLPath;
#endif
@ -355,7 +355,7 @@ public:
};
X86Assembler()
#ifdef DEBUG
#ifdef JS_METHODJIT_SPEW
: isOOLPath(false)
#endif
{

Просмотреть файл

@ -900,6 +900,8 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
/* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */
#if (WTF_CPU_X86 \
|| WTF_CPU_X86_64 \
|| WTF_CPU_ARM_TRADITIONAL \
|| WTF_CPU_ARM_THUMB2 \
|| WTF_CPU_X86)
#define ENABLE_YARR_JIT 1
#else

Просмотреть файл

@ -4289,6 +4289,7 @@ StructType::ConstructData(JSContext* cx,
if (argc == fields->count()) {
for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
const FieldInfo& field = r.front().value;
STATIC_ASSUME(field.mIndex < fields->count()); /* Quantified invariant */
if (!ImplicitConvert(cx, argv[field.mIndex], field.mType,
buffer + field.mOffset,
false, NULL))
@ -5362,7 +5363,7 @@ CClosure::ClosureStub(ffi_cif* cif, void* result, void** args, void* userData)
for (JSUint32 i = 0; i < cif->nargs; ++i)
argv[i] = JSVAL_VOID;
js::AutoArrayRooter roots(cx, argv.length(), Valueify(argv.begin()));
js::AutoArrayRooter roots(cx, argv.length(), argv.begin());
for (JSUint32 i = 0; i < cif->nargs; ++i) {
// Convert each argument, and have any CData objects created depend on
// the existing buffers.

Просмотреть файл

@ -50,6 +50,7 @@ CPPSRCS = \
tests.cpp \
selfTest.cpp \
testClassGetter.cpp \
testCloneScript.cpp \
testConservativeGC.cpp \
testContexts.cpp \
testDebugger.cpp \
@ -68,6 +69,7 @@ CPPSRCS = \
testSameValue.cpp \
testScriptObject.cpp \
testSetPropertyWithNativeGetterStubSetter.cpp \
testBug604087.cpp \
testTrap.cpp \
testXDR.cpp \
$(NULL)

Просмотреть файл

@ -0,0 +1,84 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99:
*
* Tests JS_TransplantWrappers
*/
#include "tests.h"
#include "jswrapper.h"
struct OuterWrapper : JSWrapper
{
OuterWrapper() : JSWrapper(0) {}
virtual bool isOuterWindow() {
return true;
}
static OuterWrapper singleton;
};
OuterWrapper
OuterWrapper::singleton;
static JSObject *
wrap(JSContext *cx, JSObject *toWrap, JSObject *target)
{
JSAutoEnterCompartment ac;
if (!ac.enter(cx, target))
return NULL;
JSObject *wrapper = toWrap;
if (!JS_WrapObject(cx, &wrapper))
return NULL;
return wrapper;
}
static JSObject *
PreWrap(JSContext *cx, JSObject *scope, JSObject *obj, uintN flags)
{
JS_GC(cx);
return obj;
}
static JSObject *
Wrap(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, uintN flags)
{
return JSWrapper::New(cx, obj, proto, NULL, &JSCrossCompartmentWrapper::singleton);
}
BEGIN_TEST(testBug604087)
{
JSObject *outerObj = JSWrapper::New(cx, global, global->getProto(), global,
&OuterWrapper::singleton);
JSObject *compartment2 = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), NULL);
JSObject *compartment3 = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), NULL);
JSObject *compartment4 = JS_NewCompartmentAndGlobalObject(cx, getGlobalClass(), NULL);
JSObject *c2wrapper = wrap(cx, outerObj, compartment2);
CHECK(c2wrapper);
c2wrapper->setProxyExtra(js::Int32Value(2));
JSObject *c3wrapper = wrap(cx, outerObj, compartment3);
CHECK(c3wrapper);
c3wrapper->setProxyExtra(js::Int32Value(3));
JSObject *c4wrapper = wrap(cx, outerObj, compartment4);
CHECK(c4wrapper);
c4wrapper->setProxyExtra(js::Int32Value(4));
compartment4 = c4wrapper = NULL;
JSObject *next;
{
JSAutoEnterCompartment ac;
CHECK(ac.enter(cx, compartment2));
next = JSWrapper::New(cx, compartment2, compartment2->getProto(), compartment2,
&OuterWrapper::singleton);
CHECK(next);
}
JS_SetWrapObjectCallbacks(JS_GetRuntime(cx), Wrap, PreWrap);
CHECK(JS_TransplantWrapper(cx, outerObj, next));
return true;
}
END_TEST(testBug604087)

Просмотреть файл

@ -0,0 +1,50 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99:
*
* Test script cloning.
*/
#include "tests.h"
#include "jsapi.h"
BEGIN_TEST(test_cloneScript)
{
JSObject *A, *B;
CHECK(A = createGlobal());
CHECK(B = createGlobal());
const char *source =
"var i = 0;\n"
"var sum = 0;\n"
"while (i < 10) {\n"
" sum += i;\n"
" ++i;\n"
"}\n"
"(sum);\n";
JSObject *obj;
// compile for A
{
JSAutoEnterCompartment a;
if (!a.enter(cx, A))
return false;
JSFunction *fun;
CHECK(fun = JS_CompileFunction(cx, A, "f", 0, NULL, source, strlen(source), __FILE__, 1));
CHECK(obj = JS_GetFunctionObject(fun));
}
// clone into B
{
JSAutoEnterCompartment b;
if (!b.enter(cx, B))
return false;
CHECK(JS_CloneFunctionObject(cx, obj, B));
}
return true;
}
END_TEST(test_cloneScript)

Просмотреть файл

@ -52,7 +52,7 @@ bool checkObjectFields(JSObject *savedCopy, JSObject *obj)
* doing memcmp.
*/
savedCopy->objShape = obj->objShape;
savedCopy->dslots = obj->dslots;
savedCopy->slots = obj->slots;
CHECK(!memcmp(savedCopy, obj, sizeof(*obj)));
return true;
}

Просмотреть файл

@ -8,16 +8,19 @@
static int callCount[2] = {0, 0};
static void *
callHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
callCountHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
{
callCount[before]++;
JS_GetFrameThis(cx, fp); // assert if fp is incomplete
jsval thisv;
JS_GetFrameThis(cx, fp, &thisv); // assert if fp is incomplete
return cx; // any non-null value causes the hook to be called again after
}
BEGIN_TEST(testDebugger_bug519719)
{
JS_SetCallHook(rt, callHook, NULL);
JS_SetCallHook(rt, callCountHook, NULL);
EXEC("function call(fn) { fn(0); }\n"
"function f(g) { for (var i = 0; i < 9; i++) call(g); }\n"
"f(Math.sin);\n" // record loop, starting in f
@ -27,3 +30,73 @@ BEGIN_TEST(testDebugger_bug519719)
return true;
}
END_TEST(testDebugger_bug519719)
static void *
nonStrictThisHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
{
if (before) {
bool *allWrapped = (bool *) closure;
jsval thisv;
JS_GetFrameThis(cx, fp, &thisv);
*allWrapped = *allWrapped && !JSVAL_IS_PRIMITIVE(thisv);
}
return NULL;
}
BEGIN_TEST(testDebugger_getThisNonStrict)
{
bool allWrapped = true;
JS_SetCallHook(rt, nonStrictThisHook, (void *) &allWrapped);
EXEC("function nonstrict() { }\n"
"Boolean.prototype.nonstrict = nonstrict;\n"
"String.prototype.nonstrict = nonstrict;\n"
"Number.prototype.nonstrict = nonstrict;\n"
"Object.prototype.nonstrict = nonstrict;\n"
"nonstrict.call(true);\n"
"true.nonstrict();\n"
"nonstrict.call('');\n"
"''.nonstrict();\n"
"nonstrict.call(42);\n"
"(42).nonstrict();\n"
// The below don't really get 'wrapped', but it's okay.
"nonstrict.call(undefined);\n"
"nonstrict.call(null);\n"
"nonstrict.call({});\n"
"({}).nonstrict();\n");
CHECK(allWrapped);
return true;
}
END_TEST(testDebugger_getThisNonStrict)
static void *
strictThisHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
{
if (before) {
bool *anyWrapped = (bool *) closure;
jsval thisv;
JS_GetFrameThis(cx, fp, &thisv);
*anyWrapped = *anyWrapped || !JSVAL_IS_PRIMITIVE(thisv);
}
return NULL;
}
BEGIN_TEST(testDebugger_getThisStrict)
{
bool anyWrapped = false;
JS_SetCallHook(rt, strictThisHook, (void *) &anyWrapped);
EXEC("function strict() { 'use strict'; }\n"
"Boolean.prototype.strict = strict;\n"
"String.prototype.strict = strict;\n"
"Number.prototype.strict = strict;\n"
"strict.call(true);\n"
"true.strict();\n"
"strict.call('');\n"
"''.strict();\n"
"strict.call(42);\n"
"(42).strict();\n"
"strict.call(undefined);\n"
"strict.call(null);\n");
CHECK(!anyWrapped);
return true;
}
END_TEST(testDebugger_getThisStrict)

Просмотреть файл

@ -47,8 +47,8 @@
#include <string.h>
#include "jstypes.h"
#include "jsstdint.h"
#include "jsarena.h" /* Added by JSIFY */
#include "jsutil.h" /* Added by JSIFY */
#include "jsarena.h"
#include "jsutil.h"
#include "jsclist.h"
#include "jsdhash.h"
#include "jsprf.h"
@ -1148,11 +1148,13 @@ JS_SetCompartmentCallback(JSRuntime *rt, JSCompartmentCallback callback)
}
JS_PUBLIC_API(JSWrapObjectCallback)
JS_SetWrapObjectCallback(JSContext *cx, JSWrapObjectCallback callback)
JS_SetWrapObjectCallbacks(JSRuntime *rt,
JSWrapObjectCallback callback,
JSPreWrapCallback precallback)
{
JSRuntime *rt = cx->runtime;
JSWrapObjectCallback old = rt->wrapObjectCallback;
rt->wrapObjectCallback = callback;
rt->preWrapObjectCallback = precallback;
return old;
}
@ -1185,8 +1187,10 @@ bool
JSAutoEnterCompartment::enter(JSContext *cx, JSObject *target)
{
JS_ASSERT(!call);
if (cx->compartment == target->getCompartment(cx))
if (cx->compartment == target->getCompartment()) {
call = reinterpret_cast<JSCrossCompartmentCall*>(1);
return true;
}
call = JS_EnterCrossCompartmentCall(cx, target);
return call != NULL;
}
@ -1227,6 +1231,100 @@ JS_WrapValue(JSContext *cx, jsval *vp)
return cx->compartment->wrap(cx, Valueify(vp));
}
JS_PUBLIC_API(JSObject *)
JS_TransplantWrapper(JSContext *cx, JSObject *wrapper, JSObject *target)
{
JS_ASSERT(wrapper->isWrapper());
/*
* This function is called when a window is navigating. In that case, we
* need to "move" the window from wrapper's compartment to target's
* compartment.
*/
JSCompartment *destination = target->getCompartment();
if (wrapper->getCompartment() == destination) {
// If the wrapper is in the same compartment as the destination, then
// we know that we won't find wrapper in the destination's cross
// compartment map and that the same object will continue to work.
if (!wrapper->swap(cx, target))
return NULL;
return wrapper;
}
JSObject *obj;
WrapperMap &map = destination->crossCompartmentWrappers;
Value wrapperv = ObjectValue(*wrapper);
// There might already be a wrapper for the window in the new compartment.
if (WrapperMap::Ptr p = map.lookup(wrapperv)) {
// If there is, make it the primary outer window proxy around the
// inner (accomplished by swapping target's innards with the old,
// possibly security wrapper, innards).
obj = &p->value.toObject();
map.remove(p);
if (!obj->swap(cx, target))
return NULL;
} else {
// Otherwise, this is going to be our outer window proxy in the new
// compartment.
obj = target;
}
// Now, iterate through other scopes looking for references to the old
// outer window. They need to be updated to point at the new outer window.
// They also might transition between different types of security wrappers
// based on whether the new compartment is same origin with them.
Value targetv = ObjectValue(*obj);
WrapperVector &vector = cx->runtime->compartments;
AutoValueVector toTransplant(cx);
toTransplant.reserve(vector.length());
for (JSCompartment **p = vector.begin(), **end = vector.end(); p != end; ++p) {
WrapperMap &pmap = (*p)->crossCompartmentWrappers;
if (WrapperMap::Ptr wp = pmap.lookup(wrapperv)) {
// We found a wrapper. Remember and root it.
toTransplant.append(wp->value);
}
}
for (Value *begin = toTransplant.begin(), *end = toTransplant.end(); begin != end; ++begin) {
JSObject *wobj = &begin->toObject();
JSCompartment *wcompartment = wobj->compartment();
WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
JS_ASSERT(pmap.lookup(wrapperv));
pmap.remove(wrapperv);
// First, we wrap it in the new compartment. This will return a
// new wrapper.
AutoCompartment ac(cx, wobj);
JSObject *tobj = obj;
if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
return NULL;
// Now, because we need to maintain object identity, we do a brain
// transplant on the old object. At the same time, we update the
// entry in the compartment's wrapper map to point to the old
// wrapper.
JS_ASSERT(tobj != wobj);
if (!wobj->swap(cx, tobj))
return NULL;
pmap.put(targetv, ObjectValue(*wobj));
}
// Lastly, update the old outer window proxy to point to the new one.
{
AutoCompartment ac(cx, wrapper);
JSObject *tobj = obj;
if (!ac.enter() || !JS_WrapObject(cx, &tobj))
return NULL;
if (!wrapper->swap(cx, tobj))
return NULL;
wrapper->getCompartment()->crossCompartmentWrappers.put(targetv, wrapperv);
}
return obj;
}
JS_PUBLIC_API(JSObject *)
JS_GetGlobalObject(JSContext *cx)
{
@ -1239,8 +1337,8 @@ JS_SetGlobalObject(JSContext *cx, JSObject *obj)
CHECK_REQUEST(cx);
cx->globalObject = obj;
if (!cx->maybefp())
cx->compartment = obj ? obj->getCompartment(cx) : cx->runtime->defaultCompartment;
if (!cx->hasfp())
cx->resetCompartment();
}
class AutoResolvingEntry {
@ -1277,6 +1375,7 @@ private:
JSObject *
js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
JSObject *fun_proto, *obj_proto;
/* If cx has no global object, use obj so prototypes can be found. */
@ -1327,6 +1426,7 @@ js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
JS_PUBLIC_API(JSBool)
JS_InitStandardClasses(JSContext *cx, JSObject *obj)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
/*
@ -2814,14 +2914,12 @@ JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
JS_PUBLIC_API(void *)
JS_GetPrivate(JSContext *cx, JSObject *obj)
{
assertSameCompartment(cx, obj);
return obj->getPrivate();
}
JS_PUBLIC_API(JSBool)
JS_SetPrivate(JSContext *cx, JSObject *obj, void *data)
{
assertSameCompartment(cx, obj);
obj->setPrivate(data);
return true;
}
@ -2908,16 +3006,14 @@ JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
JS_PUBLIC_API(JSObject *)
JS_NewGlobalObject(JSContext *cx, JSClass *clasp)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
JSObject *obj = NewNonFunction<WithProto::Given>(cx, Valueify(clasp), NULL, NULL);
if (!obj ||
!js_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_COMPARTMENT,
PrivateValue(cx->compartment))) {
if (!obj)
return NULL;
}
/* FIXME: comment. */
/* Construct a regexp statics object for this global object. */
JSObject *res = regexp_statics_construct(cx);
if (!res ||
!js_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_REGEXP_STATICS,
@ -2947,6 +3043,7 @@ JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *pr
JS_PUBLIC_API(JSObject *)
JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, proto, parent);
@ -2966,6 +3063,7 @@ JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
JS_PUBLIC_API(JSObject *)
JS_NewObjectWithGivenProto(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, proto, parent);
@ -2985,7 +3083,7 @@ JS_NewObjectForConstructor(JSContext *cx, const jsval *vp)
CHECK_REQUEST(cx);
assertSameCompartment(cx, *vp);
return js_NewInstance(cx, JSVAL_TO_OBJECT(*vp));
return js_CreateThis(cx, JSVAL_TO_OBJECT(*vp));
}
JS_PUBLIC_API(JSBool)
@ -3019,8 +3117,6 @@ JS_DeepFreezeObject(JSContext *cx, JSObject *obj)
/* Walk slots in obj and if any value is a non-null object, seal it. */
for (uint32 i = 0, n = obj->slotSpan(); i < n; ++i) {
const Value &v = obj->getSlot(i);
if (i == JSSLOT_PRIVATE && (obj->getClass()->flags & JSCLASS_HAS_PRIVATE))
continue;
if (v.isPrimitive())
continue;
if (!JS_DeepFreezeObject(cx, &v.toObject()))
@ -3526,8 +3622,8 @@ GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
if (obj2->isProxy()) {
JSAutoResolveFlags rf(cx, flags);
return own
? JSProxy::getOwnPropertyDescriptor(cx, obj2, id, desc)
: JSProxy::getPropertyDescriptor(cx, obj2, id, desc);
? JSProxy::getOwnPropertyDescriptor(cx, obj2, id, false, desc)
: JSProxy::getPropertyDescriptor(cx, obj2, id, false, desc);
}
if (!obj2->getAttributes(cx, id, &desc->attrs))
return false;
@ -3820,8 +3916,7 @@ JS_Enumerate(JSContext *cx, JSObject *obj)
* + native case here uses a Shape *, but that iterates in reverse!
* + so we make non-native match, by reverse-iterating after JS_Enumerating
*/
const uint32 JSSLOT_ITER_INDEX = JSSLOT_PRIVATE + 1;
JS_STATIC_ASSERT(JSSLOT_ITER_INDEX < JS_INITIAL_NSLOTS);
const uint32 JSSLOT_ITER_INDEX = 0;
static void
prop_iter_finalize(JSContext *cx, JSObject *obj)
@ -3830,7 +3925,7 @@ prop_iter_finalize(JSContext *cx, JSObject *obj)
if (!pdata)
return;
if (obj->fslots[JSSLOT_ITER_INDEX].toInt32() >= 0) {
if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() >= 0) {
/* Non-native case: destroy the ida enumerated when obj was created. */
JSIdArray *ida = (JSIdArray *) pdata;
JS_DestroyIdArray(cx, ida);
@ -3844,7 +3939,7 @@ prop_iter_trace(JSTracer *trc, JSObject *obj)
if (!pdata)
return;
if (obj->fslots[JSSLOT_ITER_INDEX].toInt32() < 0) {
if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() < 0) {
/* Native case: just mark the next property to visit. */
((Shape *) pdata)->trace(trc);
} else {
@ -3910,7 +4005,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
/* iterobj cannot escape to other threads here. */
iterobj->setPrivate(const_cast<void *>(pdata));
iterobj->fslots[JSSLOT_ITER_INDEX].setInt32(index);
iterobj->getSlotRef(JSSLOT_ITER_INDEX).setInt32(index);
return iterobj;
}
@ -3924,7 +4019,7 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
CHECK_REQUEST(cx);
assertSameCompartment(cx, iterobj);
i = iterobj->fslots[JSSLOT_ITER_INDEX].toInt32();
i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
if (i < 0) {
/* Native case: private data is a property tree node pointer. */
obj = iterobj->getParent();
@ -3950,6 +4045,7 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
/* Non-native case: use the ida enumerated when iterobj was created. */
ida = (JSIdArray *) iterobj->getPrivate();
JS_ASSERT(i <= ida->length);
STATIC_ASSUME(i <= ida->length);
if (i == 0) {
*idp = JSID_VOID;
} else {
@ -3979,6 +4075,7 @@ JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
JS_PUBLIC_API(JSObject *)
JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
/* NB: jsuint cast does ToUint32. */
assertSameCompartment(cx, JSValueArray(vector, vector ? (jsuint)length : 0));
@ -4080,6 +4177,7 @@ JS_PUBLIC_API(JSFunction *)
JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
JSObject *parent, const char *name)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
JSAtom *atom;
CHECK_REQUEST(cx);
@ -4255,6 +4353,7 @@ js_generic_native_method_dispatcher(JSContext *cx, uintN argc, Value *vp)
JS_PUBLIC_API(JSBool)
JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
uintN flags;
JSObject *ctor;
JSFunction *fun;
@ -4304,6 +4403,7 @@ JS_PUBLIC_API(JSFunction *)
JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
uintN nargs, uintN attrs)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
@ -4315,6 +4415,7 @@ JS_DefineUCFunction(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen, JSNative call,
uintN nargs, uintN attrs)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
@ -4359,6 +4460,7 @@ JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *prin
const jschar *chars, size_t length,
const char *filename, uintN lineno)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, principals);
@ -4377,6 +4479,7 @@ JS_PUBLIC_API(JSScript *)
JS_CompileUCScript(JSContext *cx, JSObject *obj, const jschar *chars, size_t length,
const char *filename, uintN lineno)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length, filename, lineno);
}
@ -4386,6 +4489,7 @@ JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
const char *bytes, size_t length,
const char *filename, uintN lineno)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
jschar *chars = js_InflateString(cx, bytes, &length);
@ -4400,6 +4504,7 @@ JS_PUBLIC_API(JSScript *)
JS_CompileScript(JSContext *cx, JSObject *obj, const char *bytes, size_t length,
const char *filename, uintN lineno)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
return JS_CompileScriptForPrincipals(cx, obj, NULL, bytes, length, filename, lineno);
}
@ -4447,6 +4552,7 @@ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, const char *bytes, size_
JS_PUBLIC_API(JSScript *)
JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
FILE *fp;
uint32 tcflags;
JSScript *script;
@ -4481,6 +4587,7 @@ JS_PUBLIC_API(JSScript *)
JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj, const char *filename, FILE *file,
JSPrincipals *principals)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
uint32 tcflags;
JSScript *script;
@ -4500,12 +4607,14 @@ JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj, const char *file
JS_PUBLIC_API(JSScript *)
JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename, FILE *file)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
}
JS_PUBLIC_API(JSObject *)
JS_NewScriptObject(JSContext *cx, JSScript *script)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, script);
if (!script)
@ -4517,6 +4626,7 @@ JS_NewScriptObject(JSContext *cx, JSScript *script)
* described in the comment for JSScript::u.object.
*/
JS_ASSERT(script->u.object);
JS_ASSERT(script != JSScript::emptyScript());
return script->u.object;
}
@ -4569,6 +4679,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
const jschar *chars, size_t length,
const char *filename, uintN lineno)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
JSFunction *fun;
JSAtom *funAtom, *argAtom;
uintN i;
@ -4639,6 +4750,7 @@ JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
const jschar *chars, size_t length,
const char *filename, uintN lineno)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name, nargs, argnames,
chars, length, filename, lineno);
}
@ -4650,6 +4762,7 @@ JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
const char *bytes, size_t length,
const char *filename, uintN lineno)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
jschar *chars = js_InflateString(cx, bytes, &length);
if (!chars)
return NULL;
@ -4666,6 +4779,7 @@ JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
const char *bytes, size_t length,
const char *filename, uintN lineno)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
return JS_CompileFunctionForPrincipals(cx, obj, NULL, name, nargs, argnames, bytes, length,
filename, lineno);
}
@ -4673,6 +4787,7 @@ JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
JS_PUBLIC_API(JSString *)
JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, uintN indent)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
JSPrinter *jp;
JSString *str;
@ -4695,6 +4810,7 @@ JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, uintN inde
JS_PUBLIC_API(JSString *)
JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, fun);
return js_DecompileToString(cx, "JS_DecompileFunction", fun,
@ -4706,6 +4822,7 @@ JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
JS_PUBLIC_API(JSString *)
JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, fun);
return js_DecompileToString(cx, "JS_DecompileFunctionBody", fun,
@ -4717,6 +4834,7 @@ JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
JS_PUBLIC_API(JSBool)
JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
JSBool ok;
CHECK_REQUEST(cx);
@ -4747,6 +4865,7 @@ JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
const char *filename, uintN lineno,
jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
JSScript *script;
JSBool ok;
@ -4770,6 +4889,7 @@ JS_PUBLIC_API(JSBool)
JS_EvaluateUCScript(JSContext *cx, JSObject *obj, const jschar *chars, uintN length,
const char *filename, uintN lineno, jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length, filename, lineno, rval);
}
@ -4779,6 +4899,7 @@ JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *princ
const char *bytes, uintN nbytes,
const char *filename, uintN lineno, jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
size_t length = nbytes;
jschar *chars = js_InflateString(cx, bytes, &length);
if (!chars)
@ -4793,6 +4914,7 @@ JS_PUBLIC_API(JSBool)
JS_EvaluateScript(JSContext *cx, JSObject *obj, const char *bytes, uintN nbytes,
const char *filename, uintN lineno, jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
return JS_EvaluateScriptForPrincipals(cx, obj, NULL, bytes, nbytes, filename, lineno, rval);
}
@ -4800,6 +4922,7 @@ JS_PUBLIC_API(JSBool)
JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc, jsval *argv,
jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
JSBool ok;
CHECK_REQUEST(cx);
@ -4813,6 +4936,7 @@ JS_PUBLIC_API(JSBool)
JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc, jsval *argv,
jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, JSValueArray(argv, argc));
@ -4829,6 +4953,7 @@ JS_PUBLIC_API(JSBool)
JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc, jsval *argv,
jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment);
JSBool ok;
CHECK_REQUEST(cx);
@ -4838,6 +4963,22 @@ JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc, jsval
return ok;
}
namespace JS {
JS_PUBLIC_API(bool)
Call(JSContext *cx, jsval thisv, jsval fval, uintN argc, jsval *argv, jsval *rval)
{
JSBool ok;
CHECK_REQUEST(cx);
assertSameCompartment(cx, thisv, fval, JSValueArray(argv, argc));
ok = ExternalInvoke(cx, Valueify(thisv), Valueify(fval), argc, Valueify(argv), Valueify(rval));
LAST_FRAME_CHECKS(cx, ok);
return ok;
}
} // namespace JS
JS_PUBLIC_API(JSObject *)
JS_New(JSContext *cx, JSObject *ctor, uintN argc, jsval *argv)
{
@ -4939,6 +5080,7 @@ JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp)
if (!fp)
return;
cx->restoreSegment();
cx->resetCompartment();
}
/************************************************************************/
@ -5272,7 +5414,7 @@ JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *
}
JS_PUBLIC_API(JSBool)
JS_ReadPair(JSStructuredCloneReader *r, uint32 *p1, uint32 *p2)
JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32 *p1, uint32 *p2)
{
return r->input().readPair((uint32_t *) p1, (uint32_t *) p2);
}
@ -5284,7 +5426,7 @@ JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len)
}
JS_PUBLIC_API(JSBool)
JS_WritePair(JSStructuredCloneWriter *w, uint32 tag, uint32 data)
JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32 tag, uint32 data)
{
return w->output().writePair(tag, data);
}

Просмотреть файл

@ -334,6 +334,7 @@ static JS_ALWAYS_INLINE jsid
INTERNED_STRING_TO_JSID(JSString *str)
{
jsid id;
JS_ASSERT(str);
JS_ASSERT(JS_StringHasBeenInterned(str));
JS_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0);
JSID_BITS(id) = (size_t)str;
@ -491,13 +492,7 @@ extern JS_PUBLIC_DATA(jsid) JSID_EMPTY;
#define JSFUN_HEAVYWEIGHT_TEST(f) ((f) & JSFUN_HEAVYWEIGHT)
#define JSFUN_THISP_FLAGS(f) (f)
#define JSFUN_THISP_TEST(f,t) ((f) & t)
#define JSFUN_THISP_STRING 0x0100 /* |this| may be a primitive string */
#define JSFUN_THISP_NUMBER 0x0200 /* |this| may be a primitive number */
#define JSFUN_THISP_BOOLEAN 0x0400 /* |this| may be a primitive boolean */
#define JSFUN_THISP_PRIMITIVE 0x0700 /* |this| may be any primitive value */
#define JSFUN_PRIMITIVE_THIS 0x0100 /* |this| may be a primitive value */
#define JSFUN_FLAGS_MASK 0x07fa /* overlay JSFUN_* attributes --
bits 12-15 are used internally to
@ -937,7 +932,9 @@ extern JS_PUBLIC_API(JSCompartmentCallback)
JS_SetCompartmentCallback(JSRuntime *rt, JSCompartmentCallback callback);
extern JS_PUBLIC_API(JSWrapObjectCallback)
JS_SetWrapObjectCallback(JSContext *cx, JSWrapObjectCallback callback);
JS_SetWrapObjectCallbacks(JSRuntime *rt,
JSWrapObjectCallback callback,
JSPreWrapCallback precallback);
extern JS_PUBLIC_API(JSCrossCompartmentCall *)
JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target);
@ -957,6 +954,9 @@ JS_WrapObject(JSContext *cx, JSObject **objp);
extern JS_PUBLIC_API(JSBool)
JS_WrapValue(JSContext *cx, jsval *vp);
extern JS_PUBLIC_API(JSObject *)
JS_TransplantWrapper(JSContext *cx, JSObject *wrapper, JSObject *target);
#ifdef __cplusplus
JS_END_EXTERN_C
@ -974,7 +974,7 @@ class JS_PUBLIC_API(JSAutoEnterCompartment)
bool entered() const { return call != NULL; }
~JSAutoEnterCompartment() {
if (call)
if (call && call != reinterpret_cast<JSCrossCompartmentCall*>(1))
JS_LeaveCrossCompartmentCall(call);
}
@ -1718,9 +1718,8 @@ struct JSClass {
#define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
/* Additional global reserved slots, beyond those for standard prototypes. */
#define JSRESERVED_GLOBAL_SLOTS_COUNT 4
#define JSRESERVED_GLOBAL_COMPARTMENT (JSProto_LIMIT * 3)
#define JSRESERVED_GLOBAL_THIS (JSRESERVED_GLOBAL_COMPARTMENT + 1)
#define JSRESERVED_GLOBAL_SLOTS_COUNT 3
#define JSRESERVED_GLOBAL_THIS (JSProto_LIMIT * 3)
#define JSRESERVED_GLOBAL_THROWTYPEERROR (JSRESERVED_GLOBAL_THIS + 1)
#define JSRESERVED_GLOBAL_REGEXP_STATICS (JSRESERVED_GLOBAL_THROWTYPEERROR + 1)
@ -2595,6 +2594,39 @@ extern JS_PUBLIC_API(JSBool)
JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
jsval *argv, jsval *rval);
#ifdef __cplusplus
JS_END_EXTERN_C
namespace JS {
static inline bool
Call(JSContext *cx, JSObject *thisObj, JSFunction *fun, uintN argc, jsval *argv, jsval *rval) {
return !!JS_CallFunction(cx, thisObj, fun, argc, argv, rval);
}
static inline bool
Call(JSContext *cx, JSObject *thisObj, const char *name, uintN argc, jsval *argv, jsval *rval) {
return !!JS_CallFunctionName(cx, thisObj, name, argc, argv, rval);
}
static inline bool
Call(JSContext *cx, JSObject *thisObj, jsval fun, uintN argc, jsval *argv, jsval *rval) {
return !!JS_CallFunctionValue(cx, thisObj, fun, argc, argv, rval);
}
extern JS_PUBLIC_API(bool)
Call(JSContext *cx, jsval thisv, jsval fun, uintN argc, jsval *argv, jsval *rval);
static inline bool
Call(JSContext *cx, jsval thisv, JSObject *funObj, uintN argc, jsval *argv, jsval *rval) {
return Call(cx, thisv, OBJECT_TO_JSVAL(funObj), argc, argv, rval);
}
} // namespace JS
JS_BEGIN_EXTERN_C
#endif // __cplusplus
/*
* These functions allow setting an operation callback that will be called
* from the thread the context is associated with some time after any thread
@ -2937,13 +2969,13 @@ JS_PUBLIC_API(void)
JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *callbacks);
JS_PUBLIC_API(JSBool)
JS_ReadPair(JSStructuredCloneReader *r, uint32 *p1, uint32 *p2);
JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32 *p1, uint32 *p2);
JS_PUBLIC_API(JSBool)
JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len);
JS_PUBLIC_API(JSBool)
JS_WritePair(JSStructuredCloneWriter *w, uint32 tag, uint32 data);
JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32 tag, uint32 data);
JS_PUBLIC_API(JSBool)
JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len);

Просмотреть файл

@ -47,8 +47,8 @@
#include "jstypes.h"
#include "jsstdint.h"
#include "jsbit.h"
#include "jsarena.h" /* Added by JSIFY */
#include "jsutil.h" /* Added by JSIFY */
#include "jsarena.h"
#include "jsprvtd.h"
#ifdef JS_ARENAMETER
static JSArenaStats *arena_stats_list;

Просмотреть файл

@ -126,6 +126,7 @@ struct JSArenaPool {
else \
_a->avail = _p + _nb; \
p = (type) _p; \
STATIC_ASSUME(!p || ubound((char *)p) >= nb) \
JS_ArenaCountAllocation(pool, nb); \
JS_END_MACRO
@ -149,6 +150,7 @@ struct JSArenaPool {
} else { \
p = (type) JS_ArenaGrow(pool, p, size, incr); \
} \
STATIC_ASSUME(!p || ubound((char *)p) >= size + incr); \
JS_ArenaCountGrowth(pool, size, incr); \
JS_END_MACRO

Просмотреть файл

@ -79,7 +79,7 @@
#include <string.h>
#include "jstypes.h"
#include "jsstdint.h"
#include "jsutil.h" /* Added by JSIFY */
#include "jsutil.h"
#include "jsapi.h"
#include "jsarray.h"
#include "jsatom.h"
@ -103,8 +103,9 @@
#include "jsvector.h"
#include "jsatominlines.h"
#include "jsobjinlines.h"
#include "jscntxtinlines.h"
#include "jsinterpinlines.h"
#include "jsobjinlines.h"
using namespace js;
using namespace js::gc;
@ -311,109 +312,6 @@ BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom,
return JS_TRUE;
}
bool
JSObject::growDenseArrayElements(JSContext *cx, uint32 oldcap, uint32 newcap)
{
JS_ASSERT(isDenseArray());
JS_ASSERT(newcap >= ARRAY_CAPACITY_MIN);
JS_ASSERT(newcap >= oldcap);
if (newcap > MAX_DSLOTS_LENGTH32) {
if (!JS_ON_TRACE(cx))
js_ReportAllocationOverflow(cx);
return JS_FALSE;
}
/* dslots can be NULL during array creation. */
Value *slots = dslots ? dslots - 1 : NULL;
Value *newslots = (Value *) cx->realloc(slots, (size_t(newcap) + 1) * sizeof(Value));
if (!newslots)
return false;
dslots = newslots + 1;
setDenseArrayCapacity(newcap);
Value *base = addressOfDenseArrayElement(0);
for (Value *vp = base + oldcap, *end = base + newcap; vp < end; ++vp)
vp->setMagic(JS_ARRAY_HOLE);
return true;
}
bool
JSObject::ensureDenseArrayElements(JSContext *cx, uint32 newcap)
{
/*
* When a dense array with CAPACITY_DOUBLING_MAX or fewer slots needs to
* grow, double its capacity, to push() N elements in amortized O(N) time.
*
* Above this limit, grow by 12.5% each time. Speed is still amortized
* O(N), with a higher constant factor, and we waste less space.
*/
static const size_t CAPACITY_DOUBLING_MAX = 1024 * 1024;
/*
* Round up all large allocations to a multiple of this (1MB), so as not
* to waste space if malloc gives us 1MB-sized chunks (as jemalloc does).
*/
static const size_t CAPACITY_CHUNK = 1024 * 1024 / sizeof(Value);
uint32 oldcap = getDenseArrayCapacity();
if (newcap > oldcap) {
/*
* If this overflows uint32, newcap is very large. nextsize will end
* up being less than newcap, the code below will thus disregard it,
* and resizeDenseArrayElements() will fail.
*
* The way we use dslots[-1] forces a few +1s and -1s here. For
* example, (oldcap * 2 + 1) produces the sequence 7, 15, 31, 63, ...
* which makes the total allocation size (with dslots[-1]) a power
* of two.
*/
uint32 nextsize = (oldcap <= CAPACITY_DOUBLING_MAX)
? oldcap * 2 + 1
: oldcap + (oldcap >> 3);
uint32 actualCapacity = JS_MAX(newcap, nextsize);
if (actualCapacity >= CAPACITY_CHUNK)
actualCapacity = JS_ROUNDUP(actualCapacity + 1, CAPACITY_CHUNK) - 1; /* -1 for dslots[-1] */
else if (actualCapacity < ARRAY_CAPACITY_MIN)
actualCapacity = ARRAY_CAPACITY_MIN;
if (!growDenseArrayElements(cx, oldcap, actualCapacity))
return false;
}
return true;
}
bool
JSObject::shrinkDenseArrayElements(JSContext *cx, uint32 newcap)
{
JS_ASSERT(isDenseArray());
JS_ASSERT(newcap < getDenseArrayCapacity());
JS_ASSERT(dslots);
uint32 fill = newcap;
if (newcap < ARRAY_CAPACITY_MIN)
newcap = ARRAY_CAPACITY_MIN;
Value *newslots = (Value *) cx->realloc(dslots - 1, (size_t(newcap) + 1) * sizeof(Value));
if (!newslots)
return false;
dslots = newslots + 1;
setDenseArrayCapacity(newcap);
/* we refuse to shrink below a minimum value, so we have to clear the excess space */
Value *base = addressOfDenseArrayElement(0);
while (fill < newcap)
base[fill++].setMagic(JS_ARRAY_HOLE);
return true;
}
static bool
ReallyBigIndexToId(JSContext* cx, jsdouble index, jsid* idp)
{
@ -456,6 +354,17 @@ GetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, JSBool *hole,
*hole = JS_FALSE;
return JS_TRUE;
}
if (obj->isArguments() &&
index < obj->getArgsInitialLength() &&
!(*vp = obj->getArgsElement(uint32(index))).isMagic(JS_ARRAY_HOLE)) {
*hole = JS_FALSE;
JSStackFrame *fp = (JSStackFrame *)obj->getPrivate();
if (fp != JS_ARGUMENTS_OBJECT_ON_TRACE) {
if (fp)
*vp = fp->canonicalActualArg(index);
return JS_TRUE;
}
}
AutoIdRooter idr(cx);
@ -530,8 +439,8 @@ js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i)
return true;
if (INDEX_TOO_SPARSE(obj, u))
return false;
return obj->ensureDenseArrayElements(cx, u + 1);
return obj->ensureDenseArrayElements(cx, u + 1);
}
JS_DEFINE_CALLINFO_3(extern, BOOL, js_EnsureDenseArrayCapacity, CONTEXT, OBJECT, INT32, 0,
nanojit::ACCSET_STORE_ANY)
@ -660,13 +569,13 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool str
if (obj->isDenseArray()) {
/*
* Don't reallocate if we're not actually shrinking our slots. If we do
* shrink slots here, resizeDenseArrayElements will fill all slots to the
* shrink slots here, ensureDenseArrayElements will fill all slots to the
* right of newlen with JS_ARRAY_HOLE. This permits us to disregard
* length when reading from arrays as long we are within the capacity.
*/
jsuint oldcap = obj->getDenseArrayCapacity();
if (oldcap > newlen && !obj->shrinkDenseArrayElements(cx, newlen))
return false;
if (oldcap > newlen)
obj->shrinkDenseArrayElements(cx, newlen);
obj->setArrayLength(newlen);
} else if (oldlen - newlen < (1 << 24)) {
do {
@ -974,20 +883,11 @@ array_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool
return JS_TRUE;
}
static void
array_finalize(JSContext *cx, JSObject *obj)
{
obj->freeDenseArrayElements(cx);
}
static void
array_trace(JSTracer *trc, JSObject *obj)
{
JS_ASSERT(obj->isDenseArray());
if (!obj->dslots)
return;
size_t holes = 0;
uint32 capacity = obj->getDenseArrayCapacity();
for (uint32 i = 0; i < capacity; i++) {
@ -1028,7 +928,7 @@ array_fix(JSContext *cx, JSObject *obj, bool *success, AutoIdVector *props)
Class js_ArrayClass = {
"Array",
Class::NON_NATIVE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::DENSE_ARRAY_CLASS_RESERVED_SLOTS) |
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
PropertyStub, /* addProperty */
PropertyStub, /* delProperty */
@ -1037,7 +937,7 @@ Class js_ArrayClass = {
EnumerateStub,
ResolveStub,
js_TryValueOf,
array_finalize,
NULL,
NULL, /* reserved0 */
NULL, /* checkAccess */
NULL, /* call */
@ -1122,26 +1022,18 @@ JSObject::makeDenseArraySlow(JSContext *cx)
* the same initial shape.
*/
JSObject *arrayProto = getProto();
if (!InitScopeForObject(cx, this, &js_SlowArrayClass, arrayProto))
if (!InitScopeForObject(cx, this, &js_SlowArrayClass, arrayProto, FINALIZE_OBJECT0))
return false;
uint32 capacity;
uint32 capacity = getDenseArrayCapacity();
if (dslots) {
capacity = getDenseArrayCapacity();
dslots[-1].setPrivateUint32(JS_INITIAL_NSLOTS + capacity);
} else {
/*
* Array.prototype is constructed as a dense array, but is immediately slowified before
* we have time to set capacity.
*/
capacity = 0;
}
/* Begin with the length property to share more of the property tree. */
/*
* Begin with the length property to share more of the property tree.
* The getter/setter here will directly access the object's private value.
*/
if (!addProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),
array_length_getter, NULL,
JSSLOT_ARRAY_LENGTH, JSPROP_PERMANENT | JSPROP_SHARED, 0, 0)) {
SHAPE_INVALID_SLOT, JSPROP_PERMANENT | JSPROP_SHARED, 0, 0)) {
setMap(oldMap);
return false;
}
@ -1159,24 +1051,12 @@ JSObject::makeDenseArraySlow(JSContext *cx)
continue;
}
/* Assert that the length covering i fits in the alloted bits. */
JS_ASSERT(JS_INITIAL_NSLOTS + i + 1 < NSLOTS_LIMIT);
if (!addDataProperty(cx, id, JS_INITIAL_NSLOTS + i, JSPROP_ENUMERATE)) {
if (!addDataProperty(cx, id, i, JSPROP_ENUMERATE)) {
setMap(oldMap);
return false;
}
}
/*
* Render our formerly-reserved non-private properties GC-safe. We do not
* need to make the length slot GC-safe because it is the private slot
* (this is statically asserted within JSObject) where the implementation
* can store an arbitrary value.
*/
JS_ASSERT(js_SlowArrayClass.flags & JSCLASS_HAS_PRIVATE);
voidDenseOnlyArraySlots();
/*
* Finally, update class. If |this| is Array.prototype, then js_InitClass
* will create an emptyShape whose class is &js_SlowArrayClass, to ensure
@ -1518,7 +1398,6 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, const Value *vector
JS_ASSERT(obj->isDenseArray());
obj->setArrayLength(length);
obj->setDenseArrayCapacity(0);
if (!vector || !length)
return true;
if (!obj->ensureDenseArrayElements(cx, length))
@ -1754,12 +1633,11 @@ js_MergeSort(void *src, size_t nel, size_t elsize,
struct CompareArgs
{
JSContext *context;
Value fval;
InvokeArgsGuard args;
JSContext *context;
InvokeSessionGuard session;
CompareArgs(JSContext *cx, const Value &fval)
: context(cx), fval(fval)
CompareArgs(JSContext *cx)
: context(cx)
{}
};
@ -1780,17 +1658,15 @@ sort_compare(void *arg, const void *a, const void *b, int *result)
if (!JS_CHECK_OPERATION_LIMIT(cx))
return JS_FALSE;
CallArgs &args = ca->args;
args.callee() = ca->fval;
args.thisv().setNull();
args[0] = *av;
args[1] = *bv;
InvokeSessionGuard &session = ca->session;
session[0] = *av;
session[1] = *bv;
if (!Invoke(cx, ca->args, 0))
if (!session.invoke(cx))
return JS_FALSE;
jsdouble cmp;
if (!ValueToNumber(cx, args.rval(), &cmp))
if (!ValueToNumber(cx, session.rval(), &cmp))
return JS_FALSE;
/* Clamp cmp to -1, 0, 1. */
@ -2028,10 +1904,8 @@ js::array_sort(JSContext *cx, uintN argc, Value *vp)
} while (++i != newlen);
}
} else {
LeaveTrace(cx);
CompareArgs ca(cx, fval);
if (!cx->stack().pushInvokeArgs(cx, 2, &ca.args))
CompareArgs ca(cx);
if (!ca.session.start(cx, fval, NullValue(), 2))
return false;
if (!js_MergeSort(vec, size_t(newlen), sizeof(Value),
@ -2338,6 +2212,7 @@ array_splice(JSContext *cx, uintN argc, Value *vp)
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
jsuint origlength = length;
/* Convert the first argument into a starting index. */
jsdouble d;
@ -2452,6 +2327,9 @@ array_splice(JSContext *cx, uintN argc, Value *vp)
length -= delta;
}
if (length < origlength && !js_SuppressDeletedIndexProperties(cx, obj, length, origlength))
return JS_FALSE;
/*
* Copy from argv into the hole to complete the splice, and update length in
* case we deleted elements from the end.
@ -2477,10 +2355,8 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
/*
* Clone aobj but pass the minimum of its length and capacity, to
* handle a = [1,2,3]; a.length = 10000 "dense" cases efficiently. In
* such a case we'll pass 8 (not 3) due to ARRAY_CAPACITY_MIN, which
* will cause nobj to be over-allocated to 16. But in the normal case
* where length is <= capacity, nobj and aobj will have the same
* capacity.
* the normal case where length is <= capacity, nobj and aobj will have
* the same capacity.
*/
length = aobj->getArrayLength();
jsuint capacity = aobj->getDenseArrayCapacity();
@ -2803,34 +2679,23 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
if (length == 0)
return JS_TRUE;
JSObject *thisp;
if (argc > 1 && !REDUCE_MODE(mode)) {
if (!js_ValueToObjectOrNull(cx, argv[1], &thisp))
return JS_FALSE;
argv[1].setObjectOrNull(thisp);
} else {
thisp = NULL;
}
Value thisv = (argc > 1 && !REDUCE_MODE(mode)) ? argv[1] : UndefinedValue();
/*
* For all but REDUCE, we call with 3 args (value, index, array). REDUCE
* requires 4 args (accum, value, index, array).
*/
LeaveTrace(cx);
argc = 3 + REDUCE_MODE(mode);
InvokeArgsGuard args;
if (!cx->stack().pushInvokeArgs(cx, argc, &args))
InvokeSessionGuard session;
if (!session.start(cx, ObjectValue(*callable), thisv, argc))
return JS_FALSE;
MUST_FLOW_THROUGH("out");
JSBool ok = JS_TRUE;
JSBool cond;
Value calleev, thisv, objv;
calleev.setObject(*callable);
thisv.setObjectOrNull(thisp);
objv.setObject(*obj);
Value objv = ObjectValue(*obj);
AutoValueRooter tvr(cx);
for (jsint i = start; i != end; i += step) {
JSBool hole;
@ -2845,22 +2710,22 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
* Push callable and 'this', then args. We must do this for every
* iteration around the loop since Invoke clobbers its arguments.
*/
args.callee() = calleev;
args.thisv() = thisv;
Value *sp = args.argv();
uintN argi = 0;
if (REDUCE_MODE(mode))
*sp++ = *vp;
sp[0] = tvr.value();
sp[1].setInt32(i);
sp[2] = objv;
session[argi++] = *vp;
session[argi++] = tvr.value();
session[argi++] = Int32Value(i);
session[argi] = objv;
/* Do the call. */
ok = Invoke(cx, args, 0);
ok = session.invoke(cx);
if (!ok)
break;
const Value &rval = session.rval();
if (mode > MAP)
cond = js_ValueToBoolean(args.rval());
cond = js_ValueToBoolean(rval);
#ifdef __GNUC__ /* quell GCC overwarning */
else
cond = JS_FALSE;
@ -2871,10 +2736,10 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
break;
case REDUCE:
case REDUCE_RIGHT:
*vp = args.rval();
*vp = rval;
break;
case MAP:
ok = SetArrayElement(cx, newarr, i, args.rval());
ok = SetArrayElement(cx, newarr, i, rval);
if (!ok)
goto out;
break;
@ -3000,10 +2865,12 @@ static JSFunctionSpec array_static_methods[] = {
JS_FS_END
};
/* The count here is a guess for the final capacity. */
static inline JSObject *
NewDenseArrayObject(JSContext *cx)
NewDenseArrayObject(JSContext *cx, jsuint count)
{
return NewNonFunction<WithProto::Class>(cx, &js_ArrayClass, NULL, NULL);
gc::FinalizeKind kind = GuessObjectGCKind(count, true);
return NewNonFunction<WithProto::Class>(cx, &js_ArrayClass, NULL, NULL, kind);
}
JSBool
@ -3012,12 +2879,6 @@ js_Array(JSContext *cx, uintN argc, Value *vp)
jsuint length;
const Value *vector;
/* Whether called with 'new' or not, use a new Array object. */
JSObject *obj = NewDenseArrayObject(cx);
if (!obj)
return JS_FALSE;
vp->setObject(*obj);
if (argc == 0) {
length = 0;
vector = NULL;
@ -3034,6 +2895,12 @@ js_Array(JSContext *cx, uintN argc, Value *vp)
vector = NULL;
}
/* Whether called with 'new' or not, use a new Array object. */
JSObject *obj = NewDenseArrayObject(cx, length);
if (!obj)
return JS_FALSE;
vp->setObject(*obj);
return InitArrayObject(cx, obj, length, vector);
}
@ -3045,15 +2912,15 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto, int32 len)
JS_ASSERT(proto->isArray());
JSObject* obj = js_NewGCObject(cx);
gc::FinalizeKind kind = GuessObjectGCKind(len, true);
JSObject* obj = js_NewGCObject(cx, kind);
if (!obj)
return NULL;
/* Initialize all fields, calling init before setting obj->map. */
obj->init(&js_ArrayClass, proto, proto->getParent(), NullValue(), cx);
/* Initialize all fields of JSObject. */
obj->init(cx, &js_ArrayClass, proto, proto->getParent(),
(void*) len, true);
obj->setSharedNonNativeMap();
obj->setArrayLength(len);
obj->setDenseArrayCapacity(0);
return obj;
}
#ifdef JS_TRACER
@ -3067,7 +2934,7 @@ js_NewPreallocatedArray(JSContext* cx, JSObject* proto, int32 len)
JSObject *obj = js_NewEmptyArray(cx, proto, len);
if (!obj)
return NULL;
if (!obj->growDenseArrayElements(cx, 0, JS_MAX(len, ARRAY_CAPACITY_MIN)))
if (!obj->ensureDenseArrayElements(cx, len))
return NULL;
return obj;
}
@ -3076,6 +2943,17 @@ JS_DEFINE_CALLINFO_3(extern, OBJECT, js_NewPreallocatedArray, CONTEXT, OBJECT, I
0, nanojit::ACCSET_STORE_ANY)
#endif
JSObject* JS_FASTCALL
js_InitializerArray(JSContext* cx, int32 count)
{
gc::FinalizeKind kind = GuessObjectGCKind(count, true);
return NewArrayWithKind(cx, kind);
}
#ifdef JS_TRACER
JS_DEFINE_CALLINFO_2(extern, OBJECT, js_InitializerArray, CONTEXT, INT32, 0,
nanojit::ACCSET_STORE_ANY)
#endif
JSObject *
js_InitArrayClass(JSContext *cx, JSObject *obj)
{
@ -3088,7 +2966,7 @@ js_InitArrayClass(JSContext *cx, JSObject *obj)
* Assert that js_InitClass used the correct (slow array, not dense array)
* class for proto's emptyShape class.
*/
JS_ASSERT(proto->emptyShape->getClass() == proto->getClass());
JS_ASSERT(proto->emptyShapes && proto->emptyShapes[0]->getClass() == proto->getClass());
proto->setArrayLength(0);
return proto;
@ -3097,7 +2975,7 @@ js_InitArrayClass(JSContext *cx, JSObject *obj)
JSObject *
js_NewArrayObject(JSContext *cx, jsuint length, const Value *vector)
{
JSObject *obj = NewDenseArrayObject(cx);
JSObject *obj = NewDenseArrayObject(cx, length);
if (!obj)
return NULL;
@ -3220,7 +3098,7 @@ js_IsDensePrimitiveArray(JSObject *obj)
jsuint capacity = obj->getDenseArrayCapacity();
for (jsuint i = 0; i < capacity; i++) {
if (obj->dslots[i].isObject())
if (obj->getDenseArrayElement(i).isObject())
return JS_FALSE;
}
@ -3244,10 +3122,9 @@ js_CloneDensePrimitiveArray(JSContext *cx, JSObject *obj, JSObject **clone)
/*
* Must use the minimum of original array's length and capacity, to handle
* |a = [1,2,3]; a.length = 10000| "dense" cases efficiently. In such a case
* we would use ARRAY_CAPACITY_MIN (not 3), which will cause the clone to be
* over-allocated. In the normal case where length is <= capacity the
* clone and original array will have the same capacity.
* |a = [1,2,3]; a.length = 10000| "dense" cases efficiently. In the normal
* case where length is <= capacity, the clone and original array will have
* the same capacity.
*/
jsuint jsvalCount = JS_MIN(obj->getDenseArrayCapacity(), length);
@ -3256,7 +3133,7 @@ js_CloneDensePrimitiveArray(JSContext *cx, JSObject *obj, JSObject **clone)
return JS_FALSE;
for (jsuint i = 0; i < jsvalCount; i++) {
const Value &val = obj->dslots[i];
const Value &val = obj->getDenseArrayElement(i);
if (val.isString()) {
// Strings must be made immutable before being copied to a clone.

Просмотреть файл

@ -46,8 +46,6 @@
#include "jspubtd.h"
#include "jsobj.h"
#define ARRAY_CAPACITY_MIN 7
extern JSBool
js_StringIsIndex(JSString *str, jsuint *indexp);
@ -139,13 +137,6 @@ js_InitArrayClass(JSContext *cx, JSObject *obj);
extern bool
js_InitContextBusyArrayTable(JSContext *cx);
/*
* Creates a new array with the given length and proto (NB: NULL is not
* translated to Array.prototype), with len slots preallocated.
*/
extern JSObject * JS_FASTCALL
js_NewArrayWithSlots(JSContext* cx, JSObject* proto, uint32 len);
extern JSObject *
js_NewArrayObject(JSContext *cx, jsuint length, const js::Value *vector);

Просмотреть файл

@ -44,8 +44,8 @@
#include <string.h>
#include "jstypes.h"
#include "jsstdint.h"
#include "jsutil.h" /* Added by JSIFY */
#include "jshash.h" /* Added by JSIFY */
#include "jsutil.h"
#include "jshash.h"
#include "jsprf.h"
#include "jsapi.h"
#include "jsatom.h"
@ -158,6 +158,8 @@ const char *const js_common_atom_names[] = {
js_name_str, /* nameAtom */
js_next_str, /* nextAtom */
js_noSuchMethod_str, /* noSuchMethodAtom */
"[object Null]", /* objectNullAtom */
"[object Undefined]", /* objectUndefinedAtom */
js_proto_str, /* protoAtom */
js_set_str, /* setAtom */
js_source_str, /* sourceAtom */

Просмотреть файл

@ -351,6 +351,8 @@ struct JSAtomState
JSAtom *nameAtom;
JSAtom *nextAtom;
JSAtom *noSuchMethodAtom;
JSAtom *objectNullAtom;
JSAtom *objectUndefinedAtom;
JSAtom *protoAtom;
JSAtom *setAtom;
JSAtom *sourceAtom;

Просмотреть файл

@ -42,7 +42,7 @@
*/
#include "jstypes.h"
#include "jsstdint.h"
#include "jsutil.h" /* Added by JSIFY */
#include "jsutil.h"
#include "jsapi.h"
#include "jsatom.h"
#include "jsbool.h"
@ -54,6 +54,7 @@
#include "jsstr.h"
#include "jsvector.h"
#include "jsinterpinlines.h"
#include "jsobjinlines.h"
using namespace js;
@ -77,28 +78,28 @@ Class js_BooleanClass = {
static JSBool
bool_toSource(JSContext *cx, uintN argc, Value *vp)
{
const Value *primp;
if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &primp))
return JS_FALSE;
bool b;
if (!GetPrimitiveThis(cx, vp, &b))
return false;
char buf[32];
JS_snprintf(buf, sizeof buf, "(new %s(%s))",
js_BooleanClass.name,
JS_BOOLEAN_STR(primp->toBoolean()));
JS_snprintf(buf, sizeof buf, "(new Boolean(%s))", JS_BOOLEAN_STR(b));
JSString *str = JS_NewStringCopyZ(cx, buf);
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
}
#endif
static JSBool
bool_toString(JSContext *cx, uintN argc, Value *vp)
{
const Value *primp;
if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &primp))
return JS_FALSE;
JSAtom *atom = cx->runtime->atomState.booleanAtoms[primp->toBoolean() ? 1 : 0];
bool b;
if (!GetPrimitiveThis(cx, vp, &b))
return false;
JSAtom *atom = cx->runtime->atomState.booleanAtoms[b ? 1 : 0];
JSString *str = ATOM_TO_STRING(atom);
if (!str)
return JS_FALSE;
@ -109,20 +110,21 @@ bool_toString(JSContext *cx, uintN argc, Value *vp)
static JSBool
bool_valueOf(JSContext *cx, uintN argc, Value *vp)
{
const Value *primp;
if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &primp))
return JS_FALSE;
*vp = *primp;
bool b;
if (!GetPrimitiveThis(cx, vp, &b))
return false;
vp->setBoolean(b);
return JS_TRUE;
}
static JSFunctionSpec boolean_methods[] = {
#if JS_HAS_TOSOURCE
JS_FN(js_toSource_str, bool_toSource, 0, JSFUN_THISP_BOOLEAN),
JS_FN(js_toSource_str, bool_toSource, 0, JSFUN_PRIMITIVE_THIS),
#endif
JS_FN(js_toString_str, bool_toString, 0, JSFUN_THISP_BOOLEAN),
JS_FN(js_valueOf_str, bool_valueOf, 0, JSFUN_THISP_BOOLEAN),
JS_FN(js_toJSON_str, bool_valueOf, 0, JSFUN_THISP_BOOLEAN),
JS_FN(js_toString_str, bool_toString, 0, JSFUN_PRIMITIVE_THIS),
JS_FN(js_valueOf_str, bool_valueOf, 0, JSFUN_PRIMITIVE_THIS),
JS_FN(js_toJSON_str, bool_valueOf, 0, JSFUN_PRIMITIVE_THIS),
JS_FS_END
};

Просмотреть файл

@ -302,11 +302,14 @@ js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* pa
JSFunction *fun = (JSFunction*) funobj;
JS_ASSERT(GET_FUNCTION_PRIVATE(cx, funobj) == fun);
JSObject* closure = js_NewGCObject(cx);
JSObject* closure = js_NewGCObject(cx, gc::FINALIZE_OBJECT2);
if (!closure)
return NULL;
closure->initSharingEmptyShape(&js_FunctionClass, proto, parent, fun, cx);
if (!closure->initSharingEmptyShape(cx, &js_FunctionClass, proto, parent,
fun, gc::FINALIZE_OBJECT2)) {
return NULL;
}
return closure;
}
JS_DEFINE_CALLINFO_4(extern, OBJECT, js_NewNullClosure, CONTEXT, OBJECT, OBJECT, OBJECT,

Просмотреть файл

@ -184,6 +184,7 @@ struct ClosureVarInfo;
#define _JS_CTYPE_CONTEXT _JS_CTYPE(JSContext *, _JS_PTR,"C", "", INFALLIBLE)
#define _JS_CTYPE_RUNTIME _JS_CTYPE(JSRuntime *, _JS_PTR,"R", "", INFALLIBLE)
#define _JS_CTYPE_MATHCACHE _JS_CTYPE(js::MathCache *, _JS_PTR,"M", "", INFALLIBLE)
#define _JS_CTYPE_THIS _JS_CTYPE(JSObject *, _JS_PTR,"T", "", INFALLIBLE)
#define _JS_CTYPE_THIS_DOUBLE _JS_CTYPE(jsdouble, _JS_F64,"D", "", INFALLIBLE)
#define _JS_CTYPE_THIS_STRING _JS_CTYPE(JSString *, _JS_PTR,"S", "", INFALLIBLE)
@ -577,6 +578,7 @@ js_dmod(jsdouble a, jsdouble b);
JS_DECLARE_CALLINFO(js_Array_dense_setelem_hole)
JS_DECLARE_CALLINFO(js_NewEmptyArray)
JS_DECLARE_CALLINFO(js_NewPreallocatedArray)
JS_DECLARE_CALLINFO(js_InitializerArray)
JS_DECLARE_CALLINFO(js_ArrayCompPush_tn)
JS_DECLARE_CALLINFO(js_EnsureDenseArrayCapacity)
@ -612,8 +614,8 @@ JS_DECLARE_CALLINFO(js_NumberToString)
/* Defined in jsobj.cpp. */
JS_DECLARE_CALLINFO(js_Object_tn)
JS_DECLARE_CALLINFO(js_NewInstanceFromTrace)
JS_DECLARE_CALLINFO(js_NonEmptyObject)
JS_DECLARE_CALLINFO(js_CreateThisFromTrace)
JS_DECLARE_CALLINFO(js_InitializerObject)
/* Defined in jsregexp.cpp. */
JS_DECLARE_CALLINFO(js_CloneRegExpObject)

Просмотреть файл

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* ***** BEGIN LICENSE BLOCK *****
* ***** 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
@ -159,7 +159,7 @@ SCInput::read(uint64_t *p)
bool
SCInput::readPair(uint32_t *tagp, uint32_t *datap)
{
uint64_t u;
uint64_t u = 0; /* initialize to shut GCC up */
bool ok = read(&u);
if (ok) {
*tagp = uint32_t(u >> 32);
@ -304,7 +304,7 @@ SCOutput::writeArray(const T *p, size_t nelems)
js_ReportAllocationOverflow(context());
return false;
}
uint64_t nwords = JS_HOWMANY(nelems, sizeof(uint64_t) / sizeof(T));
size_t nwords = JS_HOWMANY(nelems, sizeof(uint64_t) / sizeof(T));
size_t start = buf.length();
if (!buf.growByUninitialized(nwords))
return false;
@ -463,7 +463,7 @@ JSStructuredCloneWriter::startObject(JSObject *obj)
if (p) {
JSContext *cx = context();
const JSStructuredCloneCallbacks *cb = cx->runtime->structuredCloneCallbacks;
if (cb && cb->reportError)
if (cb)
cb->reportError(cx, JS_SCERR_RECURSION);
else
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SC_RECURSION);
@ -521,20 +521,14 @@ JSStructuredCloneWriter::startWrite(const js::Value &v)
} else if (js_IsArrayBuffer(obj) && ArrayBuffer::fromJSObject(obj)) {
return writeArrayBuffer(obj);
}
const JSStructuredCloneCallbacks *cb = context()->runtime->structuredCloneCallbacks;
if (cb)
return cb->write(context(), this, obj);
/* else fall through */
}
/*
* v is either an object or some strange value like JSVAL_HOLE. Even in the
* latter case, we call the write op anyway, to let the application throw
* the NOT_SUPPORTED_ERR exception.
*/
JSContext *cx = context();
JSRuntime *rt = cx->runtime;
if (rt->structuredCloneCallbacks)
return rt->structuredCloneCallbacks->write(cx, this, Jsvalify(v));
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SC_UNSUPPORTED_TYPE);
JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_UNSUPPORTED_TYPE);
return false;
}
@ -735,7 +729,7 @@ JSStructuredCloneReader::startRead(Value *vp)
case SCTAG_ARRAY_BUFFER_OBJECT:
return readArrayBuffer(data, vp);
default:
default: {
if (tag <= SCTAG_FLOAT_MAX) {
jsdouble d = ReinterpretPairAsDouble(tag, data);
if (IsNonCanonicalizedNaN(d)) {
@ -750,13 +744,17 @@ JSStructuredCloneReader::startRead(Value *vp)
if (SCTAG_TYPED_ARRAY_MIN <= tag && tag <= SCTAG_TYPED_ARRAY_MAX)
return readTypedArray(tag, data, vp);
JSRuntime *rt = context()->runtime;
if (!rt->structuredCloneCallbacks) {
const JSStructuredCloneCallbacks *cb = context()->runtime->structuredCloneCallbacks;
if (!cb) {
JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA,
"unsupported type");
return false;
}
return rt->structuredCloneCallbacks->read(context(), this, tag, data, Jsvalify(vp));
JSObject *obj = cb->read(context(), this, tag, data);
if (!obj)
return false;
vp->setObject(*obj);
}
}
return true;
}

Просмотреть файл

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* ***** BEGIN LICENSE BLOCK *****
* ***** 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

Просмотреть файл

@ -53,8 +53,8 @@
#include "jsstdint.h"
#include "jstypes.h"
#include "jsarena.h" /* Added by JSIFY */
#include "jsutil.h" /* Added by JSIFY */
#include "jsarena.h"
#include "jsutil.h"
#include "jsclist.h"
#include "jsprf.h"
#include "jsatom.h"
@ -225,6 +225,7 @@ StackSpace::mark(JSTracer *trc)
*/
Value *end = firstUnused();
for (StackSegment *seg = currentSegment; seg; seg = seg->getPreviousInMemory()) {
STATIC_ASSERT(ubound(end) >= 0);
if (seg->inContext()) {
/* This may be the only pointer to the initialVarObj. */
if (seg->hasInitialVarObj())
@ -474,7 +475,9 @@ AllFramesIter::operator++()
{
JS_ASSERT(!done());
if (curfp == curcs->getInitialFrame()) {
curcs = curcs->getPreviousInMemory();
do {
curcs = curcs->getPreviousInMemory();
} while (curcs && !curcs->inContext());
curfp = curcs ? curcs->getCurrentFrame() : NULL;
} else {
curfp = curfp->prev();
@ -507,6 +510,16 @@ JSThreadData::init()
return true;
}
MathCache *
JSThreadData::allocMathCache(JSContext *cx)
{
JS_ASSERT(!mathCache);
mathCache = new MathCache;
if (!mathCache)
js_ReportOutOfMemory(cx);
return mathCache;
}
void
JSThreadData::finish()
{
@ -527,6 +540,7 @@ JSThreadData::finish()
jmData.Finish();
#endif
stackSpace.finish();
delete mathCache;
}
void
@ -2035,6 +2049,37 @@ JSContext::JSContext(JSRuntime *rt)
busyArrays(this)
{}
void
JSContext::resetCompartment()
{
JSObject *scopeobj;
if (hasfp()) {
scopeobj = &fp()->scopeChain();
} else {
scopeobj = globalObject;
if (!scopeobj) {
compartment = runtime->defaultCompartment;
return;
}
/*
* Innerize. Assert, but check anyway, that this succeeds. (It
* can only fail due to bugs in the engine or embedding.)
*/
OBJ_TO_INNER_OBJECT(this, scopeobj);
if (!scopeobj) {
/*
* Bug. Return NULL, not defaultCompartment, to crash rather
* than open a security hole.
*/
JS_ASSERT(0);
compartment = NULL;
return;
}
}
compartment = scopeobj->getCompartment();
}
void
JSContext::pushSegmentAndFrame(js::StackSegment *newseg, JSFrameRegs &newregs)
{

Просмотреть файл

@ -53,7 +53,7 @@
#endif
#include "jsprvtd.h"
#include "jsarena.h" /* Added by JSIFY */
#include "jsarena.h"
#include "jsclist.h"
#include "jslong.h"
#include "jsatom.h"
@ -64,6 +64,7 @@
#include "jsgcchunk.h"
#include "jshashtable.h"
#include "jsinterp.h"
#include "jsmath.h"
#include "jsobj.h"
#include "jspropertycache.h"
#include "jspropertytree.h"
@ -244,7 +245,7 @@ namespace mjit {
struct ThreadData
{
JSC::ExecutableAllocator *execPool;
JSC::ExecutableAllocator *execAlloc;
// Trampolines for JIT code.
Trampolines trampolines;
@ -541,9 +542,8 @@ class InvokeArgsGuard : public CallArgs
JSStackFrame *prevInvokeFrame;
#endif
public:
inline InvokeArgsGuard() : cx(NULL), seg(NULL) {}
inline InvokeArgsGuard(JSContext *cx, Value *vp, uintN argc);
inline ~InvokeArgsGuard();
InvokeArgsGuard() : cx(NULL), seg(NULL) {}
~InvokeArgsGuard();
bool pushed() const { return cx != NULL; }
};
@ -565,8 +565,9 @@ class InvokeFrameGuard
JSFrameRegs *prevRegs_;
public:
InvokeFrameGuard() : cx_(NULL) {}
JS_REQUIRES_STACK ~InvokeFrameGuard();
~InvokeFrameGuard() { if (pushed()) pop(); }
bool pushed() const { return cx_ != NULL; }
void pop();
JSStackFrame *fp() const { return regs_.fp; }
};
@ -1188,6 +1189,16 @@ struct JSThreadData {
js::ConservativeGCThreadData conservativeGC;
private:
js::MathCache *mathCache;
js::MathCache *allocMathCache(JSContext *cx);
public:
js::MathCache *getMathCache(JSContext *cx) {
return mathCache ? mathCache : allocMathCache(cx);
}
bool init();
void finish();
void mark(JSTracer *trc);
@ -1284,6 +1295,12 @@ typedef struct JSPropertyTreeEntry {
typedef void
(* JSActivityCallback)(void *arg, JSBool active);
namespace js {
typedef js::Vector<JSCompartment *, 0, js::SystemAllocPolicy> WrapperVector;
}
struct JSRuntime {
/* Default compartment. */
JSCompartment *defaultCompartment;
@ -1292,7 +1309,7 @@ struct JSRuntime {
#endif
/* List of compartments (protected by the GC lock). */
js::Vector<JSCompartment *, 0, js::SystemAllocPolicy> compartments;
js::WrapperVector compartments;
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
JSRuntimeState state;
@ -1509,16 +1526,6 @@ struct JSRuntime {
const char *decimalSeparator;
const char *numGrouping;
/*
* Weak references to lazily-created, well-known XML singletons.
*
* NB: Singleton objects must be carefully disconnected from the rest of
* the object graph usually associated with a JSContext's global object,
* including the set of standard class objects. See jsxml.c for details.
*/
JSObject *anynameObject;
JSObject *functionNamespaceObject;
#ifdef JS_THREADSAFE
/* Number of threads with active requests and unhandled interrupts. */
volatile int32 interruptCounter;
@ -1674,6 +1681,7 @@ struct JSRuntime {
#endif
JSWrapObjectCallback wrapObjectCallback;
JSPreWrapCallback preWrapObjectCallback;
JSC::ExecutableAllocator *regExpAllocator;
@ -2004,9 +2012,14 @@ struct JSContext
friend class js::StackSpace;
friend bool js::Interpret(JSContext *, JSStackFrame *, uintN, uintN);
void resetCompartment();
/* 'regs' must only be changed by calling this function. */
void setCurrentRegs(JSFrameRegs *regs) {
JS_ASSERT_IF(regs, regs->fp);
this->regs = regs;
if (!regs)
resetCompartment();
}
/* Temporary arena pool used while compiling and decompiling. */

Просмотреть файл

@ -46,6 +46,7 @@
#include "jsstaticcheck.h"
#include "jsxml.h"
#include "jsregexp.h"
#include "jsgc.h"
inline js::RegExpStatics *
JSContext::regExpStatics()
@ -139,6 +140,7 @@ StackSpace::isCurrentAndActive(JSContext *cx) const
currentSegment == cx->getCurrentSegment();
}
STATIC_POSTCONDITION(!return || ubound(from) >= nvals)
JS_ALWAYS_INLINE bool
StackSpace::ensureSpace(JSContext *maybecx, Value *from, ptrdiff_t nvals) const
{
@ -323,8 +325,6 @@ StackSpace::pushInvokeFrame(JSContext *cx, const CallArgs &args,
{
JS_ASSERT(firstUnused() == args.argv() + args.argc());
JSStackFrame *fp = fg->regs_.fp;
fp->setPrev(cx->regs);
if (JS_UNLIKELY(!currentSegment->inContext())) {
cx->pushSegmentAndFrame(currentSegment, fg->regs_);
} else {
@ -353,12 +353,12 @@ StackSpace::popInvokeFrame(const InvokeFrameGuard &fg)
}
}
JS_REQUIRES_STACK JS_ALWAYS_INLINE
InvokeFrameGuard::~InvokeFrameGuard()
JS_ALWAYS_INLINE void
InvokeFrameGuard::pop()
{
if (JS_UNLIKELY(!pushed()))
return;
JS_ASSERT(pushed());
cx_->stack().popInvokeFrame(*this);
cx_ = NULL;
}
JS_REQUIRES_STACK JS_ALWAYS_INLINE JSStackFrame *
@ -391,8 +391,6 @@ StackSpace::pushInlineFrame(JSContext *cx, JSScript *script, JSStackFrame *fp,
JS_ASSERT(isCurrentAndActive(cx));
JS_ASSERT(cx->regs == regs && script == fp->script());
fp->setPrev(regs);
regs->fp = fp;
regs->pc = script->code;
regs->sp = fp->slots() + script->nfixed;
@ -511,10 +509,8 @@ class CompartmentChecker
* compartment mismatches.
*/
static void fail(JSCompartment *c1, JSCompartment *c2) {
#ifdef DEBUG_jorendorff
printf("*** Compartment mismatch %p vs. %p\n", (void *) c1, (void *) c2);
// JS_NOT_REACHED("compartment mismatch");
#endif
JS_NOT_REACHED("compartment mismatched");
}
void check(JSCompartment *c) {
@ -530,7 +526,7 @@ class CompartmentChecker
void check(JSObject *obj) {
if (obj)
check(obj->getCompartment(context));
check(obj->getCompartment());
}
void check(const js::Value &v) {
@ -567,8 +563,11 @@ class CompartmentChecker
}
void check(JSScript *script) {
if (script && script->u.object)
check(script->u.object);
if (script && script != JSScript::emptyScript()) {
check(script->compartment);
if (script->u.object)
check(script->u.object);
}
}
void check(JSString *) { /* nothing for now */ }
@ -642,6 +641,7 @@ assertSameCompartment(JSContext *cx, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
#undef START_ASSERT_SAME_COMPARTMENT
STATIC_PRECONDITION_ASSUME(ubound(vp) >= argc + 2)
JS_ALWAYS_INLINE bool
CallJSNative(JSContext *cx, js::Native native, uintN argc, js::Value *vp)
{
@ -657,6 +657,7 @@ CallJSNative(JSContext *cx, js::Native native, uintN argc, js::Value *vp)
return ok;
}
STATIC_PRECONDITION(ubound(vp) >= argc + 2)
JS_ALWAYS_INLINE bool
CallJSNativeConstructor(JSContext *cx, js::Native native, uintN argc, js::Value *vp)
{

Просмотреть файл

@ -52,7 +52,8 @@ using namespace js;
using namespace js::gc;
JSCompartment::JSCompartment(JSRuntime *rt)
: rt(rt), principals(NULL), data(NULL), marked(false), debugMode(false)
: rt(rt), principals(NULL), data(NULL), marked(false), debugMode(false),
anynameObject(NULL), functionNamespaceObject(NULL)
{
JS_INIT_CLIST(&scripts);
}
@ -65,15 +66,8 @@ bool
JSCompartment::init()
{
chunk = NULL;
shortStringArena.init();
stringArena.init();
funArena.init();
#if JS_HAS_XML_SUPPORT
xmlArena.init();
#endif
objArena.init();
for (unsigned i = 0; i < JS_EXTERNAL_STRING_LIMIT; i++)
externalStringArenas[i].init();
for (unsigned i = 0; i < FINALIZE_LIMIT; i++)
arenas[i].init();
for (unsigned i = 0; i < FINALIZE_LIMIT; i++)
freeLists.finalizables[i] = NULL;
#ifdef JS_GCMETER
@ -85,21 +79,10 @@ JSCompartment::init()
bool
JSCompartment::arenaListsAreEmpty()
{
bool empty = objArena.isEmpty() &&
funArena.isEmpty() &&
#if JS_HAS_XML_SUPPORT
xmlArena.isEmpty() &&
#endif
shortStringArena.isEmpty() &&
stringArena.isEmpty();
if (!empty)
return false;
for (unsigned i = 0; i < JS_EXTERNAL_STRING_LIMIT; i++) {
if (!externalStringArenas[i].isEmpty())
for (unsigned i = 0; i < FINALIZE_LIMIT; i++) {
if (!arenas[i].isEmpty())
return false;
}
return true;
}
@ -134,6 +117,24 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
}
}
/*
* Wrappers should really be parented to the wrapped parent of the wrapped
* object, but in that case a wrapped global object would have a NULL
* parent without being a proper global object (JSCLASS_IS_GLOBAL). Instead
,
* we parent all wrappers to the global object in their home compartment.
* This loses us some transparency, and is generally very cheesy.
*/
JSObject *global;
if (cx->hasfp()) {
global = cx->fp()->scopeChain().getGlobal();
} else {
global = cx->globalObject;
OBJ_TO_INNER_OBJECT(cx, global);
if (!global)
return false;
}
/* Unwrap incoming objects. */
if (vp->isObject()) {
JSObject *obj = &vp->toObject();
@ -145,21 +146,40 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
/* Don't unwrap an outer window proxy. */
if (!obj->getClass()->ext.innerObject) {
obj = vp->toObject().unwrap(&flags);
OBJ_TO_OUTER_OBJECT(cx, obj);
vp->setObject(*obj);
if (obj->getCompartment() == this)
return true;
if (cx->runtime->preWrapObjectCallback)
obj = cx->runtime->preWrapObjectCallback(cx, global, obj, flags);
if (!obj)
return false;
vp->setObject(*obj);
if (obj->getCompartment() == this)
return true;
} else {
if (cx->runtime->preWrapObjectCallback)
obj = cx->runtime->preWrapObjectCallback(cx, global, obj, flags);
JS_ASSERT(!obj->isWrapper() || obj->getClass()->ext.innerObject);
vp->setObject(*obj);
}
/* If the wrapped object is already in this compartment, we are done. */
if (obj->getCompartment(cx) == this)
return true;
#ifdef DEBUG
{
JSObject *outer = obj;
OBJ_TO_OUTER_OBJECT(cx, outer);
JS_ASSERT(outer && outer == obj);
}
#endif
}
/* If we already have a wrapper for this value, use it. */
if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(*vp)) {
*vp = p->value;
if (vp->isObject())
vp->toObject().setParent(global);
return true;
}
@ -194,31 +214,16 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
* the wrap hook to reason over what wrappers are currently applied
* to the object.
*/
JSObject *wrapper = cx->runtime->wrapObjectCallback(cx, obj, proto, flags);
JSObject *wrapper = cx->runtime->wrapObjectCallback(cx, obj, proto, global, flags);
if (!wrapper)
return false;
wrapper->setProto(proto);
vp->setObject(*wrapper);
wrapper->setProto(proto);
if (!crossCompartmentWrappers.put(wrapper->getProxyPrivate(), *vp))
return false;
/*
* Wrappers should really be parented to the wrapped parent of the wrapped
* object, but in that case a wrapped global object would have a NULL
* parent without being a proper global object (JSCLASS_IS_GLOBAL). Instead,
* we parent all wrappers to the global object in their home compartment.
* This loses us some transparency, and is generally very cheesy.
*/
JSObject *global;
if (cx->hasfp()) {
global = cx->fp()->scopeChain().getGlobal();
} else {
global = cx->globalObject;
OBJ_TO_INNER_OBJECT(cx, global);
if (!global)
return false;
}
wrapper->setParent(global);
return true;
}
@ -311,14 +316,19 @@ JSCompartment::sweep(JSContext *cx)
chunk = NULL;
/* Remove dead wrappers from the table. */
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
if (IsAboutToBeFinalized(e.front().value.toGCThing()))
JS_ASSERT_IF(IsAboutToBeFinalized(e.front().key.toGCThing()) &&
!IsAboutToBeFinalized(e.front().value.toGCThing()),
e.front().key.isString());
if (IsAboutToBeFinalized(e.front().key.toGCThing()) ||
IsAboutToBeFinalized(e.front().value.toGCThing())) {
e.removeFront();
}
}
#if defined JS_METHODJIT && defined JS_MONOIC
for (JSCList *cursor = scripts.next; cursor != &scripts; cursor = cursor->next) {
JSScript *script = reinterpret_cast<JSScript *>(cursor);
if (script->jit)
if (script->hasJITCode())
mjit::ic::SweepCallICs(script);
}
#endif
@ -333,7 +343,7 @@ JSCompartment::purge(JSContext *cx)
for (JSScript *script = (JSScript *)scripts.next;
&script->links != &scripts;
script = (JSScript *)script->links.next) {
if (script->jit) {
if (script->hasJITCode()) {
# if defined JS_POLYIC
mjit::ic::PurgePICs(cx, script);
# endif

Просмотреть файл

@ -42,28 +42,21 @@
#include "jscntxt.h"
#include "jsgc.h"
#include "jsmath.h"
#include "jsobj.h"
#include "jsfun.h"
#include "jsgcstats.h"
#include "jsclist.h"
#include "jsxml.h"
struct JSCompartment {
struct JS_FRIEND_API(JSCompartment) {
JSRuntime *rt;
JSPrincipals *principals;
js::gc::Chunk *chunk;
js::gc::ArenaList<JSObject> objArena;
js::gc::ArenaList<JSFunction> funArena;
js::gc::ArenaList<JSShortString> shortStringArena;
js::gc::ArenaList<JSString> stringArena;
js::gc::ArenaList<JSString> externalStringArenas[js::gc::JS_EXTERNAL_STRING_LIMIT];
#if JS_HAS_XML_SUPPORT
js::gc::ArenaList<JSXML> xmlArena;
#endif
js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT];
js::gc::FreeLists freeLists;
js::gc::FreeLists freeLists;
#ifdef JS_GCMETER
js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT];
#endif
@ -76,6 +69,16 @@ struct JSCompartment {
/* List all scripts in this compartment. */
JSCList scripts;
/*
* Weak references to lazily-created, well-known XML singletons.
*
* NB: Singleton objects must be carefully disconnected from the rest of
* the object graph usually associated with a JSContext's global object,
* including the set of standard class objects. See jsxml.c for details.
*/
JSObject *anynameObject;
JSObject *functionNamespaceObject;
JSCompartment(JSRuntime *cx);
~JSCompartment();
@ -91,10 +94,6 @@ struct JSCompartment {
bool wrapException(JSContext *cx);
void sweep(JSContext *cx);
#ifdef JS_METHODJIT
bool addScript(JSContext *cx, JSScript *script);
void removeScript(JSScript *script);
#endif
void purge(JSContext *cx);
void finishArenaLists();
bool arenaListsAreEmpty();
@ -126,7 +125,7 @@ class SwitchToCompartment : public PreserveCompartment {
}
SwitchToCompartment(JSContext *cx, JSObject *target) : PreserveCompartment(cx) {
cx->compartment = target->getCompartment(cx);
cx->compartment = target->getCompartment();
}
};

Просмотреть файл

@ -60,7 +60,7 @@
#include "jsstdint.h"
#include "jsprf.h"
#include "prmjtime.h"
#include "jsutil.h" /* Added by JSIFY */
#include "jsutil.h"
#include "jsapi.h"
#include "jsversion.h"
#include "jsbuiltins.h"
@ -2026,7 +2026,7 @@ JSBool
date_toJSON(JSContext *cx, uintN argc, Value *vp)
{
/* Step 1. */
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = js_ValueToNonNullObject(cx, vp[1]);
if (!obj)
return false;
@ -2563,7 +2563,9 @@ JS_FRIEND_API(JSObject *)
js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
{
JSObject *obj = NewBuiltinClassInstance(cx, &js_DateClass);
if (!obj || !SetUTCTime(cx, obj, msec_time))
if (!obj || !obj->ensureSlots(cx, JSObject::DATE_CLASS_RESERVED_SLOTS))
return NULL;
if (!SetUTCTime(cx, obj, msec_time))
return NULL;
return obj;
}

Просмотреть файл

@ -44,7 +44,7 @@
#include <string.h>
#include "jstypes.h"
#include "jsstdint.h"
#include "jsutil.h" /* Added by JSIFY */
#include "jsutil.h"
#include "jsclist.h"
#include "jsapi.h"
#include "jscntxt.h"
@ -116,8 +116,7 @@ js_SetDebugMode(JSContext *cx, JSBool debug)
&script->links != &cx->compartment->scripts;
script = (JSScript *)script->links.next) {
if (script->debugMode != debug &&
script->ncode &&
script->ncode != JS_UNJITTABLE_METHOD &&
script->hasJITCode() &&
!IsScriptLive(cx, script)) {
/*
* In the event that this fails, debug mode is left partially on,
@ -236,6 +235,12 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
return JS_FALSE;
}
if (JSOp(*pc) == JSOP_BEGIN) {
JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
NULL, JSMSG_READ_ONLY, "trap invalid on BEGIN opcode");
return JS_FALSE;
}
JS_ASSERT((JSOp) *pc != JSOP_TRAP);
junk = NULL;
rt = cx->runtime;
@ -274,7 +279,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
cx->free(junk);
#ifdef JS_METHODJIT
if (script->ncode != NULL && script->ncode != JS_UNJITTABLE_METHOD) {
if (script->hasJITCode()) {
mjit::Recompiler recompiler(cx, script);
if (!recompiler.recompile())
return JS_FALSE;
@ -327,7 +332,7 @@ JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
DBG_UNLOCK(cx->runtime);
#ifdef JS_METHODJIT
if (script->ncode != NULL && script->ncode != JS_UNJITTABLE_METHOD) {
if (script->hasJITCode()) {
mjit::Recompiler recompiler(cx, script);
recompiler.recompile();
}
@ -1016,6 +1021,19 @@ JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
return js_LineNumberToPC(script, lineno);
}
JS_PUBLIC_API(jsbytecode *)
JS_FirstValidPC(JSContext *cx, JSScript *script)
{
jsbytecode *pc = script->code;
return *pc == JSOP_BEGIN ? pc + JSOP_BEGIN_LENGTH : pc;
}
JS_PUBLIC_API(jsbytecode *)
JS_EndPC(JSContext *cx, JSScript *script)
{
return script->code + script->length;
}
JS_PUBLIC_API(uintN)
JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun)
{
@ -1215,12 +1233,15 @@ JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp)
return js_GetCallObject(cx, fp);
}
JS_PUBLIC_API(JSObject *)
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp)
JS_PUBLIC_API(JSBool)
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp, jsval *thisv)
{
if (fp->isDummyFrame())
return NULL;
return fp->computeThisObject(cx);
return false;
if (!fp->computeThis(cx))
return false;
*thisv = Jsvalify(fp->thisValue());
return true;
}
JS_PUBLIC_API(JSFunction *)
@ -1646,15 +1667,7 @@ JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
JS_PUBLIC_API(size_t)
JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
{
size_t nbytes = (obj->isFunction() && obj->getPrivate() == obj)
? sizeof(JSFunction)
: sizeof *obj;
if (obj->dslots) {
nbytes += (obj->dslots[-1].toPrivateUint32() - JS_INITIAL_NSLOTS + 1)
* sizeof obj->dslots[0];
}
return nbytes;
return obj->slotsAndStructSize();
}
static size_t

Просмотреть файл

@ -159,6 +159,12 @@ JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
extern JS_PUBLIC_API(jsbytecode *)
JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno);
extern JS_PUBLIC_API(jsbytecode *)
JS_FirstValidPC(JSContext *cx, JSScript *script);
extern JS_PUBLIC_API(jsbytecode *)
JS_EndPC(JSContext *cx, JSScript *script);
extern JS_PUBLIC_API(uintN)
JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun);
@ -245,8 +251,8 @@ JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSObject *)
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSObject *)
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSBool)
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp, jsval *thisv);
extern JS_PUBLIC_API(JSFunction *)
JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше