зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central into tracemonkey
This commit is contained in:
Коммит
312e4e1e90
|
@ -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,9 +2465,18 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
|
|||
jsClass = aObj->getClass();
|
||||
} while (1);
|
||||
|
||||
NS_ASSERTION(!aAllowShortCircuit ||
|
||||
result == doGetObjectPrincipal(origObj, PR_FALSE),
|
||||
#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,7 +454,15 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
|||
js::AutoValueRooter argv(ctx);
|
||||
argv.set(OBJECT_TO_JSVAL(param));
|
||||
|
||||
{
|
||||
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) {
|
||||
|
@ -463,6 +476,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage,
|
||||
aSync, aJSON, aObjectsArray,
|
||||
aJSONRetVal, mContext) : NS_OK;
|
||||
|
|
|
@ -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)
|
||||
|
@ -1458,12 +1483,10 @@ nsGlobalWindow::SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal)
|
|||
"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,29 +1919,48 @@ 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;
|
||||
}
|
||||
|
||||
mJSObject = outerObject;
|
||||
SetWrapper(mJSObject);
|
||||
|
||||
{
|
||||
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 {
|
||||
|
@ -1931,6 +1971,13 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
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,7 +2018,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
|
||||
if ((!reUseInnerWindow || aDocument != oldDoc) && !aState) {
|
||||
nsCOMPtr<nsIHTMLDocument> html_doc(do_QueryInterface(mDocument));
|
||||
nsCommonWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject,
|
||||
nsWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject,
|
||||
html_doc);
|
||||
}
|
||||
|
||||
|
@ -2007,10 +2044,13 @@ 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) {
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(nav));
|
||||
|
||||
if (JSVAL_TO_OBJECT(nav)->compartment() == newInnerWindow->mJSObject->compartment()) {
|
||||
// Restore window.navigator onto the new inner window.
|
||||
|
||||
::JS_DefineProperty(cx, newInnerWindow->mJSObject, "navigator",
|
||||
|
@ -2032,6 +2072,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
getter_AddRefs(navigatorHolder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mArguments) {
|
||||
newInnerWindow->DefineArgumentsProperty(mArguments);
|
||||
|
@ -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,
|
||||
#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.
|
||||
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)) {
|
||||
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",
|
||||
jsval thisVal;
|
||||
|
||||
printf("%sentering %s %s this: ",
|
||||
_indentSpaces(indent++),
|
||||
funName,
|
||||
JS_IsConstructorFrame(cx, fp) ? "constructing":"",
|
||||
(int)JS_GetFrameThis(cx, fp));
|
||||
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)
|
||||
|
|
196
js/src/jsapi.cpp
196
js/src/jsapi.cpp
|
@ -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.
|
||||
* Begin with the length property to share more of the property tree.
|
||||
* The getter/setter here will directly access the object's private value.
|
||||
*/
|
||||
capacity = 0;
|
||||
}
|
||||
|
||||
/* Begin with the length property to share more of the property tree. */
|
||||
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))
|
||||
|
@ -1755,11 +1634,10 @@ js_MergeSort(void *src, size_t nel, size_t elsize,
|
|||
struct CompareArgs
|
||||
{
|
||||
JSContext *context;
|
||||
Value fval;
|
||||
InvokeArgsGuard args;
|
||||
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()) {
|
||||
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,9 +563,12 @@ class CompartmentChecker
|
|||
}
|
||||
|
||||
void check(JSScript *script) {
|
||||
if (script && 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,26 +42,19 @@
|
|||
|
||||
#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;
|
||||
|
||||
#ifdef JS_GCMETER
|
||||
|
@ -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);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче