Merge latest green b2g-inbound changeset and mozilla-central

This commit is contained in:
Ed Morley 2013-08-27 15:17:56 +01:00
commit d4ffac9dcd
265 changed files with 5519 additions and 1399 deletions

View File

@ -87,8 +87,6 @@ config.status: $(topsrcdir)/configure
# Build pseudo-external modules first when export is explicitly called
export::
$(RM) -r $(DIST)/sdk
$(MAKE) -C config export
$(MAKE) tier_nspr
ifdef ENABLE_TESTS
# Additional makefile targets to call automated test suites

View File

@ -12,7 +12,8 @@
<content>
<xul:stack>
<xul:toolbarbutton anonid="progressButton" class="circularprogressindicator-progressButton appbar-secondary"/>
<html:canvas anonid="progressRing" class="circularprogressindicator-progressRing" width="46" height="46"></html:canvas>
<html:div anonid="progressTrack" xbl:inherits="progress" class="circularprogressindicator-progressTrack"></html:div>
<html:canvas anonid="progressRing" xbl:inherits="progress" class="circularprogressindicator-progressRing" width="40" height="40"></html:canvas>
</xul:stack>
</content>
<implementation>
@ -33,6 +34,9 @@
<![CDATA[
const PROGRESS_RING_IMG = "chrome://browser/skin/images/progresscircle.png";
// show ring background even if % is 0.
this.setAttribute("progress", percentComplete);
let startAngle = 1.5 * Math.PI;
let endAngle = startAngle + (2 * Math.PI * (percentComplete / 100));
@ -70,6 +74,7 @@
<![CDATA[
this._progressCircleCtx.clearRect(0, 0,
this._progressCanvas.width, this._progressCanvas.height);
this.removeAttribute("progress");
]]>
</body>
</method>

View File

@ -469,10 +469,26 @@ documenttab[selected] .documenttab-selection {
}
.circularprogressindicator-progressRing {
margin: -2px 18px;
visibility: visible;
margin: 0 @toolbar_horizontal_spacing@;
pointer-events:none;
position: absolute;
}
.circularprogressindicator-progressTrack {
visibility: visible;
margin: 0 @toolbar_horizontal_spacing@;
pointer-events: none;
position: absolute;
width: 40px;
height: 40px;
background-repeat: no-repeat;
background-size: 40px 40px;
background-image: url(chrome://browser/skin/images/progresscircle-bg.png);
}
.circularprogressindicator-progressRing:not([progress]),
.circularprogressindicator-progressTrack:not([progress]) {
visibility: hidden;
}
/* Progress meter ---------------------------------------------------------- */

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 363 B

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -105,6 +105,7 @@ chrome.jar:
skin/images/plus-34.png (images/plus-34.png)
skin/images/plus-24.png (images/plus-24.png)
skin/images/progresscircle.png (images/progresscircle.png)
skin/images/progresscircle-bg.png (images/progresscircle-bg.png)
skin/images/overlay-back.png (images/overlay-back.png)
skin/images/overlay-plus.png (images/overlay-plus.png)

View File

@ -13,6 +13,7 @@
#define BLOBURI_SCHEME "blob"
#define MEDIASTREAMURI_SCHEME "mediastream"
#define MEDIASOURCEURI_SCHEME "mediasource"
#define FONTTABLEURI_SCHEME "moz-fonttable"
class nsIDOMBlob;
class nsIDOMMediaStream;
@ -39,6 +40,9 @@ public:
NS_IMETHOD NewChannel(nsIURI *aURI, nsIChannel * *_retval) MOZ_OVERRIDE;
NS_IMETHOD AllowPort(int32_t port, const char * scheme, bool *_retval) MOZ_OVERRIDE;
static nsresult GenerateURIString(const nsACString &aScheme,
nsACString &aUri);
// Methods for managing uri->object mapping
// AddDataEntry creates the URI with the given scheme and returns it in aUri
static nsresult AddDataEntry(const nsACString& aScheme,
@ -68,6 +72,13 @@ public:
NS_IMETHOD GetScheme(nsACString &result) MOZ_OVERRIDE;
};
class nsFontTableProtocolHandler : public nsHostObjectProtocolHandler
{
public:
NS_IMETHOD GetScheme(nsACString &result);
NS_IMETHOD NewURI(const nsACString & aSpec, const char * aOriginCharset, nsIURI *aBaseURI, nsIURI * *_retval);
};
inline bool IsBlobURI(nsIURI* aUri)
{
bool isBlob;
@ -86,6 +97,12 @@ inline bool IsMediaSourceURI(nsIURI* aUri)
return NS_SUCCEEDED(aUri->SchemeIs(MEDIASOURCEURI_SCHEME, &isMediaSource)) && isMediaSource;
}
inline bool IsFontTableURI(nsIURI* aUri)
{
bool isFont;
return NS_SUCCEEDED(aUri->SchemeIs(FONTTABLEURI_SCHEME, &isFont)) && isFont;
}
extern nsresult
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream);
@ -107,4 +124,8 @@ NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource)
{ 0x12ef31fc, 0xa8fb, 0x4661, \
{ 0x9a, 0x63, 0xfb, 0x61, 0x04,0x5d, 0xb8, 0x61 } }
#define NS_FONTTABLEPROTOCOLHANDLER_CID \
{ 0x3fc8f04e, 0xd719, 0x43ca, \
{ 0x9a, 0xd0, 0x18, 0xee, 0x32, 0x02, 0x11, 0xf2 } }
#endif /* nsHostObjectProtocolHandler_h */

View File

@ -70,6 +70,7 @@
#include "nsFocusManager.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsHtml5Module.h"
#include "nsHtml5StringParser.h"
#include "nsIAsyncVerifyRedirectCallback.h"
@ -2715,10 +2716,12 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
}
nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
NS_ASSERTION(loadGroup, "Could not get loadgroup; onload may fire too early");
nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
NS_ASSERTION(loadGroup || IsFontTableURI(documentURI),
"Could not get loadgroup; onload may fire too early");
// check for a Content Security Policy to pass down to the channel that
// will get created to load the image
nsCOMPtr<nsIChannelPolicy> channelPolicy;

View File

@ -29,22 +29,9 @@ nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme,
nsIPrincipal* aPrincipal,
nsACString& aUri)
{
nsresult rv;
nsCOMPtr<nsIUUIDGenerator> uuidgen =
do_GetService("@mozilla.org/uuid-generator;1", &rv);
nsresult rv = GenerateURIString(aScheme, aUri);
NS_ENSURE_SUCCESS(rv, rv);
nsID id;
rv = uuidgen->GenerateUUIDInPlace(&id);
NS_ENSURE_SUCCESS(rv, rv);
char chars[NSID_LENGTH];
id.ToProvidedString(chars);
aUri += aScheme;
aUri += NS_LITERAL_CSTRING(":");
aUri += Substring(chars + 1, chars + NSID_LENGTH - 2);
if (!gDataTable) {
gDataTable = new nsClassHashtable<nsCStringHashKey, DataInfo>;
gDataTable->Init();
@ -71,6 +58,29 @@ nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri)
}
}
nsresult
nsHostObjectProtocolHandler::GenerateURIString(const nsACString &aScheme,
nsACString& aUri)
{
nsresult rv;
nsCOMPtr<nsIUUIDGenerator> uuidgen =
do_GetService("@mozilla.org/uuid-generator;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsID id;
rv = uuidgen->GenerateUUIDInPlace(&id);
NS_ENSURE_SUCCESS(rv, rv);
char chars[NSID_LENGTH];
id.ToProvidedString(chars);
aUri += aScheme;
aUri += NS_LITERAL_CSTRING(":");
aUri += Substring(chars + 1, chars + NSID_LENGTH - 2);
return NS_OK;
}
nsIPrincipal*
nsHostObjectProtocolHandler::GetDataEntryPrincipal(const nsACString& aUri)
{
@ -276,6 +286,13 @@ nsMediaSourceProtocolHandler::GetScheme(nsACString &result)
return NS_OK;
}
NS_IMETHODIMP
nsFontTableProtocolHandler::GetScheme(nsACString &result)
{
result.AssignLiteral(FONTTABLEURI_SCHEME);
return NS_OK;
}
nsresult
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
{
@ -308,6 +325,39 @@ NS_GetStreamForMediaStreamURI(nsIURI* aURI, nsIDOMMediaStream** aStream)
return NS_OK;
}
NS_IMETHODIMP
nsFontTableProtocolHandler::NewURI(const nsACString& aSpec,
const char *aCharset,
nsIURI *aBaseURI,
nsIURI **aResult)
{
nsRefPtr<nsIURI> uri;
// Either you got here via a ref or a fonttable: uri
if (aSpec.Length() && aSpec.CharAt(0) == '#') {
nsresult rv = aBaseURI->CloneIgnoringRef(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
uri->SetRef(aSpec);
} else {
// Relative URIs (other than #ref) are not meaningful within the
// fonttable: scheme.
// If aSpec is a relative URI -other- than a bare #ref,
// this will leave uri empty, and we'll return a failure code below.
uri = new nsSimpleURI();
uri->SetSpec(aSpec);
}
bool schemeIs;
if (NS_FAILED(uri->SchemeIs(FONTTABLEURI_SCHEME, &schemeIs)) || !schemeIs) {
NS_WARNING("Non-fonttable spec in nsFontTableProtocolHander");
return NS_ERROR_NOT_AVAILABLE;
}
uri.forget(aResult);
return NS_OK;
}
nsresult
NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource)
{

View File

@ -730,11 +730,13 @@ public:
JS::Value GetQueryObject(JSContext* cx, WebGLQuery *query, WebGLenum pname);
private:
// ANY_SAMPLES_PASSED(_CONSERVATIVE) slot
WebGLRefPtr<WebGLQuery> mActiveOcclusionQuery;
// LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN slot
WebGLRefPtr<WebGLQuery> mActiveTransformFeedbackQuery;
bool ValidateQueryTargetParameter(WebGLenum target, const char* infos);
WebGLRefPtr<WebGLQuery>& GetActiveQueryByTarget(WebGLenum target);
WebGLRefPtr<WebGLQuery>* GetQueryTargetSlot(WebGLenum target, const char* infos);
// -----------------------------------------------------------------------------
// Buffer Objects (WebGLContextBuffers.cpp)

View File

@ -113,7 +113,8 @@ WebGLContext::BeginQuery(WebGLenum target, WebGLQuery *query)
if (!IsContextStable())
return;
if (!ValidateQueryTargetParameter(target, "beginQuery")) {
WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target, "beginQuery");
if (!targetSlot) {
return;
}
@ -153,7 +154,7 @@ WebGLContext::BeginQuery(WebGLenum target, WebGLQuery *query)
return;
}
if (GetActiveQueryByTarget(target)) {
if (*targetSlot) {
/*
* See SPECS BeginQuery.1
*/
@ -173,7 +174,7 @@ WebGLContext::BeginQuery(WebGLenum target, WebGLQuery *query)
gl->fBeginQuery(SimulateOcclusionQueryTarget(gl, target), query->mGLName);
}
GetActiveQueryByTarget(target) = query;
*targetSlot = query;
}
void
@ -182,12 +183,13 @@ WebGLContext::EndQuery(WebGLenum target)
if (!IsContextStable())
return;
if (!ValidateQueryTargetParameter(target, "endQuery")) {
WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target, "endQuery");
if (!targetSlot) {
return;
}
if (!GetActiveQueryByTarget(target) ||
target != GetActiveQueryByTarget(target)->mType)
if (!*targetSlot ||
target != (*targetSlot)->mType)
{
/* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
* marks the end of the sequence of commands to be tracked for the query type
@ -214,7 +216,7 @@ WebGLContext::EndQuery(WebGLenum target)
gl->fEndQuery(SimulateOcclusionQueryTarget(gl, target));
}
GetActiveQueryByTarget(target) = nullptr;
*targetSlot = nullptr;
}
bool
@ -237,7 +239,8 @@ WebGLContext::GetQuery(WebGLenum target, WebGLenum pname)
if (!IsContextStable())
return nullptr;
if (!ValidateQueryTargetParameter(target, "getQuery")) {
WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target, "getQuery");
if (!targetSlot) {
return nullptr;
}
@ -249,7 +252,7 @@ WebGLContext::GetQuery(WebGLenum target, WebGLenum pname)
return nullptr;
}
nsRefPtr<WebGLQuery> tmp = GetActiveQueryByTarget(target).get();
nsRefPtr<WebGLQuery> tmp = targetSlot->get();
return tmp.forget();
}
@ -329,36 +332,19 @@ WebGLContext::GetQueryObject(JSContext* cx, WebGLQuery *query, WebGLenum pname)
return JS::NullValue();
}
bool
WebGLContext::ValidateQueryTargetParameter(WebGLenum target, const char* infos)
WebGLRefPtr<WebGLQuery>*
WebGLContext::GetQueryTargetSlot(WebGLenum target, const char* infos)
{
switch (target) {
case LOCAL_GL_ANY_SAMPLES_PASSED:
case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
return &mActiveOcclusionQuery;
case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
return true;
return &mActiveTransformFeedbackQuery;
}
ErrorInvalidEnum("%s: unknown query target", infos);
return false;
}
WebGLRefPtr<WebGLQuery>&
WebGLContext::GetActiveQueryByTarget(WebGLenum target)
{
MOZ_ASSERT(ValidateQueryTargetParameter(target, "private WebGLContext::GetActiveQueryByTarget"));
switch (target) {
case LOCAL_GL_ANY_SAMPLES_PASSED:
case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
return mActiveOcclusionQuery;
case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
return mActiveTransformFeedbackQuery;
}
MOZ_ASSERT(false, "WebGLContext::GetActiveQueryByTarget is not compatible with "
"WebGLContext::ValidateQueryTargetParameter");
return mActiveOcclusionQuery;
return nullptr;
}

View File

@ -41,7 +41,11 @@ public:
bool IsActive() const
{
return mContext->GetActiveQueryByTarget(mType) == this;
WebGLRefPtr<WebGLQuery>* targetSlot = mContext->GetQueryTargetSlot(mType, "WebGLQuery::IsActive()");
MOZ_ASSERT(targetSlot, "unknown query object's type");
return *targetSlot == this;
}
bool HasEverBeenActive()

View File

@ -29,18 +29,24 @@ class ELMCreationDetector
public:
ELMCreationDetector() :
// We can do this optimization only in the main thread.
mDefault(!NS_IsMainThread()),
mInitialCount(mDefault ? 0 : nsEventListenerManager::sMainThreadCreatedCount)
mNonMainThread(!NS_IsMainThread()),
mInitialCount(mNonMainThread ?
0 : nsEventListenerManager::sMainThreadCreatedCount)
{
}
bool MayHaveNewListenerManager()
{
return mDefault ||
return mNonMainThread ||
mInitialCount != nsEventListenerManager::sMainThreadCreatedCount;
}
bool IsMainThread()
{
return !mNonMainThread;
}
private:
bool mDefault;
bool mNonMainThread;
uint32_t mInitialCount;
};
@ -343,6 +349,15 @@ nsEventTargetChainItem::HandleEventTargetChain(
}
}
static nsTArray<nsEventTargetChainItem>* sCachedMainThreadChain = nullptr;
void
NS_ShutdownEventTargetChainRecycler()
{
delete sCachedMainThreadChain;
sCachedMainThreadChain = nullptr;
}
nsEventTargetChainItem*
EventTargetChainItemForChromeTarget(nsTArray<nsEventTargetChainItem>& aChain,
nsINode* aNode,
@ -456,7 +471,15 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
// event dispatching is finished.
nsRefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
nsTArray<nsEventTargetChainItem> chain(128);
ELMCreationDetector cd;
nsTArray<nsEventTargetChainItem> chain;
if (cd.IsMainThread()) {
if (!sCachedMainThreadChain) {
sCachedMainThreadChain = new nsTArray<nsEventTargetChainItem>();
}
chain.SwapElements(*sCachedMainThreadChain);
chain.SetCapacity(128);
}
// Create the event target chain item for the event target.
nsEventTargetChainItem* targetEtci =
@ -575,7 +598,6 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
// Event target chain is created. Handle the chain.
nsEventChainPostVisitor postVisitor(preVisitor);
nsCxPusher pusher;
ELMCreationDetector cd;
nsEventTargetChainItem::HandleEventTargetChain(chain,
postVisitor,
aCallback,
@ -610,6 +632,12 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
if (aEventStatus) {
*aEventStatus = preVisitor.mEventStatus;
}
if (cd.IsMainThread() && chain.Capacity() == 128 && sCachedMainThreadChain) {
chain.ClearAndRetainStorage();
chain.SwapElements(*sCachedMainThreadChain);
}
return rv;
}

View File

@ -250,7 +250,7 @@ void StateMachineTracker::EnsureGlobalStateMachine()
ReentrantMonitorAutoEnter mon(mMonitor);
if (mStateMachineCount == 0) {
NS_ASSERTION(!mStateMachineThread, "Should have null state machine thread!");
DebugOnly<nsresult> rv = NS_NewNamedThread("Media State", &mStateMachineThread, nullptr);
DebugOnly<nsresult> rv = NS_NewNamedThread("Media State", &mStateMachineThread);
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Can't create media state machine thread");
}
mStateMachineCount++;

View File

@ -761,6 +761,7 @@ nsDocShell::nsDocShell():
mAllowMedia(true),
mAllowDNSPrefetch(true),
mAllowWindowControl(true),
mAllowContentRetargeting(true),
mCreatingDocument(false),
mUseErrorPages(false),
mObserveErrorPages(true),
@ -2346,6 +2347,20 @@ NS_IMETHODIMP nsDocShell::SetAllowWindowControl(bool aAllowWindowControl)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting)
{
*aAllowContentRetargeting = mAllowContentRetargeting;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting)
{
mAllowContentRetargeting = aAllowContentRetargeting;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
{
@ -2869,6 +2884,8 @@ nsDocShell::SetDocLoaderParent(nsDocLoader * aParent)
{
SetAllowWindowControl(value);
}
SetAllowContentRetargeting(
parentAsDocShell->GetAllowContentRetargeting());
if (NS_SUCCEEDED(parentAsDocShell->GetIsActive(&value)))
{
SetIsActive(value);
@ -7783,6 +7800,8 @@ nsDocShell::RestoreFromHistory()
bool allowDNSPrefetch;
childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
bool allowContentRetargeting = childShell->GetAllowContentRetargeting();
// this.AddChild(child) calls child.SetDocLoaderParent(this), meaning
// that the child inherits our state. Among other things, this means
// that the child inherits our mIsActive and mInPrivateBrowsing, which
@ -7796,6 +7815,7 @@ nsDocShell::RestoreFromHistory()
childShell->SetAllowImages(allowImages);
childShell->SetAllowMedia(allowMedia);
childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
childShell->SetAllowContentRetargeting(allowContentRetargeting);
rv = childShell->BeginRestore(nullptr, false);
NS_ENSURE_SUCCESS(rv, rv);
@ -9863,9 +9883,14 @@ nsresult nsDocShell::DoChannelLoad(nsIChannel * aChannel,
(void) aChannel->SetLoadFlags(loadFlags);
rv = aURILoader->OpenURI(aChannel,
(mLoadType == LOAD_LINK),
this);
uint32_t openFlags = 0;
if (mLoadType == LOAD_LINK) {
openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
}
if (!mAllowContentRetargeting) {
openFlags |= nsIURILoader::DONT_RETARGET;
}
rv = aURILoader->OpenURI(aChannel, openFlags, this);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;

View File

@ -812,6 +812,7 @@ protected:
bool mAllowMedia;
bool mAllowDNSPrefetch;
bool mAllowWindowControl;
bool mAllowContentRetargeting;
bool mCreatingDocument; // (should be) debugging only
bool mUseErrorPages;
bool mObserveErrorPages;

View File

@ -42,7 +42,7 @@ interface nsIVariant;
interface nsIPrivacyTransitionObserver;
interface nsIReflowObserver;
[scriptable, builtinclass, uuid(365e7446-6c4b-45ae-ae08-b7b401900093)]
[scriptable, builtinclass, uuid(4bb2261b-4c13-44a4-ace3-fc2eec17cc34)]
interface nsIDocShell : nsIDocShellTreeItem
{
/**
@ -258,6 +258,13 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
attribute boolean allowWindowControl;
/**
* True if the docshell allows its content to be handled by a content listener
* other than the docshell itself, including the external helper app service,
* and false otherwise. Defaults to true.
*/
[infallible] attribute boolean allowContentRetargeting;
/**
* Get an enumerator over this docShell and its children.
*

View File

@ -25,6 +25,7 @@ MOCHITEST_FILES = \
582176_dummy.html \
582176_xml.xml \
582176_xslt.xsl \
allowContentRetargeting.sjs \
$(NULL)
MOCHITEST_CHROME_FILES = \
@ -100,6 +101,7 @@ MOCHITEST_CHROME_FILES = \
generic.html \
test_bug846906.xul \
bug846906.html \
test_allowContentRetargeting.html \
$(NULL)
ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)

View File

@ -0,0 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function handleRequest(req, resp) {
resp.setHeader("Content-Type", "application/octet-stream", false);
resp.write("hi");
}

View File

@ -0,0 +1,94 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(runNextTest);
var TEST_URL = "http://mochi.test:8888/tests/docshell/test/chrome/allowContentRetargeting.sjs";
var Ci = Components.interfaces;
function runNextTest() {
var test = tests.shift();
if (!test) {
SimpleTest.finish();
return;
}
test();
}
var tests = [
// Set allowContentRetargeting = false, load a downloadable URL, verify the
// downloadable stops loading.
function basic() {
var iframe = insertIframe();
docshellForWindow(iframe.contentWindow).allowContentRetargeting = false;
loadIframe(iframe);
},
// Set allowContentRetargeting = false on parent docshell, load a downloadable
// URL, verify the downloadable stops loading.
function inherit() {
var docshell = docshellForWindow(window);
docshell.allowContentRetargeting = false;
loadIframe(insertIframe());
},
];
function docshellForWindow(win) {
return win.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebNavigation).
QueryInterface(Ci.nsIDocShell);
}
function insertIframe() {
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
return iframe;
}
function loadIframe(iframe) {
iframe.setAttribute("src", TEST_URL);
docshellForWindow(iframe.contentWindow).
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebProgress).
addProgressListener(progressListener,
Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
}
var progressListener = {
onStateChange: function (webProgress, req, flags, status) {
if (!(flags & Ci.nsIWebProgressListener.STATE_STOP))
return;
is(Components.isSuccessCode(status), false,
"Downloadable should have failed to load");
document.querySelector("iframe").remove();
runNextTest();
},
QueryInterface: function (iid) {
var iids = [
Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
Ci.nsISupports,
];
if (iids.some(function (i) { return iid.equals(i); }))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
};
</script>
</head>
<body>
<p id="display">
</p>
</body>
</html>

View File

@ -11,6 +11,7 @@
#include "nsIXPCScriptable.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDOMScriptObjectFactory.h"
#include "js/Id.h"
#ifdef XP_WIN
#undef GetClassName

View File

@ -8,6 +8,7 @@
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Assertions.h"
#include "js/Id.h" // must come before js/RootingAPI.h
#include "js/Value.h" // must come before js/RootingAPI.h
#include "js/RootingAPI.h"

View File

@ -939,6 +939,10 @@ ContentParent::OnChannelConnected(int32_t pid)
}
#endif
}
// Set a reply timeout. The only time the parent process will actually
// timeout is through urgent messages (which are used by CPOWs).
SetReplyTimeoutMs(Preferences::GetInt("dom.ipc.cpow.timeout", 3000));
}
void
@ -2797,5 +2801,14 @@ ContentParent::RecvKeywordToURI(const nsCString& aKeyword, OptionalInputStreamPa
return true;
}
bool
ContentParent::ShouldContinueFromReplyTimeout()
{
// The only time ContentParent sends blocking messages is for CPOWs, so
// timeouts should only ever occur in electrolysis-enabled sessions.
MOZ_ASSERT(Preferences::GetBool("browser.tabs.remote", false));
return false;
}
} // namespace dom
} // namespace mozilla

View File

@ -180,6 +180,8 @@ protected:
void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why);
bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE;
private:
static nsDataHashtable<nsStringHashKey, ContentParent*> *sAppContentParents;
static nsTArray<ContentParent*>* sNonAppContentParents;

View File

@ -1,18 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
MOCHITEST_FILES = \
test_foo.html \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -1,6 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

View File

@ -1,30 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE HTML>
<html>
<!--
Tests of DOM Worker Threads XHR(Bug 450452 )
-->
<head>
<title>Test for DOM Worker Threads XHR (Bug 450452 )</title>
<script type="text/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=450452">DOM Worker Threads XHR (Bug 450452)</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
ok(true, "passed");
</script>
</pre>
</body>
</html>

View File

@ -13,5 +13,3 @@ DIRS += [
'geolocation',
'notification',
]
TEST_DIRS += ['foo']

View File

@ -9,6 +9,7 @@
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "nsIWidget.h"
#include "gfx2DGlue.h"
#include "mozilla/gfx/2D.h"
#include "gfxUtils.h"
#include <algorithm>
@ -27,6 +28,46 @@ public:
virtual gfx::SourceSurface* GetSurface() = 0;
};
class DataTextureSourceBasic : public DataTextureSource
, public TextureSourceBasic
{
public:
virtual TextureSourceBasic* AsSourceBasic() MOZ_OVERRIDE { return this; }
virtual gfx::SourceSurface* GetSurface() MOZ_OVERRIDE { return mSurface; }
SurfaceFormat GetFormat() const MOZ_OVERRIDE
{
return mSurface->GetFormat();
}
virtual IntSize GetSize() const MOZ_OVERRIDE
{
return mSurface->GetSize();
}
virtual bool Update(gfx::DataSourceSurface* aSurface,
TextureFlags aFlags,
nsIntRegion* aDestRegion = nullptr,
gfx::IntPoint* aSrcOffset = nullptr) MOZ_OVERRIDE
{
// XXX - For this to work with IncrementalContentHost we will need to support
// the aDestRegion and aSrcOffset parameters properly;
mSurface = aSurface;
return true;
}
virtual void DeallocateDeviceData() MOZ_OVERRIDE
{
mSurface = nullptr;
SetUpdateSerial(0);
}
public:
RefPtr<gfx::DataSourceSurface> mSurface;
};
/**
* Texture source and host implementaion for software compositing.
*/
@ -34,6 +75,12 @@ class DeprecatedTextureHostBasic : public DeprecatedTextureHost
, public TextureSourceBasic
{
public:
DeprecatedTextureHostBasic()
: mCompositor(nullptr)
{}
SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
virtual IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual TextureSourceBasic* AsSourceBasic() MOZ_OVERRIDE { return this; }
@ -88,6 +135,7 @@ protected:
nsRefPtr<gfxImageSurface> mThebesImage;
nsRefPtr<gfxASurface> mThebesSurface;
IntSize mSize;
SurfaceFormat mFormat;
};
void
@ -231,6 +279,19 @@ BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect,
return rt.forget();
}
TemporaryRef<DataTextureSource>
BasicCompositor::CreateDataTextureSource(TextureFlags aFlags)
{
RefPtr<DataTextureSource> result = new DataTextureSourceBasic();
return result.forget();
}
bool
BasicCompositor::SupportsEffect(EffectTypes aEffect)
{
return static_cast<EffectTypes>(aEffect) != EFFECT_YCBCR;
}
static void
DrawSurfaceWithTextureCoords(DrawTarget *aDest,
const gfx::Rect& aDestRect,

View File

@ -23,6 +23,12 @@ public:
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
{
return mDrawTarget ? mDrawTarget->GetFormat()
: gfx::FORMAT_UNKNOWN;
}
RefPtr<gfx::DrawTarget> mDrawTarget;
gfx::IntSize mSize;
};
@ -39,9 +45,6 @@ public:
virtual void Destroy() MOZ_OVERRIDE;
virtual TemporaryRef<DataTextureSource>
CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE { return nullptr; }
virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() MOZ_OVERRIDE
{
return TextureFactoryIdentifier(LAYERS_BASIC,
@ -56,6 +59,11 @@ public:
CreateRenderTargetFromSource(const gfx::IntRect &aRect,
const CompositingRenderTarget *aSource) MOZ_OVERRIDE;
virtual TemporaryRef<DataTextureSource>
CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE;
virtual bool SupportsEffect(EffectTypes aEffect) MOZ_OVERRIDE;
virtual void SetRenderTarget(CompositingRenderTarget *aSource) MOZ_OVERRIDE
{
mRenderTarget = static_cast<BasicCompositingRenderTarget*>(aSource);

View File

@ -29,6 +29,9 @@
#include "nsIPrincipal.h"
#include "Element.h"
#include "nsSVGUtils.h"
#include "nsIScriptSecurityManager.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsContentUtils.h"
#include "harfbuzz/hb.h"
#define SVG_CONTENT_TYPE NS_LITERAL_CSTRING("image/svg+xml")
@ -307,12 +310,16 @@ gfxSVGGlyphsDocument::ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen)
nsresult rv = CreateBufferedStream(aBuffer, aBufLen, stream);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> principal =
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
nsCOMPtr<nsIURI> uri;
nsHostObjectProtocolHandler::GenerateURIString(NS_LITERAL_CSTRING(FONTTABLEURI_SCHEME),
mSVGGlyphsDocumentURI);
rv = NS_NewURI(getter_AddRefs(uri), mSVGGlyphsDocumentURI);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> uri;
principal->GetURI(getter_AddRefs(uri));
nsCOMPtr<nsIPrincipal> principal;
nsContentUtils::GetSecurityManager()->
GetNoAppCodebasePrincipal(uri, getter_AddRefs(principal));
nsCOMPtr<nsIDOMDocument> domDoc;
rv = NS_NewDOMDocument(getter_AddRefs(domDoc),
@ -325,6 +332,11 @@ gfxSVGGlyphsDocument::ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen)
DocumentFlavorSVG);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> document(do_QueryInterface(domDoc));
if (!document) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIChannel> channel;
rv = NS_NewInputStreamChannel(getter_AddRefs(channel), uri, nullptr /* stream */,
SVG_CONTENT_TYPE, UTF8_CHARSET);
@ -332,10 +344,6 @@ gfxSVGGlyphsDocument::ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen)
channel->SetOwner(principal);
nsCOMPtr<nsIDocument> document(do_QueryInterface(domDoc));
if (!document) {
return NS_ERROR_FAILURE;
}
document->SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED);
nsCOMPtr<nsIStreamListener> listener;
@ -348,9 +356,6 @@ gfxSVGGlyphsDocument::ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen)
return NS_ERROR_FAILURE;
}
document->SetBaseURI(uri);
document->SetPrincipal(principal);
rv = listener->OnStartRequest(channel, nullptr /* aContext */);
if (NS_FAILED(rv)) {
channel->Cancel(rv);

View File

@ -57,6 +57,8 @@ private:
nsCOMPtr<nsIPresShell> mPresShell;
nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
nsAutoCString mSVGGlyphsDocumentURI;
};
/**

View File

@ -11,6 +11,7 @@
#include <cstddef>
#include <glib.h>
#include <linux/joystick.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/ioctl.h>
@ -20,9 +21,6 @@
#include "mozilla/dom/GamepadService.h"
#include "udev.h"
// Include this later because it also does #define JS_VERSION
#include <linux/joystick.h>
namespace {
using mozilla::dom::GamepadService;

View File

@ -322,6 +322,15 @@ SyncChannel::ShouldContinueFromTimeout()
cont = static_cast<SyncListener*>(mListener.get())->OnReplyTimeout();
}
static enum { UNKNOWN, NOT_DEBUGGING, DEBUGGING } sDebuggingChildren = UNKNOWN;
if (sDebuggingChildren == UNKNOWN) {
sDebuggingChildren = getenv("MOZ_DEBUG_CHILD_PROCESS") ? DEBUGGING : NOT_DEBUGGING;
}
if (sDebuggingChildren == DEBUGGING) {
return true;
}
if (!cont) {
// NB: there's a sublety here. If parents were allowed to
// send sync messages to children, then it would be possible

View File

@ -1,6 +1,8 @@
include protocol PTestDataStructuresSub;
include PTestDataStructuresCommon;
include "mozilla/GfxMessageUtils.h";
namespace mozilla {
namespace _ipdltest {

View File

@ -9,12 +9,14 @@ parent:
sync Test3() returns (uint32_t result);
sync Test4_Begin();
sync Test4_NestedSync();
sync FinalTest_Begin();
child:
async Start();
urgent Reply1() returns (uint32_t result);
urgent Reply2() returns (uint32_t result);
urgent Test4_Reenter();
urgent FinalTest_Hang();
};
} // namespace _ipdltest

View File

@ -3,6 +3,13 @@
#include "IPDLUnitTests.h" // fail etc.
#include <unistd.h>
template<>
struct RunnableMethodTraits<mozilla::_ipdltest::TestUrgencyParent>
{
static void RetainCallee(mozilla::_ipdltest::TestUrgencyParent* obj) { }
static void ReleaseCallee(mozilla::_ipdltest::TestUrgencyParent* obj) { }
};
namespace mozilla {
namespace _ipdltest {
@ -74,6 +81,21 @@ TestUrgencyParent::RecvTest4_NestedSync()
return false;
}
bool
TestUrgencyParent::RecvFinalTest_Begin()
{
SetReplyTimeoutMs(2000);
if (CallFinalTest_Hang())
fail("should have failed due to timeout");
if (!GetIPCChannel()->Unsound_IsClosed())
fail("channel should have closed");
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &TestUrgencyParent::Close));
return false;
}
//-----------------------------------------------------------------------------
// child
@ -115,6 +137,10 @@ TestUrgencyChild::RecvStart()
if (!SendTest4_Begin())
fail("calling SendTest4_Begin");
// This must be the last test, since the child process may die.
if (SendFinalTest_Begin())
fail("Final test should not have succeeded");
Close();
return true;
@ -153,6 +179,13 @@ TestUrgencyChild::AnswerTest4_Reenter()
return true;
}
bool
TestUrgencyChild::AnswerFinalTest_Hang()
{
sleep(10);
return true;
}
TestUrgencyChild::TestUrgencyChild()
: test_(0)
{

View File

@ -27,14 +27,20 @@ public:
bool RecvTest3(uint32_t *value);
bool RecvTest4_Begin();
bool RecvTest4_NestedSync();
bool RecvFinalTest_Begin();
bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE
{
return false;
}
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
{
if (NormalShutdown != why)
if (AbnormalShutdown != why)
fail("unexpected destruction!");
passed("ok");
QuitParent();
}
private:
bool inreply_;
};
@ -51,10 +57,11 @@ public:
bool AnswerReply1(uint32_t *reply);
bool AnswerReply2(uint32_t *reply);
bool AnswerTest4_Reenter();
bool AnswerFinalTest_Hang();
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
{
if (NormalShutdown != why)
if (AbnormalShutdown != why)
fail("unexpected destruction!");
QuitChild();
}

View File

@ -594,7 +594,7 @@ JavaScriptParent::unwrap(JSContext *cx, ObjectId objId)
bool
JavaScriptParent::ipcfail(JSContext *cx)
{
JS_ReportError(cx, "catastrophic IPC failure");
JS_ReportError(cx, "child process crashed or timedout");
return false;
}

View File

@ -10,7 +10,7 @@
#include "JavaScriptShared.h"
#include "mozilla/jsipc/PJavaScriptParent.h"
#include "jsclass.h"
#include "js/Class.h"
#ifdef XP_WIN
#undef GetClassName

721
js/public/Class.h Normal file
View File

@ -0,0 +1,721 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* JSClass definition and its component types, plus related interfaces. */
#ifndef js_Class_h
#define js_Class_h
#include "jspubtd.h"
#include "jstypes.h"
#include "js/CallArgs.h"
#include "js/Id.h"
/*
* A JSClass acts as a vtable for JS objects that allows JSAPI clients to
* control various aspects of the behavior of an object like property lookup.
* js::Class is an engine-private extension that allows more control over
* object behavior and, e.g., allows custom slow layout.
*/
class JSFreeOp;
namespace JS {
template <typename T> class Handle;
template <typename T> class MutableHandle;
class Value;
typedef JS::Handle<JSObject*> HandleObject;
typedef JS::Handle<jsid> HandleId;
typedef JS::Handle<JS::Value> HandleValue;
typedef JS::MutableHandle<JSObject*> MutableHandleObject;
typedef JS::MutableHandle<JS::Value> MutableHandleValue;
}
namespace js {
class Class;
class FreeOp;
class PropertyId;
class PropertyName;
class Shape;
class SpecialId;
// This is equal to JSFunction::class_. Use it in places where you don't want
// to #include jsfun.h.
extern JS_FRIEND_DATA(js::Class* const) FunctionClassPtr;
static JS_ALWAYS_INLINE jsid
SPECIALID_TO_JSID(const SpecialId &sid);
/*
* We partition the ways to refer to a property into three: by an index
* (uint32_t); by a string whose characters do not represent an index
* (PropertyName, see vm/String.h); and by various special values.
*
* Special values are encoded using SpecialId, which is layout-compatible but
* non-interconvertible with jsid. A SpecialId is used for JSID_VOID, which
* does not occur in JS scripts but may be used to indicate the absence of a
* valid identifier. In the future, a SpecialId may also be an object used by
* Harmony-proposed private names.
*/
class SpecialId
{
uintptr_t bits_;
/* Needs access to raw bits. */
friend JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid);
friend class PropertyId;
static const uintptr_t TYPE_VOID = JSID_TYPE_VOID;
static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT;
static const uintptr_t TYPE_MASK = JSID_TYPE_MASK;
SpecialId(uintptr_t bits) : bits_(bits) { }
public:
SpecialId() : bits_(TYPE_VOID) { }
/* Object-valued */
SpecialId(JSObject &obj)
: bits_(uintptr_t(&obj) | TYPE_OBJECT)
{
JS_ASSERT(&obj != NULL);
JS_ASSERT((uintptr_t(&obj) & TYPE_MASK) == 0);
}
bool isObject() const {
return (bits_ & TYPE_MASK) == TYPE_OBJECT && bits_ != TYPE_OBJECT;
}
JSObject *toObject() const {
JS_ASSERT(isObject());
return reinterpret_cast<JSObject *>(bits_ & ~TYPE_MASK);
}
/* Empty */
static SpecialId empty() {
SpecialId sid(TYPE_OBJECT);
JS_ASSERT(sid.isEmpty());
return sid;
}
bool isEmpty() const {
return bits_ == TYPE_OBJECT;
}
/* Void */
static SpecialId voidId() {
SpecialId sid(TYPE_VOID);
JS_ASSERT(sid.isVoid());
return sid;
}
bool isVoid() const {
return bits_ == TYPE_VOID;
}
};
static JS_ALWAYS_INLINE jsid
SPECIALID_TO_JSID(const SpecialId &sid)
{
jsid id;
JSID_BITS(id) = sid.bits_;
JS_ASSERT_IF(sid.isObject(), JSID_IS_OBJECT(id) && JSID_TO_OBJECT(id) == sid.toObject());
JS_ASSERT_IF(sid.isVoid(), JSID_IS_VOID(id));
JS_ASSERT_IF(sid.isEmpty(), JSID_IS_EMPTY(id));
return id;
}
static JS_ALWAYS_INLINE bool
JSID_IS_SPECIAL(jsid id)
{
return JSID_IS_OBJECT(id) || JSID_IS_EMPTY(id) || JSID_IS_VOID(id);
}
static JS_ALWAYS_INLINE SpecialId
JSID_TO_SPECIALID(jsid id)
{
JS_ASSERT(JSID_IS_SPECIAL(id));
if (JSID_IS_OBJECT(id))
return SpecialId(*JSID_TO_OBJECT(id));
if (JSID_IS_EMPTY(id))
return SpecialId::empty();
JS_ASSERT(JSID_IS_VOID(id));
return SpecialId::voidId();
}
typedef JS::Handle<SpecialId> HandleSpecialId;
} // namespace js
// JSClass operation signatures.
// Add or get a property named by id in obj. Note the jsid id type -- id may
// be a string (Unicode property identifier) or an int (element index). The
// *vp out parameter, on success, is the new property value after the action.
typedef bool
(* JSPropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp);
// Set a property named by id in obj, treating the assignment as strict
// mode code if strict is true. Note the jsid id type -- id may be a string
// (Unicode property identifier) or an int (element index). The *vp out
// parameter, on success, is the new property value after the
// set.
typedef bool
(* JSStrictPropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
bool strict, JS::MutableHandle<JS::Value> vp);
// Delete a property named by id in obj.
//
// If an error occurred, return false as per normal JSAPI error practice.
//
// If no error occurred, but the deletion attempt wasn't allowed (perhaps
// because the property was non-configurable), set *succeeded to false and
// return true. This will cause |delete obj[id]| to evaluate to false in
// non-strict mode code, and to throw a TypeError in strict mode code.
//
// If no error occurred and the deletion wasn't disallowed (this is *not* the
// same as saying that a deletion actually occurred -- deleting a non-existent
// property, or an inherited property, is allowed -- it's just pointless),
// set *succeeded to true and return true.
typedef bool
(* JSDeletePropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
bool *succeeded);
// This function type is used for callbacks that enumerate the properties of
// a JSObject. The behavior depends on the value of enum_op:
//
// JSENUMERATE_INIT
// A new, opaque iterator state should be allocated and stored in *statep.
// (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
//
// The number of properties that will be enumerated should be returned as
// an integer jsval in *idp, if idp is non-null, and provided the number of
// enumerable properties is known. If idp is non-null and the number of
// enumerable properties can't be computed in advance, *idp should be set
// to JSVAL_ZERO.
//
// JSENUMERATE_INIT_ALL
// Used identically to JSENUMERATE_INIT, but exposes all properties of the
// object regardless of enumerability.
//
// JSENUMERATE_NEXT
// A previously allocated opaque iterator state is passed in via statep.
// Return the next jsid in the iteration using *idp. The opaque iterator
// state pointed at by statep is destroyed and *statep is set to JSVAL_NULL
// if there are no properties left to enumerate.
//
// JSENUMERATE_DESTROY
// Destroy the opaque iterator state previously allocated in *statep by a
// call to this function when enum_op was JSENUMERATE_INIT or
// JSENUMERATE_INIT_ALL.
//
// The return value is used to indicate success, with a value of false
// indicating failure.
typedef bool
(* JSNewEnumerateOp)(JSContext *cx, JS::Handle<JSObject*> obj, JSIterateOp enum_op,
JS::MutableHandle<JS::Value> statep, JS::MutableHandle<jsid> idp);
// The old-style JSClass.enumerate op should define all lazy properties not
// yet reflected in obj.
typedef bool
(* JSEnumerateOp)(JSContext *cx, JS::Handle<JSObject*> obj);
// Resolve a lazy property named by id in obj by defining it directly in obj.
// Lazy properties are those reflected from some peer native property space
// (e.g., the DOM attributes for a given node reflected as obj) on demand.
//
// JS looks for a property in an object, and if not found, tries to resolve
// the given id. If resolve succeeds, the engine looks again in case resolve
// defined obj[id]. If no such property exists directly in obj, the process
// is repeated with obj's prototype, etc.
//
// NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
typedef bool
(* JSResolveOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id);
// Like JSResolveOp, but flags provide contextual information as follows:
//
// JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment
//
// The *objp out parameter, on success, should be null to indicate that id
// was not resolved; and non-null, referring to obj or one of its prototypes,
// if id was resolved. The hook may assume *objp is null on entry.
//
// This hook instead of JSResolveOp is called via the JSClass.resolve member
// if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
typedef bool
(* JSNewResolveOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, unsigned flags,
JS::MutableHandle<JSObject*> objp);
// Convert obj to the given type, returning true with the resulting value in
// *vp on success, and returning false on error or exception.
typedef bool
(* JSConvertOp)(JSContext *cx, JS::Handle<JSObject*> obj, JSType type,
JS::MutableHandle<JS::Value> vp);
// Finalize obj, which the garbage collector has determined to be unreachable
// from other live objects or from GC roots. Obviously, finalizers must never
// store a reference to obj.
typedef void
(* JSFinalizeOp)(JSFreeOp *fop, JSObject *obj);
// Finalizes external strings created by JS_NewExternalString.
struct JSStringFinalizer {
void (*finalize)(const JSStringFinalizer *fin, jschar *chars);
};
// JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
// returning false on error/exception, true on success with obj[id]'s last-got
// value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id
// is either a string or an int jsval.
typedef bool
(* JSCheckAccessOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JSAccessMode mode, JS::MutableHandle<JS::Value> vp);
// Check whether v is an instance of obj. Return false on error or exception,
// true on success with true in *bp if v is an instance of obj, false in
// *bp otherwise.
typedef bool
(* JSHasInstanceOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JS::Value> vp,
bool *bp);
// Function type for trace operation of the class called to enumerate all
// traceable things reachable from obj's private data structure. For each such
// thing, a trace implementation must call one of the JS_Call*Tracer variants
// on the thing.
//
// JSTraceOp implementation can assume that no other threads mutates object
// state. It must not change state of the object or corresponding native
// structures. The only exception for this rule is the case when the embedding
// needs a tight integration with GC. In that case the embedding can check if
// the traversal is a part of the marking phase through calling
// JS_IsGCMarkingTracer and apply a special code like emptying caches or
// marking its native structures.
typedef void
(* JSTraceOp)(JSTracer *trc, JSObject *obj);
// Callback that JSTraceOp implementation can provide to return a string
// describing the reference traced with JS_CallTracer.
typedef void
(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
// A generic type for functions mapping an object to another object, or null
// if an error or exception was thrown on cx.
typedef JSObject *
(* JSObjectOp)(JSContext *cx, JS::Handle<JSObject*> obj);
// Hook that creates an iterator object for a given object. Returns the
// iterator object or null if an error or exception was thrown on cx.
typedef JSObject *
(* JSIteratorOp)(JSContext *cx, JS::HandleObject obj, bool keysonly);
typedef JSObject *
(* JSWeakmapKeyDelegateOp)(JSObject *obj);
/* js::Class operation signatures. */
namespace js {
typedef bool
(* LookupGenericOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* LookupPropOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* LookupElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index,
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* LookupSpecialOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* DefineGenericOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
typedef bool
(* DefinePropOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter,
unsigned attrs);
typedef bool
(* DefineElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
typedef bool
(* DefineSpecialOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter,
unsigned attrs);
typedef bool
(* GenericIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
JS::MutableHandleValue vp);
typedef bool
(* PropertyIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
JS::Handle<PropertyName*> name, JS::MutableHandleValue vp);
typedef bool
(* ElementIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, uint32_t index,
JS::MutableHandleValue vp);
typedef bool
(* ElementIfPresentOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
uint32_t index, JS::MutableHandleValue vp, bool* present);
typedef bool
(* SpecialIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
HandleSpecialId sid, JS::MutableHandleValue vp);
typedef bool
(* StrictGenericIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandleValue vp, bool strict);
typedef bool
(* StrictPropertyIdOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
JS::MutableHandleValue vp, bool strict);
typedef bool
(* StrictElementIdOp)(JSContext *cx, JS::HandleObject obj, uint32_t index,
JS::MutableHandleValue vp, bool strict);
typedef bool
(* StrictSpecialIdOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
JS::MutableHandleValue vp, bool strict);
typedef bool
(* GenericAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp);
typedef bool
(* PropertyAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
unsigned *attrsp);
typedef bool
(* ElementAttributesOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, unsigned *attrsp);
typedef bool
(* SpecialAttributesOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid, unsigned *attrsp);
typedef bool
(* DeletePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
bool *succeeded);
typedef bool
(* DeleteElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *succeeded);
typedef bool
(* DeleteSpecialOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid, bool *succeeded);
typedef JSObject *
(* ObjectOp)(JSContext *cx, JS::HandleObject obj);
typedef void
(* FinalizeOp)(FreeOp *fop, JSObject *obj);
#define JS_CLASS_MEMBERS \
const char *name; \
uint32_t flags; \
\
/* Mandatory function pointer members. */ \
JSPropertyOp addProperty; \
JSDeletePropertyOp delProperty; \
JSPropertyOp getProperty; \
JSStrictPropertyOp setProperty; \
JSEnumerateOp enumerate; \
JSResolveOp resolve; \
JSConvertOp convert; \
\
/* Optional members (may be null). */ \
FinalizeOp finalize; \
JSCheckAccessOp checkAccess; \
JSNative call; \
JSHasInstanceOp hasInstance; \
JSNative construct; \
JSTraceOp trace
/*
* The helper struct to measure the size of JS_CLASS_MEMBERS to know how much
* we have to pad js::Class to match the size of JSClass.
*/
struct ClassSizeMeasurement
{
JS_CLASS_MEMBERS;
};
struct ClassExtension
{
JSObjectOp outerObject;
JSObjectOp innerObject;
JSIteratorOp iteratorObject;
/*
* isWrappedNative is true only if the class is an XPCWrappedNative.
* WeakMaps use this to override the wrapper disposal optimization.
*/
bool isWrappedNative;
/*
* If an object is used as a key in a weakmap, it may be desirable for the
* garbage collector to keep that object around longer than it otherwise
* would. A common case is when the key is a wrapper around an object in
* another compartment, and we want to avoid collecting the wrapper (and
* removing the weakmap entry) as long as the wrapped object is alive. In
* that case, the wrapped object is returned by the wrapper's
* weakmapKeyDelegateOp hook. As long as the wrapper is used as a weakmap
* key, it will not be collected (and remain in the weakmap) until the
* wrapped object is collected.
*/
JSWeakmapKeyDelegateOp weakmapKeyDelegateOp;
};
#define JS_NULL_CLASS_EXT {NULL,NULL,NULL,false,NULL}
struct ObjectOps
{
LookupGenericOp lookupGeneric;
LookupPropOp lookupProperty;
LookupElementOp lookupElement;
LookupSpecialOp lookupSpecial;
DefineGenericOp defineGeneric;
DefinePropOp defineProperty;
DefineElementOp defineElement;
DefineSpecialOp defineSpecial;
GenericIdOp getGeneric;
PropertyIdOp getProperty;
ElementIdOp getElement;
ElementIfPresentOp getElementIfPresent; /* can be null */
SpecialIdOp getSpecial;
StrictGenericIdOp setGeneric;
StrictPropertyIdOp setProperty;
StrictElementIdOp setElement;
StrictSpecialIdOp setSpecial;
GenericAttributesOp getGenericAttributes;
PropertyAttributesOp getPropertyAttributes;
ElementAttributesOp getElementAttributes;
SpecialAttributesOp getSpecialAttributes;
GenericAttributesOp setGenericAttributes;
PropertyAttributesOp setPropertyAttributes;
ElementAttributesOp setElementAttributes;
SpecialAttributesOp setSpecialAttributes;
DeletePropertyOp deleteProperty;
DeleteElementOp deleteElement;
DeleteSpecialOp deleteSpecial;
JSNewEnumerateOp enumerate;
ObjectOp thisObject;
};
#define JS_NULL_OBJECT_OPS \
{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL}
} // namespace js
// Classes, objects, and properties.
typedef void (*JSClassInternal)();
struct JSClass {
const char *name;
uint32_t flags;
// Mandatory function pointer members.
JSPropertyOp addProperty;
JSDeletePropertyOp delProperty;
JSPropertyOp getProperty;
JSStrictPropertyOp setProperty;
JSEnumerateOp enumerate;
JSResolveOp resolve;
JSConvertOp convert;
// Optional members (may be null).
JSFinalizeOp finalize;
JSCheckAccessOp checkAccess;
JSNative call;
JSHasInstanceOp hasInstance;
JSNative construct;
JSTraceOp trace;
void *reserved[40];
};
#define JSCLASS_HAS_PRIVATE (1<<0) // objects have private slot
#define JSCLASS_NEW_ENUMERATE (1<<1) // has JSNewEnumerateOp hook
#define JSCLASS_NEW_RESOLVE (1<<2) // has JSNewResolveOp hook
#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) // private is (nsISupports *)
#define JSCLASS_IS_DOMJSCLASS (1<<4) // objects are DOM
#define JSCLASS_IMPLEMENTS_BARRIERS (1<<5) // Correctly implements GC read
// and write barriers
#define JSCLASS_EMULATES_UNDEFINED (1<<6) // objects of this class act
// like the value undefined,
// in some contexts
#define JSCLASS_USERBIT1 (1<<7) // Reserved for embeddings.
// To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or
// JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where
// n is a constant in [1, 255]. Reserved slots are indexed from 0 to n-1.
#define JSCLASS_RESERVED_SLOTS_SHIFT 8 // room for 8 flags below */
#define JSCLASS_RESERVED_SLOTS_WIDTH 8 // and 16 above this field */
#define JSCLASS_RESERVED_SLOTS_MASK JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH)
#define JSCLASS_HAS_RESERVED_SLOTS(n) (((n) & JSCLASS_RESERVED_SLOTS_MASK) \
<< JSCLASS_RESERVED_SLOTS_SHIFT)
#define JSCLASS_RESERVED_SLOTS(clasp) (((clasp)->flags \
>> JSCLASS_RESERVED_SLOTS_SHIFT) \
& JSCLASS_RESERVED_SLOTS_MASK)
#define JSCLASS_HIGH_FLAGS_SHIFT (JSCLASS_RESERVED_SLOTS_SHIFT + \
JSCLASS_RESERVED_SLOTS_WIDTH)
#define JSCLASS_IS_ANONYMOUS (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0))
#define JSCLASS_IS_GLOBAL (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1))
#define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+2))
#define JSCLASS_INTERNAL_FLAG3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
// Indicate whether the proto or ctor should be frozen.
#define JSCLASS_FREEZE_PROTO (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
#define JSCLASS_FREEZE_CTOR (1<<(JSCLASS_HIGH_FLAGS_SHIFT+5))
// Reserved for embeddings.
#define JSCLASS_USERBIT2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6))
#define JSCLASS_USERBIT3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+7))
#define JSCLASS_BACKGROUND_FINALIZE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+8))
// Bits 26 through 31 are reserved for the CACHED_PROTO_KEY mechanism, see
// below.
// ECMA-262 requires that most constructors used internally create objects
// with "the original Foo.prototype value" as their [[Prototype]] (__proto__)
// member initial value. The "original ... value" verbiage is there because
// in ECMA-262, global properties naming class objects are read/write and
// deleteable, for the most part.
//
// Implementing this efficiently requires that global objects have classes
// with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
// prevously allowed, but is now an ES5 violation and thus unsupported.
//
#define JSCLASS_GLOBAL_SLOT_COUNT (JSProto_LIMIT * 3 + 26)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \
JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
#define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp) \
(((clasp)->flags & JSCLASS_IS_GLOBAL) \
&& JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
// Fast access to the original value of each standard class's prototype.
#define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 10)
#define JSCLASS_CACHED_PROTO_WIDTH 6
#define JSCLASS_CACHED_PROTO_MASK JS_BITMASK(JSCLASS_CACHED_PROTO_WIDTH)
#define JSCLASS_HAS_CACHED_PROTO(key) (uint32_t(key) << JSCLASS_CACHED_PROTO_SHIFT)
#define JSCLASS_CACHED_PROTO_KEY(clasp) ((JSProtoKey) \
(((clasp)->flags \
>> JSCLASS_CACHED_PROTO_SHIFT) \
& JSCLASS_CACHED_PROTO_MASK))
// Initializer for unused members of statically initialized JSClass structs.
#define JSCLASS_NO_INTERNAL_MEMBERS {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,JSCLASS_NO_INTERNAL_MEMBERS
namespace js {
struct Class
{
JS_CLASS_MEMBERS;
ClassExtension ext;
ObjectOps ops;
uint8_t pad[sizeof(JSClass) - sizeof(ClassSizeMeasurement) -
sizeof(ClassExtension) - sizeof(ObjectOps)];
/* Class is not native and its map is not a scope. */
static const uint32_t NON_NATIVE = JSCLASS_INTERNAL_FLAG2;
bool isNative() const {
return !(flags & NON_NATIVE);
}
bool hasPrivate() const {
return !!(flags & JSCLASS_HAS_PRIVATE);
}
bool emulatesUndefined() const {
return flags & JSCLASS_EMULATES_UNDEFINED;
}
bool isCallable() const {
return this == js::FunctionClassPtr || call;
}
static size_t offsetOfFlags() { return offsetof(Class, flags); }
};
JS_STATIC_ASSERT(offsetof(JSClass, name) == offsetof(Class, name));
JS_STATIC_ASSERT(offsetof(JSClass, flags) == offsetof(Class, flags));
JS_STATIC_ASSERT(offsetof(JSClass, addProperty) == offsetof(Class, addProperty));
JS_STATIC_ASSERT(offsetof(JSClass, delProperty) == offsetof(Class, delProperty));
JS_STATIC_ASSERT(offsetof(JSClass, getProperty) == offsetof(Class, getProperty));
JS_STATIC_ASSERT(offsetof(JSClass, setProperty) == offsetof(Class, setProperty));
JS_STATIC_ASSERT(offsetof(JSClass, enumerate) == offsetof(Class, enumerate));
JS_STATIC_ASSERT(offsetof(JSClass, resolve) == offsetof(Class, resolve));
JS_STATIC_ASSERT(offsetof(JSClass, convert) == offsetof(Class, convert));
JS_STATIC_ASSERT(offsetof(JSClass, finalize) == offsetof(Class, finalize));
JS_STATIC_ASSERT(offsetof(JSClass, checkAccess) == offsetof(Class, checkAccess));
JS_STATIC_ASSERT(offsetof(JSClass, call) == offsetof(Class, call));
JS_STATIC_ASSERT(offsetof(JSClass, construct) == offsetof(Class, construct));
JS_STATIC_ASSERT(offsetof(JSClass, hasInstance) == offsetof(Class, hasInstance));
JS_STATIC_ASSERT(offsetof(JSClass, trace) == offsetof(Class, trace));
JS_STATIC_ASSERT(sizeof(JSClass) == sizeof(Class));
static JS_ALWAYS_INLINE JSClass *
Jsvalify(Class *c)
{
return (JSClass *)c;
}
static JS_ALWAYS_INLINE const JSClass *
Jsvalify(const Class *c)
{
return (const JSClass *)c;
}
static JS_ALWAYS_INLINE Class *
Valueify(JSClass *c)
{
return (Class *)c;
}
static JS_ALWAYS_INLINE const Class *
Valueify(const JSClass *c)
{
return (const Class *)c;
}
/*
* Enumeration describing possible values of the [[Class]] internal property
* value of objects.
*/
enum ESClassValue {
ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean,
ESClass_RegExp, ESClass_ArrayBuffer, ESClass_Date
};
/*
* Return whether the given object has the given [[Class]] internal property
* value. Beware, this query says nothing about the js::Class of the JSObject
* so the caller must not assume anything about obj's representation (e.g., obj
* may be a proxy).
*/
inline bool
ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx);
/* Just a helper that checks v.isObject before calling ObjectClassIs. */
inline bool
IsObjectWithClass(const JS::Value &v, ESClassValue classValue, JSContext *cx);
inline bool
IsPoisonedSpecialId(js::SpecialId iden)
{
if (iden.isObject())
return JS::IsPoisonedPtr(iden.toObject());
return false;
}
template <> struct GCMethods<SpecialId>
{
static SpecialId initial() { return SpecialId(); }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(SpecialId id) { return IsPoisonedSpecialId(id); }
};
} /* namespace js */
#endif /* js_Class_h */

View File

@ -60,7 +60,7 @@ class HashMap
{
typedef Key KeyType;
static const Key &getKey(TableEntry &e) { return e.key; }
static void setKey(TableEntry &e, Key &k) { const_cast<Key &>(e.key) = k; }
static void setKey(TableEntry &e, Key &k) { HashPolicy::rekey(const_cast<Key &>(e.key), k); }
};
typedef detail::HashTable<TableEntry, MapHashPolicy, AllocPolicy> Impl;
@ -295,7 +295,7 @@ class HashSet
{
typedef T KeyType;
static const KeyType &getKey(const T &t) { return t; }
static void setKey(T &t, KeyType &k) { t = k; }
static void setKey(T &t, KeyType &k) { HashPolicy::rekey(t, k); }
};
typedef detail::HashTable<const T, SetOps, AllocPolicy> Impl;
@ -517,6 +517,9 @@ struct PointerHasher
JS_ASSERT(!JS::IsPoisonedPtr(l));
return k == l;
}
static void rekey(Key &k, const Key& newKey) {
k = newKey;
}
};
// Default hash policy: just use the 'lookup' value. This of course only
@ -535,6 +538,9 @@ struct DefaultHasher
// Use builtin or overloaded operator==.
return k == l;
}
static void rekey(Key &k, const Key& newKey) {
k = newKey;
}
};
// Specialize hashing policy for pointer types. It assumes that the type is

150
js/public/Id.h Normal file
View File

@ -0,0 +1,150 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_Id_h
#define js_Id_h
#include "jstypes.h"
#include "js/IdForward.h"
#include "js/Utility.h"
class JSObject;
class JSString;
#ifdef JS_USE_JSID_STRUCT_TYPES
struct jsid
{
size_t asBits;
bool operator==(jsid rhs) const { return asBits == rhs.asBits; }
bool operator!=(jsid rhs) const { return asBits != rhs.asBits; }
};
# define JSID_BITS(id) (id.asBits)
#else
# define JSID_BITS(id) (id)
#endif
#define JSID_TYPE_STRING 0x0
#define JSID_TYPE_INT 0x1
#define JSID_TYPE_VOID 0x2
#define JSID_TYPE_OBJECT 0x4
#define JSID_TYPE_MASK 0x7
// Avoid using canonical 'id' for jsid parameters since this is a magic word in
// Objective-C++ which, apparently, wants to be able to #include jsapi.h.
#define id iden
static JS_ALWAYS_INLINE bool
JSID_IS_STRING(jsid id)
{
return (JSID_BITS(id) & JSID_TYPE_MASK) == 0;
}
static JS_ALWAYS_INLINE JSString *
JSID_TO_STRING(jsid id)
{
JS_ASSERT(JSID_IS_STRING(id));
return (JSString *)JSID_BITS(id);
}
static JS_ALWAYS_INLINE bool
JSID_IS_ZERO(jsid id)
{
return JSID_BITS(id) == 0;
}
static JS_ALWAYS_INLINE bool
JSID_IS_INT(jsid id)
{
return !!(JSID_BITS(id) & JSID_TYPE_INT);
}
static JS_ALWAYS_INLINE int32_t
JSID_TO_INT(jsid id)
{
JS_ASSERT(JSID_IS_INT(id));
return ((uint32_t)JSID_BITS(id)) >> 1;
}
#define JSID_INT_MIN 0
#define JSID_INT_MAX INT32_MAX
static JS_ALWAYS_INLINE bool
INT_FITS_IN_JSID(int32_t i)
{
return i >= 0;
}
static JS_ALWAYS_INLINE jsid
INT_TO_JSID(int32_t i)
{
jsid id;
JS_ASSERT(INT_FITS_IN_JSID(i));
JSID_BITS(id) = ((i << 1) | JSID_TYPE_INT);
return id;
}
static JS_ALWAYS_INLINE bool
JSID_IS_OBJECT(jsid id)
{
return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_OBJECT &&
(size_t)JSID_BITS(id) != JSID_TYPE_OBJECT;
}
static JS_ALWAYS_INLINE JSObject *
JSID_TO_OBJECT(jsid id)
{
JS_ASSERT(JSID_IS_OBJECT(id));
return (JSObject *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
}
static JS_ALWAYS_INLINE jsid
OBJECT_TO_JSID(JSObject *obj)
{
jsid id;
JS_ASSERT(obj != NULL);
JS_ASSERT(((size_t)obj & JSID_TYPE_MASK) == 0);
JSID_BITS(id) = ((size_t)obj | JSID_TYPE_OBJECT);
return id;
}
static JS_ALWAYS_INLINE bool
JSID_IS_GCTHING(jsid id)
{
return JSID_IS_STRING(id) || JSID_IS_OBJECT(id);
}
static JS_ALWAYS_INLINE void *
JSID_TO_GCTHING(jsid id)
{
return (void *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
}
static JS_ALWAYS_INLINE bool
JSID_IS_VOID(const jsid id)
{
JS_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID,
JSID_BITS(id) == JSID_TYPE_VOID);
return ((size_t)JSID_BITS(id) == JSID_TYPE_VOID);
}
static JS_ALWAYS_INLINE bool
JSID_IS_EMPTY(const jsid id)
{
return ((size_t)JSID_BITS(id) == JSID_TYPE_OBJECT);
}
#undef id
#ifdef JS_USE_JSID_STRUCT_TYPES
extern JS_PUBLIC_DATA(const jsid) JSID_VOID;
extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY;
#else
# define JSID_VOID ((jsid)JSID_TYPE_VOID)
# define JSID_EMPTY ((jsid)JSID_TYPE_OBJECT)
#endif
#endif /* js_Id_h */

55
js/public/IdForward.h Normal file
View File

@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_IdForward_h
#define js_IdForward_h
#include <stddef.h>
// A jsid is an identifier for a property or method of an object which is
// either a 31-bit signed integer, interned string or object.
//
// Also, there is an additional jsid value, JSID_VOID, which does not occur in
// JS scripts but may be used to indicate the absence of a valid jsid. A void
// jsid is not a valid id and only arises as an exceptional API return value,
// such as in JS_NextProperty. Embeddings must not pass JSID_VOID into JSAPI
// entry points expecting a jsid and do not need to handle JSID_VOID in hooks
// receiving a jsid except when explicitly noted in the API contract.
//
// A jsid is not implicitly convertible to or from a jsval; JS_ValueToId or
// JS_IdToValue must be used instead.
//
// In release builds, jsid is defined to be an integral type. This
// prevents many bugs from being caught at compile time. E.g.:
//
// jsid id = ...
// if (id) // error
// ...
//
// size_t n = id; // error
//
// To catch more errors, jsid is given a struct type in C++ debug builds.
// Struct assignment and (in C++) operator== allow correct code to be mostly
// oblivious to the change. This feature can be explicitly disabled in debug
// builds by defining JS_NO_JSVAL_JSID_STRUCT_TYPES.
//
// Note: if jsid was always a struct, we could just forward declare it in
// places where its declaration is needed. But the fact that it's a typedef in
// non-debug builds prevents that. So we have this file, which is morally
// equivalent to a forward declaration, and should be included by any file that
// uses jsid but doesn't need its definition.
#if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
# define JS_USE_JSID_STRUCT_TYPES
#endif
#ifdef JS_USE_JSID_STRUCT_TYPES
struct jsid;
#else
typedef ptrdiff_t jsid;
#endif
#endif /* js_IdForward_h */

View File

@ -12,6 +12,7 @@
#include "jspubtd.h"
#include "js/IdForward.h"
#include "js/Utility.h"
/*

View File

@ -341,7 +341,7 @@ obj_valueOf(JSContext *cx, unsigned argc, Value *vp)
return true;
}
#if OLD_GETTER_SETTER_METHODS
#if JS_OLD_GETTER_SETTER_METHODS
enum DefineType { Getter, Setter };
@ -479,7 +479,7 @@ obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp)
}
return true;
}
#endif /* OLD_GETTER_SETTER_METHODS */
#endif /* JS_OLD_GETTER_SETTER_METHODS */
/* ES5 15.2.3.2. */
bool
@ -977,7 +977,7 @@ const JSFunctionSpec js::object_methods[] = {
JS_FN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,0),
JS_FN(js_isPrototypeOf_str, obj_isPrototypeOf, 1,0),
JS_FN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0),
#if OLD_GETTER_SETTER_METHODS
#if JS_OLD_GETTER_SETTER_METHODS
JS_FN(js_defineGetter_str, js::obj_defineGetter, 2,0),
JS_FN(js_defineSetter_str, js::obj_defineSetter, 2,0),
JS_FN(js_lookupGetter_str, obj_lookupGetter, 1,0),

View File

@ -217,7 +217,7 @@ struct FieldInfo
};
// Hash policy for FieldInfos.
struct FieldHashPolicy
struct FieldHashPolicy : DefaultHasher<JSFlatString*>
{
typedef JSFlatString* Key;
typedef Key Lookup;

View File

@ -27,7 +27,6 @@
#include "jsopcode.h"
#include "jsscript.h"
#include "jstypes.h"
#include "jsversion.h"
#include "frontend/BytecodeCompiler.h"
#include "frontend/FoldConstants.h"

View File

@ -18,7 +18,6 @@
#include "jscntxt.h"
#include "jspubtd.h"
#include "jsversion.h"
#include "js/Vector.h"
#include "vm/RegExpObject.h"

View File

@ -352,6 +352,7 @@ struct HeapPtrHasher
static HashNumber hash(Lookup obj) { return DefaultHasher<T *>::hash(obj); }
static bool match(const Key &k, Lookup l) { return k.get() == l; }
static void rekey(Key &k, const Key& newKey) { k.unsafeSet(newKey); }
};
/* Specialized hashing policy for HeapPtrs. */
@ -366,6 +367,7 @@ struct EncapsulatedPtrHasher
static HashNumber hash(Lookup obj) { return DefaultHasher<T *>::hash(obj); }
static bool match(const Key &k, Lookup l) { return k.get() == l; }
static void rekey(Key &k, const Key& newKey) { k.unsafeSet(newKey); }
};
template <class T>
@ -576,6 +578,7 @@ class EncapsulatedId
jsid get() const { return value; }
jsid *unsafeGet() { return &value; }
void unsafeSet(jsid newId) { value = newId; }
operator jsid() const { return value; }
protected:

View File

@ -490,9 +490,10 @@ AutoGCRooter::trace(JSTracer *trc)
AutoObjectUnsigned32HashMap *self = static_cast<AutoObjectUnsigned32HashMap *>(this);
AutoObjectUnsigned32HashMap::HashMapImpl &map = self->map;
for (AutoObjectUnsigned32HashMap::Enum e(map); !e.empty(); e.popFront()) {
mozilla::DebugOnly<JSObject *> key = e.front().key;
MarkObjectRoot(trc, const_cast<JSObject **>(&e.front().key), "AutoObjectUnsignedHashMap key");
JS_ASSERT(key == e.front().key); // Needs rewriting for moving GC, see bug 726687.
JSObject *key = e.front().key;
MarkObjectRoot(trc, &key, "AutoObjectUnsignedHashMap key");
if (key != e.front().key)
e.rekeyFront(key);
}
return;
}
@ -501,9 +502,10 @@ AutoGCRooter::trace(JSTracer *trc)
AutoObjectHashSet *self = static_cast<AutoObjectHashSet *>(this);
AutoObjectHashSet::HashSetImpl &set = self->set;
for (AutoObjectHashSet::Enum e(set); !e.empty(); e.popFront()) {
mozilla::DebugOnly<JSObject *> obj = e.front();
MarkObjectRoot(trc, const_cast<JSObject **>(&e.front()), "AutoObjectHashSet value");
JS_ASSERT(obj == e.front()); // Needs rewriting for moving GC, see bug 726687.
JSObject *obj = e.front();
MarkObjectRoot(trc, &obj, "AutoObjectHashSet value");
if (obj != e.front())
e.rekeyFront(obj);
}
return;
}

View File

@ -7274,11 +7274,8 @@ CodeGenerator::visitAsmJSCheckOverRecursed(LAsmJSCheckOverRecursed *lir)
}
bool
CodeGenerator::visitRangeAssert(LRangeAssert *ins)
CodeGenerator::emitAssertRangeI(Range *r, Register input)
{
Register input = ToRegister(ins->input());
Range *r = ins->range();
// Check the lower bound.
if (r->lower() != INT32_MIN) {
Label success;
@ -7303,12 +7300,8 @@ CodeGenerator::visitRangeAssert(LRangeAssert *ins)
}
bool
CodeGenerator::visitDoubleRangeAssert(LDoubleRangeAssert *ins)
CodeGenerator::emitAssertRangeD(Range *r, FloatRegister input, FloatRegister temp)
{
FloatRegister input = ToFloatRegister(ins->input());
FloatRegister temp = ToFloatRegister(ins->temp());
Range *r = ins->range();
// Check the lower bound.
if (!r->isLowerInfinite()) {
Label success;
@ -7353,5 +7346,58 @@ CodeGenerator::visitDoubleRangeAssert(LDoubleRangeAssert *ins)
return true;
}
bool
CodeGenerator::visitAssertRangeI(LAssertRangeI *ins)
{
Register input = ToRegister(ins->input());
Range *r = ins->range();
return emitAssertRangeI(r, input);
}
bool
CodeGenerator::visitAssertRangeD(LAssertRangeD *ins)
{
FloatRegister input = ToFloatRegister(ins->input());
FloatRegister temp = ToFloatRegister(ins->temp());
Range *r = ins->range();
return emitAssertRangeD(r, input, temp);
}
bool
CodeGenerator::visitAssertRangeV(LAssertRangeV *ins)
{
Range *r = ins->range();
const ValueOperand value = ToValue(ins, LAssertRangeV::Input);
Register tag = masm.splitTagForTest(value);
Label done;
{
Label isNotInt32;
masm.branchTestInt32(Assembler::NotEqual, tag, &isNotInt32);
Register unboxInt32 = ToTempUnboxRegister(ins->temp());
Register input = masm.extractInt32(value, unboxInt32);
emitAssertRangeI(r, input);
masm.jump(&done);
masm.bind(&isNotInt32);
}
{
Label isNotDouble;
masm.branchTestDouble(Assembler::NotEqual, tag, &isNotDouble);
FloatRegister input = ToFloatRegister(ins->floatTemp1());
FloatRegister temp = ToFloatRegister(ins->floatTemp2());
masm.unboxDouble(value, input);
emitAssertRangeD(r, input, temp);
masm.jump(&done);
masm.bind(&isNotDouble);
}
masm.breakpoint();
masm.bind(&done);
return true;
}
} // namespace ion
} // namespace js

View File

@ -301,8 +301,9 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitNameIC(OutOfLineUpdateCache *ool, NameIC *ic);
bool visitCallsiteCloneIC(OutOfLineUpdateCache *ool, CallsiteCloneIC *ic);
bool visitRangeAssert(LRangeAssert *ins);
bool visitDoubleRangeAssert(LDoubleRangeAssert *ins);
bool visitAssertRangeI(LAssertRangeI *ins);
bool visitAssertRangeD(LAssertRangeD *ins);
bool visitAssertRangeV(LAssertRangeV *ins);
IonScriptCounts *extractUnassociatedScriptCounts() {
IonScriptCounts *counts = unassociatedScriptCounts_;
@ -354,6 +355,9 @@ class CodeGenerator : public CodeGeneratorSpecific
// Bailout if an element about to be written to is a hole.
bool emitStoreHoleCheck(Register elements, const LAllocation *index, LSnapshot *snapshot);
bool emitAssertRangeI(Range *r, Register input);
bool emitAssertRangeD(Range *r, FloatRegister input, FloatRegister temp);
// Script counts created when compiling code with no associated JSScript.
IonScriptCounts *unassociatedScriptCounts_;

View File

@ -1331,7 +1331,7 @@ OptimizeMIR(MIRGenerator *mir)
if (mir->shouldCancel("RA Beta"))
return false;
if (!r.analyze())
if (!r.analyze() || !r.addRangeAssertions())
return false;
IonSpewPass("Range Analysis");
AssertExtendedGraphCoherency(graph);

View File

@ -6695,6 +6695,10 @@ IonBuilder::getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index)
if (index->mightBeType(MIRType_String))
barrier = true;
// See note about always needing a barrier in jsop_getprop.
if (needsToMonitorMissingProperties(types))
barrier = true;
MInstruction *ins = MGetElementCache::New(obj, index, barrier);
current->add(ins);
@ -8237,15 +8241,8 @@ IonBuilder::getPropTryCache(bool *emitted, HandlePropertyName name, HandleId id,
if (accessGetter)
barrier = true;
// GetPropertyParIC cannot safely call TypeScript::Monitor to ensure that
// the observed type set contains undefined. To account for possible
// missing properties, which property types do not track, we must always
// insert a type barrier.
if (info().executionMode() == ParallelExecution &&
!types->hasType(types::Type::UndefinedType()))
{
if (needsToMonitorMissingProperties(types))
barrier = true;
}
MIRType rvalType = MIRTypeFromValueType(types->getKnownTypeTag());
if (barrier || IsNullOrUndefined(rvalType))
@ -8259,6 +8256,17 @@ IonBuilder::getPropTryCache(bool *emitted, HandlePropertyName name, HandleId id,
return true;
}
bool
IonBuilder::needsToMonitorMissingProperties(types::StackTypeSet *types)
{
// GetPropertyParIC and GetElementParIC cannot safely call
// TypeScript::Monitor to ensure that the observed type set contains
// undefined. To account for possible missing properties, which property
// types do not track, we must always insert a type barrier.
return (info().executionMode() == ParallelExecution &&
!types->hasType(types::Type::UndefinedType()));
}
bool
IonBuilder::jsop_setprop(HandlePropertyName name)
{

View File

@ -364,6 +364,7 @@ class IonBuilder : public MIRGenerator
bool barrier, types::StackTypeSet *types);
bool getPropTryCache(bool *emitted, HandlePropertyName name, HandleId id,
bool barrier, types::StackTypeSet *types);
bool needsToMonitorMissingProperties(types::StackTypeSet *types);
// jsop_setprop() helpers.
bool setPropTryCommonSetter(bool *emitted, MDefinition *obj,

View File

@ -4923,16 +4923,12 @@ class LAsmJSCheckOverRecursed : public LInstructionHelper<0, 0, 0>
}
};
class LRangeAssert : public LInstructionHelper<0, 1, 0>
class LAssertRangeI : public LInstructionHelper<0, 1, 0>
{
Range range_;
public:
LIR_HEADER(RangeAssert)
LIR_HEADER(AssertRangeI)
LRangeAssert(const LAllocation &input, Range r)
: range_(r)
{
LAssertRangeI(const LAllocation &input) {
setOperand(0, input);
}
@ -4940,21 +4936,20 @@ class LRangeAssert : public LInstructionHelper<0, 1, 0>
return getOperand(0);
}
MAssertRange *mir() {
return mir_->toAssertRange();
}
Range *range() {
return &range_;
return mir()->range();
}
};
class LDoubleRangeAssert : public LInstructionHelper<0, 1, 1>
class LAssertRangeD : public LInstructionHelper<0, 1, 1>
{
Range range_;
public:
LIR_HEADER(DoubleRangeAssert)
LIR_HEADER(AssertRangeD)
LDoubleRangeAssert(const LAllocation &input, const LDefinition &temp, Range r)
: range_(r)
{
LAssertRangeD(const LAllocation &input, const LDefinition &temp) {
setOperand(0, input);
setTemp(0, temp);
}
@ -4967,8 +4962,44 @@ class LDoubleRangeAssert : public LInstructionHelper<0, 1, 1>
return getTemp(0);
}
MAssertRange *mir() {
return mir_->toAssertRange();
}
Range *range() {
return &range_;
return mir()->range();
}
};
class LAssertRangeV : public LInstructionHelper<0, BOX_PIECES, 3>
{
public:
LIR_HEADER(AssertRangeV)
LAssertRangeV(const LDefinition &temp, const LDefinition &floatTemp1,
const LDefinition &floatTemp2)
{
setTemp(0, temp);
setTemp(1, floatTemp1);
setTemp(2, floatTemp2);
}
static const size_t Input = 0;
const LDefinition *temp() {
return getTemp(0);
}
const LDefinition *floatTemp1() {
return getTemp(1);
}
const LDefinition *floatTemp2() {
return getTemp(2);
}
MAssertRange *mir() {
return mir_->toAssertRange();
}
Range *range() {
return mir()->range();
}
};

View File

@ -245,8 +245,9 @@
_(AsmJSCall) \
_(AsmJSCheckOverRecursed) \
_(CheckInterruptPar) \
_(RangeAssert) \
_(DoubleRangeAssert)
_(AssertRangeI) \
_(AssertRangeD) \
_(AssertRangeV)
#if defined(JS_CPU_X86)
# include "jit/x86/LOpcodes-x86.h"

View File

@ -2447,6 +2447,36 @@ LIRGenerator::visitGuardString(MGuardString *ins)
return redefine(ins, ins->input());
}
bool
LIRGenerator::visitAssertRange(MAssertRange *ins)
{
MDefinition *input = ins->input();
LInstruction *lir = NULL;
switch (input->type()) {
case MIRType_Int32:
lir = new LAssertRangeI(useRegisterAtStart(input));
break;
case MIRType_Double:
lir = new LAssertRangeD(useRegister(input), tempFloat());
break;
case MIRType_Value:
lir = new LAssertRangeV(tempToUnbox(), tempFloat(), tempFloat());
if (!useBox(lir, LAssertRangeV::Input, input))
return false;
break;
default:
MOZ_ASSUME_UNREACHABLE("Unexpected Range for MIRType");
break;
}
lir->setMir(ins);
return add(lir);
}
bool
LIRGenerator::visitCallGetProperty(MCallGetProperty *ins)
{
@ -2935,25 +2965,6 @@ LIRGenerator::visitInstruction(MInstruction *ins)
return false;
}
// Check the computed range for this instruction, if the option is set. Note
// that this code is quite invasive; it adds numerous additional
// instructions for each MInstruction with a computed range, and it uses
// registers, so it also affects register allocation.
if (js_IonOptions.checkRangeAnalysis) {
if (Range *r = ins->range()) {
switch (ins->type()) {
case MIRType_Int32:
add(new LRangeAssert(useRegisterAtStart(ins), *r));
break;
case MIRType_Double:
add(new LDoubleRangeAssert(useRegister(ins), tempFloat(), *r));
break;
default:
break;
}
}
}
return true;
}

View File

@ -206,6 +206,7 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitGuardClass(MGuardClass *ins);
bool visitGuardObject(MGuardObject *ins);
bool visitGuardString(MGuardString *ins);
bool visitAssertRange(MAssertRange *ins);
bool visitCallGetProperty(MCallGetProperty *ins);
bool visitDeleteProperty(MDeleteProperty *ins);
bool visitGetNameCache(MGetNameCache *ins);

View File

@ -2227,6 +2227,29 @@ class MGuardString
}
};
class MAssertRange
: public MUnaryInstruction
{
MAssertRange(MDefinition *ins)
: MUnaryInstruction(ins)
{
setGuard();
setMovable();
setResultType(MIRType_None);
}
public:
INSTRUCTION_HEADER(AssertRange)
static MAssertRange *New(MDefinition *ins) {
return new MAssertRange(ins);
}
AliasSet getAliasSet() const {
return AliasSet::None();
}
};
// Caller-side allocation of |this| for |new|:
// Given a templateobject, construct |this| for JSOP_NEW
class MCreateThisWithTemplate

View File

@ -74,6 +74,7 @@ namespace ion {
_(Unbox) \
_(GuardObject) \
_(GuardString) \
_(AssertRange) \
_(ToDouble) \
_(ToInt32) \
_(TruncateToInt32) \

View File

@ -200,6 +200,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
SAFE_OP(GuardShape)
SAFE_OP(GuardObjectType)
SAFE_OP(GuardClass)
SAFE_OP(AssertRange)
SAFE_OP(ArrayLength)
SAFE_OP(TypedArrayLength)
SAFE_OP(TypedArrayElements)

View File

@ -1612,6 +1612,35 @@ RangeAnalysis::analyze()
return true;
}
bool
RangeAnalysis::addRangeAssertions()
{
if (!js_IonOptions.checkRangeAnalysis)
return true;
// Check the computed range for this instruction, if the option is set. Note
// that this code is quite invasive; it adds numerous additional
// instructions for each MInstruction with a computed range, and it uses
// registers, so it also affects register allocation.
for (ReversePostorderIterator iter(graph_.rpoBegin()); iter != graph_.rpoEnd(); iter++) {
MBasicBlock *block = *iter;
for (MInstructionIterator iter(block->begin()); iter != block->end(); iter++) {
MInstruction *ins = *iter;
Range *r = ins->range();
if (!r || ins->isAssertRange() || ins->isBeta())
continue;
MAssertRange *guard = MAssertRange::New(ins);
guard->setRange(new Range(*r));
block->insertAfter(ins, guard);
}
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
// Range based Truncation
///////////////////////////////////////////////////////////////////////////////

View File

@ -81,6 +81,7 @@ class RangeAnalysis
graph_(graph) {}
bool addBetaNobes();
bool analyze();
bool addRangeAssertions();
bool removeBetaNobes();
bool truncate();

View File

@ -3,11 +3,11 @@
* Do not edit.
*/
#ifndef _JS_CONFDEFS_H_
#define _JS_CONFDEFS_H_
#ifndef js_confdefs_h
#define js_confdefs_h
@ALLDEFINES@
#include "js/RequiredDefines.h"
#endif /* _JS_CONFDEFS_H_ */
#endif /* js_confdefs_h */

View File

@ -5,8 +5,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_config_h___
#define js_config_h___
#ifndef js_config_h
#define js_config_h
/* Definitions set at build time that affect SpiderMonkey's public API.
This header file is generated by the SpiderMonkey configure script,
@ -42,4 +42,4 @@
#undef MOZJS_MAJOR_VERSION
#undef MOZJS_MINOR_VERSION
#endif /* js_config_h___ */
#endif /* js_config_h */

View File

@ -2,8 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jsclass.h"
#include "js/Class.h"
#include "jsapi-tests/tests.h"
int count = 0;

View File

@ -10,7 +10,6 @@
*/
#include "jsapi.h"
#include "jsclass.h"
#include "jscpucfg.h"
#include "jspubtd.h"
#include "jstypes.h"
@ -18,6 +17,7 @@
#include "js/Anchor.h"
#include "js/CallArgs.h"
#include "js/CharacterEncoding.h"
#include "js/Class.h"
#include "js/Date.h"
#include "js/GCAPI.h"
#include "js/HashTable.h"

View File

@ -123,11 +123,6 @@ JS::detail::CallMethodIfWrapped(JSContext *cx, IsAcceptableThis test, NativeImpl
#define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
#endif
#ifdef JS_USE_JSID_STRUCT_TYPES
const jsid JSID_VOID = { size_t(JSID_TYPE_VOID) };
const jsid JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
#endif
const jsid voidIdValue = JSID_VOID;
const jsid emptyIdValue = JSID_EMPTY;
const HandleId JS::JSID_VOIDHANDLE = HandleId::fromMarkedLocation(&voidIdValue);
@ -1480,7 +1475,7 @@ static const JSStdName object_prototype_names[] = {
{js_InitObjectClass, EAGER_ATOM(hasOwnProperty), &JSObject::class_},
{js_InitObjectClass, EAGER_ATOM(isPrototypeOf), &JSObject::class_},
{js_InitObjectClass, EAGER_ATOM(propertyIsEnumerable), &JSObject::class_},
#if OLD_GETTER_SETTER_METHODS
#if JS_OLD_GETTER_SETTER_METHODS
{js_InitObjectClass, EAGER_ATOM(defineGetter), &JSObject::class_},
{js_InitObjectClass, EAGER_ATOM(defineSetter), &JSObject::class_},
{js_InitObjectClass, EAGER_ATOM(lookupGetter), &JSObject::class_},

View File

@ -18,12 +18,13 @@
#include <stdint.h>
#include <stdio.h>
#include "js-config.h"
#include "jsalloc.h"
#include "jspubtd.h"
#include "js/CallArgs.h"
#include "js/Class.h"
#include "js/HashTable.h"
#include "js/Id.h"
#include "js/RootingAPI.h"
#include "js/Utility.h"
#include "js/Value.h"
@ -749,131 +750,6 @@ CallNonGenericMethod(JSContext *cx, IsAcceptableThis Test, NativeImpl Impl, Call
/************************************************************************/
/* JSClass operation signatures. */
/*
* Add or get a property named by id in obj. Note the jsid id type -- id may
* be a string (Unicode property identifier) or an int (element index). The
* *vp out parameter, on success, is the new property value after the action.
*/
typedef bool
(* JSPropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp);
/*
* Set a property named by id in obj, treating the assignment as strict
* mode code if strict is true. Note the jsid id type -- id may be a string
* (Unicode property identifier) or an int (element index). The *vp out
* parameter, on success, is the new property value after the
* set.
*/
typedef bool
(* JSStrictPropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
bool strict, JS::MutableHandle<JS::Value> vp);
/*
* Delete a property named by id in obj.
*
* If an error occurred, return false as per normal JSAPI error practice.
*
* If no error occurred, but the deletion attempt wasn't allowed (perhaps
* because the property was non-configurable), set *succeeded to false and
* return true. This will cause |delete obj[id]| to evaluate to false in
* non-strict mode code, and to throw a TypeError in strict mode code.
*
* If no error occurred and the deletion wasn't disallowed (this is *not* the
* same as saying that a deletion actually occurred -- deleting a non-existent
* property, or an inherited property, is allowed -- it's just pointless),
* set *succeeded to true and return true.
*/
typedef bool
(* JSDeletePropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
bool *succeeded);
/*
* This function type is used for callbacks that enumerate the properties of
* a JSObject. The behavior depends on the value of enum_op:
*
* JSENUMERATE_INIT
* A new, opaque iterator state should be allocated and stored in *statep.
* (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
*
* The number of properties that will be enumerated should be returned as
* an integer jsval in *idp, if idp is non-null, and provided the number of
* enumerable properties is known. If idp is non-null and the number of
* enumerable properties can't be computed in advance, *idp should be set
* to JSVAL_ZERO.
*
* JSENUMERATE_INIT_ALL
* Used identically to JSENUMERATE_INIT, but exposes all properties of the
* object regardless of enumerability.
*
* JSENUMERATE_NEXT
* A previously allocated opaque iterator state is passed in via statep.
* Return the next jsid in the iteration using *idp. The opaque iterator
* state pointed at by statep is destroyed and *statep is set to JSVAL_NULL
* if there are no properties left to enumerate.
*
* JSENUMERATE_DESTROY
* Destroy the opaque iterator state previously allocated in *statep by a
* call to this function when enum_op was JSENUMERATE_INIT or
* JSENUMERATE_INIT_ALL.
*
* The return value is used to indicate success, with a value of false
* indicating failure.
*/
typedef bool
(* JSNewEnumerateOp)(JSContext *cx, JS::Handle<JSObject*> obj, JSIterateOp enum_op,
JS::MutableHandle<JS::Value> statep, JS::MutableHandle<jsid> idp);
/*
* The old-style JSClass.enumerate op should define all lazy properties not
* yet reflected in obj.
*/
typedef bool
(* JSEnumerateOp)(JSContext *cx, JS::Handle<JSObject*> obj);
/*
* Resolve a lazy property named by id in obj by defining it directly in obj.
* Lazy properties are those reflected from some peer native property space
* (e.g., the DOM attributes for a given node reflected as obj) on demand.
*
* JS looks for a property in an object, and if not found, tries to resolve
* the given id. If resolve succeeds, the engine looks again in case resolve
* defined obj[id]. If no such property exists directly in obj, the process
* is repeated with obj's prototype, etc.
*
* NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
*/
typedef bool
(* JSResolveOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id);
/*
* Like JSResolveOp, but flags provide contextual information as follows:
*
* JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment
*
* The *objp out parameter, on success, should be null to indicate that id
* was not resolved; and non-null, referring to obj or one of its prototypes,
* if id was resolved. The hook may assume *objp is null on entry.
*
* This hook instead of JSResolveOp is called via the JSClass.resolve member
* if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
*/
typedef bool
(* JSNewResolveOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, unsigned flags,
JS::MutableHandle<JSObject*> objp);
/*
* Convert obj to the given type, returning true with the resulting value in
* *vp on success, and returning false on error or exception.
*/
typedef bool
(* JSConvertOp)(JSContext *cx, JS::Handle<JSObject*> obj, JSType type,
JS::MutableHandle<JS::Value> vp);
typedef struct JSFreeOp JSFreeOp;
struct JSFreeOp {
private:
JSRuntime *runtime_;
@ -888,85 +764,10 @@ struct JSFreeOp {
}
};
/*
* Finalize obj, which the garbage collector has determined to be unreachable
* from other live objects or from GC roots. Obviously, finalizers must never
* store a reference to obj.
*/
typedef void
(* JSFinalizeOp)(JSFreeOp *fop, JSObject *obj);
/*
* Finalizes external strings created by JS_NewExternalString.
*/
typedef struct JSStringFinalizer JSStringFinalizer;
struct JSStringFinalizer {
void (*finalize)(const JSStringFinalizer *fin, jschar *chars);
};
/*
* JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
* returning false on error/exception, true on success with obj[id]'s last-got
* value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id
* is either a string or an int jsval.
*/
typedef bool
(* JSCheckAccessOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JSAccessMode mode, JS::MutableHandle<JS::Value> vp);
/*
* Check whether v is an instance of obj. Return false on error or exception,
* true on success with true in *bp if v is an instance of obj, false in
* *bp otherwise.
*/
typedef bool
(* JSHasInstanceOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JS::Value> vp,
bool *bp);
/*
* Function type for trace operation of the class called to enumerate all
* traceable things reachable from obj's private data structure. For each such
* thing, a trace implementation must call one of the JS_Call*Tracer variants
* on the thing.
*
* JSTraceOp implementation can assume that no other threads mutates object
* state. It must not change state of the object or corresponding native
* structures. The only exception for this rule is the case when the embedding
* needs a tight integration with GC. In that case the embedding can check if
* the traversal is a part of the marking phase through calling
* JS_IsGCMarkingTracer and apply a special code like emptying caches or
* marking its native structures.
*/
typedef void
(* JSTraceOp)(JSTracer *trc, JSObject *obj);
/*
* Callback that JSTraceOp implementation can provide to return a string
* describing the reference traced with JS_CallTracer.
*/
typedef void
(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
/*
* A generic type for functions mapping an object to another object, or null
* if an error or exception was thrown on cx.
*/
typedef JSObject *
(* JSObjectOp)(JSContext *cx, JS::Handle<JSObject*> obj);
/*
* Hook that creates an iterator object for a given object. Returns the
* iterator object or null if an error or exception was thrown on cx.
*/
typedef JSObject *
(* JSIteratorOp)(JSContext *cx, JS::HandleObject obj, bool keysonly);
typedef JSObject *
(* JSWeakmapKeyDelegateOp)(JSObject *obj);
/* Callbacks and their arguments. */
/************************************************************************/
typedef enum JSContextOp {
JSCONTEXT_NEW,
JSCONTEXT_DESTROY
@ -1161,47 +962,6 @@ JS_NumberValue(double d)
/************************************************************************/
/*
* A jsid is an identifier for a property or method of an object which is
* either a 31-bit signed integer, interned string or object. Also, there is
* an additional jsid value, JSID_VOID, which does not occur in JS scripts but
* may be used to indicate the absence of a valid jsid.
*
* A jsid is not implicitly convertible to or from a jsval; JS_ValueToId or
* JS_IdToValue must be used instead.
*/
#define JSID_TYPE_STRING 0x0
#define JSID_TYPE_INT 0x1
#define JSID_TYPE_VOID 0x2
#define JSID_TYPE_OBJECT 0x4
#define JSID_TYPE_MASK 0x7
/*
* Avoid using canonical 'id' for jsid parameters since this is a magic word in
* Objective-C++ which, apparently, wants to be able to #include jsapi.h.
*/
#define id iden
static JS_ALWAYS_INLINE bool
JSID_IS_STRING(jsid id)
{
return (JSID_BITS(id) & JSID_TYPE_MASK) == 0;
}
static JS_ALWAYS_INLINE JSString *
JSID_TO_STRING(jsid id)
{
JS_ASSERT(JSID_IS_STRING(id));
return (JSString *)JSID_BITS(id);
}
static JS_ALWAYS_INLINE bool
JSID_IS_ZERO(jsid id)
{
return JSID_BITS(id) == 0;
}
JS_PUBLIC_API(bool)
JS_StringHasBeenInterned(JSContext *cx, JSString *str);
@ -1215,104 +975,6 @@ JS_StringHasBeenInterned(JSContext *cx, JSString *str);
JS_PUBLIC_API(jsid)
INTERNED_STRING_TO_JSID(JSContext *cx, JSString *str);
static JS_ALWAYS_INLINE bool
JSID_IS_INT(jsid id)
{
return !!(JSID_BITS(id) & JSID_TYPE_INT);
}
static JS_ALWAYS_INLINE int32_t
JSID_TO_INT(jsid id)
{
JS_ASSERT(JSID_IS_INT(id));
return ((uint32_t)JSID_BITS(id)) >> 1;
}
#define JSID_INT_MIN 0
#define JSID_INT_MAX INT32_MAX
static JS_ALWAYS_INLINE bool
INT_FITS_IN_JSID(int32_t i)
{
return i >= 0;
}
static JS_ALWAYS_INLINE jsid
INT_TO_JSID(int32_t i)
{
jsid id;
JS_ASSERT(INT_FITS_IN_JSID(i));
JSID_BITS(id) = ((i << 1) | JSID_TYPE_INT);
return id;
}
static JS_ALWAYS_INLINE bool
JSID_IS_OBJECT(jsid id)
{
return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_OBJECT &&
(size_t)JSID_BITS(id) != JSID_TYPE_OBJECT;
}
static JS_ALWAYS_INLINE JSObject *
JSID_TO_OBJECT(jsid id)
{
JS_ASSERT(JSID_IS_OBJECT(id));
return (JSObject *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
}
static JS_ALWAYS_INLINE jsid
OBJECT_TO_JSID(JSObject *obj)
{
jsid id;
JS_ASSERT(obj != NULL);
JS_ASSERT(((size_t)obj & JSID_TYPE_MASK) == 0);
JSID_BITS(id) = ((size_t)obj | JSID_TYPE_OBJECT);
return id;
}
static JS_ALWAYS_INLINE bool
JSID_IS_GCTHING(jsid id)
{
return JSID_IS_STRING(id) || JSID_IS_OBJECT(id);
}
static JS_ALWAYS_INLINE void *
JSID_TO_GCTHING(jsid id)
{
return (void *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
}
/*
* A void jsid is not a valid id and only arises as an exceptional API return
* value, such as in JS_NextProperty. Embeddings must not pass JSID_VOID into
* JSAPI entry points expecting a jsid and do not need to handle JSID_VOID in
* hooks receiving a jsid except when explicitly noted in the API contract.
*/
static JS_ALWAYS_INLINE bool
JSID_IS_VOID(const jsid id)
{
JS_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID,
JSID_BITS(id) == JSID_TYPE_VOID);
return ((size_t)JSID_BITS(id) == JSID_TYPE_VOID);
}
static JS_ALWAYS_INLINE bool
JSID_IS_EMPTY(const jsid id)
{
return ((size_t)JSID_BITS(id) == JSID_TYPE_OBJECT);
}
#undef id
#ifdef JS_USE_JSID_STRUCT_TYPES
extern JS_PUBLIC_DATA(const jsid) JSID_VOID;
extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY;
#else
# define JSID_VOID ((jsid)JSID_TYPE_VOID)
# define JSID_EMPTY ((jsid)JSID_TYPE_OBJECT)
#endif
/*
* Returns true iff the given jsval is immune to GC and can be used across
* multiple JSRuntimes without requiring any conversion API.
@ -2812,121 +2474,6 @@ JS_SetNativeStackQuota(JSRuntime *cx, size_t stackSize);
/************************************************************************/
/*
* Classes, objects, and properties.
*/
typedef void (*JSClassInternal)();
struct JSClass {
const char *name;
uint32_t flags;
/* Mandatory function pointer members. */
JSPropertyOp addProperty;
JSDeletePropertyOp delProperty;
JSPropertyOp getProperty;
JSStrictPropertyOp setProperty;
JSEnumerateOp enumerate;
JSResolveOp resolve;
JSConvertOp convert;
/* Optional members (may be null). */
JSFinalizeOp finalize;
JSCheckAccessOp checkAccess;
JSNative call;
JSHasInstanceOp hasInstance;
JSNative construct;
JSTraceOp trace;
void *reserved[40];
};
#define JSCLASS_HAS_PRIVATE (1<<0) /* objects have private slot */
#define JSCLASS_NEW_ENUMERATE (1<<1) /* has JSNewEnumerateOp hook */
#define JSCLASS_NEW_RESOLVE (1<<2) /* has JSNewResolveOp hook */
#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) /* private is (nsISupports *) */
#define JSCLASS_IS_DOMJSCLASS (1<<4) /* objects are DOM */
#define JSCLASS_IMPLEMENTS_BARRIERS (1<<5) /* Correctly implements GC read
and write barriers */
#define JSCLASS_EMULATES_UNDEFINED (1<<6) /* objects of this class act
like the value undefined,
in some contexts */
#define JSCLASS_USERBIT1 (1<<7) /* Reserved for embeddings. */
/*
* To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or
* JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where
* n is a constant in [1, 255]. Reserved slots are indexed from 0 to n-1.
*/
#define JSCLASS_RESERVED_SLOTS_SHIFT 8 /* room for 8 flags below */
#define JSCLASS_RESERVED_SLOTS_WIDTH 8 /* and 16 above this field */
#define JSCLASS_RESERVED_SLOTS_MASK JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH)
#define JSCLASS_HAS_RESERVED_SLOTS(n) (((n) & JSCLASS_RESERVED_SLOTS_MASK) \
<< JSCLASS_RESERVED_SLOTS_SHIFT)
#define JSCLASS_RESERVED_SLOTS(clasp) (((clasp)->flags \
>> JSCLASS_RESERVED_SLOTS_SHIFT) \
& JSCLASS_RESERVED_SLOTS_MASK)
#define JSCLASS_HIGH_FLAGS_SHIFT (JSCLASS_RESERVED_SLOTS_SHIFT + \
JSCLASS_RESERVED_SLOTS_WIDTH)
#define JSCLASS_IS_ANONYMOUS (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0))
#define JSCLASS_IS_GLOBAL (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1))
#define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+2))
#define JSCLASS_INTERNAL_FLAG3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
/* Indicate whether the proto or ctor should be frozen. */
#define JSCLASS_FREEZE_PROTO (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
#define JSCLASS_FREEZE_CTOR (1<<(JSCLASS_HIGH_FLAGS_SHIFT+5))
/* Reserved for embeddings. */
#define JSCLASS_USERBIT2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6))
#define JSCLASS_USERBIT3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+7))
#define JSCLASS_BACKGROUND_FINALIZE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+8))
/*
* Bits 26 through 31 are reserved for the CACHED_PROTO_KEY mechanism, see
* below.
*/
/* Global flags. */
#define JSGLOBAL_FLAGS_CLEARED 0x1
/*
* ECMA-262 requires that most constructors used internally create objects
* with "the original Foo.prototype value" as their [[Prototype]] (__proto__)
* member initial value. The "original ... value" verbiage is there because
* in ECMA-262, global properties naming class objects are read/write and
* deleteable, for the most part.
*
* Implementing this efficiently requires that global objects have classes
* with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
* prevously allowed, but is now an ES5 violation and thus unsupported.
*/
#define JSCLASS_GLOBAL_SLOT_COUNT (JSProto_LIMIT * 3 + 26)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \
JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
#define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp) \
(((clasp)->flags & JSCLASS_IS_GLOBAL) \
&& JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
/* Fast access to the original value of each standard class's prototype. */
#define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 10)
#define JSCLASS_CACHED_PROTO_WIDTH 6
#define JSCLASS_CACHED_PROTO_MASK JS_BITMASK(JSCLASS_CACHED_PROTO_WIDTH)
#define JSCLASS_HAS_CACHED_PROTO(key) (uint32_t(key) << JSCLASS_CACHED_PROTO_SHIFT)
#define JSCLASS_CACHED_PROTO_KEY(clasp) ((JSProtoKey) \
(((clasp)->flags \
>> JSCLASS_CACHED_PROTO_SHIFT) \
& JSCLASS_CACHED_PROTO_MASK))
/* Initializer for unused members of statically initialized JSClass structs. */
#define JSCLASS_NO_INTERNAL_MEMBERS {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,JSCLASS_NO_INTERNAL_MEMBERS
extern JS_PUBLIC_API(int)
JS_IdArrayLength(JSContext *cx, JSIdArray *ida);

View File

@ -181,14 +181,16 @@ void
js::MarkAtoms(JSTracer *trc)
{
JSRuntime *rt = trc->runtime;
for (AtomSet::Range r = rt->atoms().all(); !r.empty(); r.popFront()) {
AtomStateEntry entry = r.front();
for (AtomSet::Enum e(rt->atoms()); !e.empty(); e.popFront()) {
const AtomStateEntry &entry = e.front();
if (!entry.isTagged())
continue;
JSAtom *tmp = entry.asPtr();
MarkStringRoot(trc, &tmp, "interned_atom");
JS_ASSERT(tmp == entry.asPtr());
JSAtom *atom = entry.asPtr();
bool tagged = entry.isTagged();
MarkStringRoot(trc, &atom, "interned_atom");
if (entry.asPtr() != atom)
e.rekeyFront(AtomHasher::Lookup(atom), AtomStateEntry(atom, tagged));
}
}

View File

@ -92,6 +92,7 @@ struct AtomHasher
static HashNumber hash(const Lookup &l) { return mozilla::HashString(l.chars, l.length); }
static inline bool match(const AtomStateEntry &entry, const Lookup &lookup);
static void rekey(AtomStateEntry &k, const AtomStateEntry& newKey) { k = newKey; }
};
typedef HashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy> AtomSet;

View File

@ -1,408 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jsclass_h
#define jsclass_h
/*
* A JSClass acts as a vtable for JS objects that allows JSAPI clients to
* control various aspects of the behavior of an object like property lookup.
* js::Class is an engine-private extension that allows more control over
* object behavior and, e.g., allows custom slow layout.
*/
#include "jsapi.h"
namespace js {
class Class;
class FreeOp;
class PropertyId;
class PropertyName;
class Shape;
class SpecialId;
// This is equal to JSFunction::class_. Use it in places where you don't want
// to #include jsfun.h.
extern JS_FRIEND_DATA(js::Class* const) FunctionClassPtr;
static JS_ALWAYS_INLINE jsid
SPECIALID_TO_JSID(const SpecialId &sid);
/*
* We partition the ways to refer to a property into three: by an index
* (uint32_t); by a string whose characters do not represent an index
* (PropertyName, see vm/String.h); and by various special values.
*
* Special values are encoded using SpecialId, which is layout-compatible but
* non-interconvertible with jsid. A SpecialId is used for JSID_VOID, which
* does not occur in JS scripts but may be used to indicate the absence of a
* valid identifier. In the future, a SpecialId may also be an object used by
* Harmony-proposed private names.
*/
class SpecialId
{
uintptr_t bits_;
/* Needs access to raw bits. */
friend JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid);
friend class PropertyId;
static const uintptr_t TYPE_VOID = JSID_TYPE_VOID;
static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT;
static const uintptr_t TYPE_MASK = JSID_TYPE_MASK;
SpecialId(uintptr_t bits) : bits_(bits) { }
public:
SpecialId() : bits_(TYPE_VOID) { }
/* Object-valued */
SpecialId(JSObject &obj)
: bits_(uintptr_t(&obj) | TYPE_OBJECT)
{
JS_ASSERT(&obj != NULL);
JS_ASSERT((uintptr_t(&obj) & TYPE_MASK) == 0);
}
bool isObject() const {
return (bits_ & TYPE_MASK) == TYPE_OBJECT && bits_ != TYPE_OBJECT;
}
JSObject *toObject() const {
JS_ASSERT(isObject());
return reinterpret_cast<JSObject *>(bits_ & ~TYPE_MASK);
}
/* Empty */
static SpecialId empty() {
SpecialId sid(TYPE_OBJECT);
JS_ASSERT(sid.isEmpty());
return sid;
}
bool isEmpty() const {
return bits_ == TYPE_OBJECT;
}
/* Void */
static SpecialId voidId() {
SpecialId sid(TYPE_VOID);
JS_ASSERT(sid.isVoid());
return sid;
}
bool isVoid() const {
return bits_ == TYPE_VOID;
}
};
static JS_ALWAYS_INLINE jsid
SPECIALID_TO_JSID(const SpecialId &sid)
{
jsid id;
JSID_BITS(id) = sid.bits_;
JS_ASSERT_IF(sid.isObject(), JSID_IS_OBJECT(id) && JSID_TO_OBJECT(id) == sid.toObject());
JS_ASSERT_IF(sid.isVoid(), JSID_IS_VOID(id));
JS_ASSERT_IF(sid.isEmpty(), JSID_IS_EMPTY(id));
return id;
}
static JS_ALWAYS_INLINE bool
JSID_IS_SPECIAL(jsid id)
{
return JSID_IS_OBJECT(id) || JSID_IS_EMPTY(id) || JSID_IS_VOID(id);
}
static JS_ALWAYS_INLINE SpecialId
JSID_TO_SPECIALID(jsid id)
{
JS_ASSERT(JSID_IS_SPECIAL(id));
if (JSID_IS_OBJECT(id))
return SpecialId(*JSID_TO_OBJECT(id));
if (JSID_IS_EMPTY(id))
return SpecialId::empty();
JS_ASSERT(JSID_IS_VOID(id));
return SpecialId::voidId();
}
typedef JS::Handle<SpecialId> HandleSpecialId;
/* js::Class operation signatures. */
typedef bool
(* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* LookupPropOp)(JSContext *cx, HandleObject obj, JS::Handle<PropertyName*> name,
MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid,
MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* DefineGenericOp)(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
typedef bool
(* DefinePropOp)(JSContext *cx, HandleObject obj, JS::Handle<PropertyName*> name, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
typedef bool
(* DefineElementOp)(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
typedef bool
(* DefineSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
typedef bool
(* GenericIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, MutableHandleValue vp);
typedef bool
(* PropertyIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, JS::Handle<PropertyName*> name, MutableHandleValue vp);
typedef bool
(* ElementIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, MutableHandleValue vp);
typedef bool
(* ElementIfPresentOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, MutableHandleValue vp, bool* present);
typedef bool
(* SpecialIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, MutableHandleValue vp);
typedef bool
(* StrictGenericIdOp)(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp, bool strict);
typedef bool
(* StrictPropertyIdOp)(JSContext *cx, HandleObject obj, JS::Handle<PropertyName*> name, MutableHandleValue vp, bool strict);
typedef bool
(* StrictElementIdOp)(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp, bool strict);
typedef bool
(* StrictSpecialIdOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, MutableHandleValue vp, bool strict);
typedef bool
(* GenericAttributesOp)(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
typedef bool
(* PropertyAttributesOp)(JSContext *cx, HandleObject obj, JS::Handle<PropertyName*> name, unsigned *attrsp);
typedef bool
(* ElementAttributesOp)(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
typedef bool
(* SpecialAttributesOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp);
typedef bool
(* DeletePropertyOp)(JSContext *cx, HandleObject obj, JS::Handle<PropertyName*> name, bool *succeeded);
typedef bool
(* DeleteElementOp)(JSContext *cx, HandleObject obj, uint32_t index, bool *succeeded);
typedef bool
(* DeleteSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, bool *succeeded);
typedef JSObject *
(* ObjectOp)(JSContext *cx, HandleObject obj);
typedef void
(* FinalizeOp)(FreeOp *fop, JSObject *obj);
#define JS_CLASS_MEMBERS \
const char *name; \
uint32_t flags; \
\
/* Mandatory function pointer members. */ \
JSPropertyOp addProperty; \
JSDeletePropertyOp delProperty; \
JSPropertyOp getProperty; \
JSStrictPropertyOp setProperty; \
JSEnumerateOp enumerate; \
JSResolveOp resolve; \
JSConvertOp convert; \
\
/* Optional members (may be null). */ \
FinalizeOp finalize; \
JSCheckAccessOp checkAccess; \
JSNative call; \
JSHasInstanceOp hasInstance; \
JSNative construct; \
JSTraceOp trace
/*
* The helper struct to measure the size of JS_CLASS_MEMBERS to know how much
* we have to pad js::Class to match the size of JSClass.
*/
struct ClassSizeMeasurement
{
JS_CLASS_MEMBERS;
};
struct ClassExtension
{
JSObjectOp outerObject;
JSObjectOp innerObject;
JSIteratorOp iteratorObject;
/*
* isWrappedNative is true only if the class is an XPCWrappedNative.
* WeakMaps use this to override the wrapper disposal optimization.
*/
bool isWrappedNative;
/*
* If an object is used as a key in a weakmap, it may be desirable for the
* garbage collector to keep that object around longer than it otherwise
* would. A common case is when the key is a wrapper around an object in
* another compartment, and we want to avoid collecting the wrapper (and
* removing the weakmap entry) as long as the wrapped object is alive. In
* that case, the wrapped object is returned by the wrapper's
* weakmapKeyDelegateOp hook. As long as the wrapper is used as a weakmap
* key, it will not be collected (and remain in the weakmap) until the
* wrapped object is collected.
*/
JSWeakmapKeyDelegateOp weakmapKeyDelegateOp;
};
#define JS_NULL_CLASS_EXT {NULL,NULL,NULL,false,NULL}
struct ObjectOps
{
LookupGenericOp lookupGeneric;
LookupPropOp lookupProperty;
LookupElementOp lookupElement;
LookupSpecialOp lookupSpecial;
DefineGenericOp defineGeneric;
DefinePropOp defineProperty;
DefineElementOp defineElement;
DefineSpecialOp defineSpecial;
GenericIdOp getGeneric;
PropertyIdOp getProperty;
ElementIdOp getElement;
ElementIfPresentOp getElementIfPresent; /* can be null */
SpecialIdOp getSpecial;
StrictGenericIdOp setGeneric;
StrictPropertyIdOp setProperty;
StrictElementIdOp setElement;
StrictSpecialIdOp setSpecial;
GenericAttributesOp getGenericAttributes;
PropertyAttributesOp getPropertyAttributes;
ElementAttributesOp getElementAttributes;
SpecialAttributesOp getSpecialAttributes;
GenericAttributesOp setGenericAttributes;
PropertyAttributesOp setPropertyAttributes;
ElementAttributesOp setElementAttributes;
SpecialAttributesOp setSpecialAttributes;
DeletePropertyOp deleteProperty;
DeleteElementOp deleteElement;
DeleteSpecialOp deleteSpecial;
JSNewEnumerateOp enumerate;
ObjectOp thisObject;
};
#define JS_NULL_OBJECT_OPS \
{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL}
struct Class
{
JS_CLASS_MEMBERS;
ClassExtension ext;
ObjectOps ops;
uint8_t pad[sizeof(JSClass) - sizeof(ClassSizeMeasurement) -
sizeof(ClassExtension) - sizeof(ObjectOps)];
/* Class is not native and its map is not a scope. */
static const uint32_t NON_NATIVE = JSCLASS_INTERNAL_FLAG2;
bool isNative() const {
return !(flags & NON_NATIVE);
}
bool hasPrivate() const {
return !!(flags & JSCLASS_HAS_PRIVATE);
}
bool emulatesUndefined() const {
return flags & JSCLASS_EMULATES_UNDEFINED;
}
bool isCallable() const {
return this == js::FunctionClassPtr || call;
}
static size_t offsetOfFlags() { return offsetof(Class, flags); }
};
JS_STATIC_ASSERT(offsetof(JSClass, name) == offsetof(Class, name));
JS_STATIC_ASSERT(offsetof(JSClass, flags) == offsetof(Class, flags));
JS_STATIC_ASSERT(offsetof(JSClass, addProperty) == offsetof(Class, addProperty));
JS_STATIC_ASSERT(offsetof(JSClass, delProperty) == offsetof(Class, delProperty));
JS_STATIC_ASSERT(offsetof(JSClass, getProperty) == offsetof(Class, getProperty));
JS_STATIC_ASSERT(offsetof(JSClass, setProperty) == offsetof(Class, setProperty));
JS_STATIC_ASSERT(offsetof(JSClass, enumerate) == offsetof(Class, enumerate));
JS_STATIC_ASSERT(offsetof(JSClass, resolve) == offsetof(Class, resolve));
JS_STATIC_ASSERT(offsetof(JSClass, convert) == offsetof(Class, convert));
JS_STATIC_ASSERT(offsetof(JSClass, finalize) == offsetof(Class, finalize));
JS_STATIC_ASSERT(offsetof(JSClass, checkAccess) == offsetof(Class, checkAccess));
JS_STATIC_ASSERT(offsetof(JSClass, call) == offsetof(Class, call));
JS_STATIC_ASSERT(offsetof(JSClass, construct) == offsetof(Class, construct));
JS_STATIC_ASSERT(offsetof(JSClass, hasInstance) == offsetof(Class, hasInstance));
JS_STATIC_ASSERT(offsetof(JSClass, trace) == offsetof(Class, trace));
JS_STATIC_ASSERT(sizeof(JSClass) == sizeof(Class));
static JS_ALWAYS_INLINE JSClass *
Jsvalify(Class *c)
{
return (JSClass *)c;
}
static JS_ALWAYS_INLINE const JSClass *
Jsvalify(const Class *c)
{
return (const JSClass *)c;
}
static JS_ALWAYS_INLINE Class *
Valueify(JSClass *c)
{
return (Class *)c;
}
static JS_ALWAYS_INLINE const Class *
Valueify(const JSClass *c)
{
return (const Class *)c;
}
/*
* Enumeration describing possible values of the [[Class]] internal property
* value of objects.
*/
enum ESClassValue {
ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean,
ESClass_RegExp, ESClass_ArrayBuffer, ESClass_Date
};
/*
* Return whether the given object has the given [[Class]] internal property
* value. Beware, this query says nothing about the js::Class of the JSObject
* so the caller must not assume anything about obj's representation (e.g., obj
* may be a proxy).
*/
inline bool
ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx);
/* Just a helper that checks v.isObject before calling ObjectClassIs. */
inline bool
IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx);
inline bool
IsPoisonedSpecialId(js::SpecialId iden)
{
if (iden.isObject())
return IsPoisonedPtr(iden.toObject());
return false;
}
template <> struct GCMethods<SpecialId>
{
static SpecialId initial() { return SpecialId(); }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(SpecialId id) { return IsPoisonedSpecialId(id); }
};
} /* namespace js */
#endif /* jsclass_h */

View File

@ -83,10 +83,8 @@ struct CrossCompartmentKey
: kind(kind), debugger(dbg), wrapped(wrapped) {}
};
struct WrapperHasher
struct WrapperHasher : public DefaultHasher<CrossCompartmentKey>
{
typedef CrossCompartmentKey Lookup;
static HashNumber hash(const CrossCompartmentKey &key) {
JS_ASSERT(!IsPoisonedPtr(key.wrapped));
return uint32_t(uintptr_t(key.wrapped)) | uint32_t(key.kind);

View File

@ -11,8 +11,8 @@
#include "mozilla/MemoryReporting.h"
#endif
#include "jsapi.h"
#include "jsbytecode.h"
#include "jsclass.h"
#include "jspubtd.h"
#include "js/CallArgs.h"
@ -240,7 +240,7 @@ typedef bool
extern JS_FRIEND_API(void)
DumpHeapComplete(JSRuntime *rt, FILE *fp);
#ifdef OLD_GETTER_SETTER_METHODS
#ifdef JS_OLD_GETTER_SETTER_METHODS
JS_FRIEND_API(bool) obj_defineGetter(JSContext *cx, unsigned argc, js::Value *vp);
JS_FRIEND_API(bool) obj_defineSetter(JSContext *cx, unsigned argc, js::Value *vp);
#endif

View File

@ -3042,7 +3042,7 @@ GetValueTypeForTable(const Value &v)
return type;
}
struct types::ArrayTableKey
struct types::ArrayTableKey : public DefaultHasher<types::ArrayTableKey>
{
Type type;
JSObject *proto;
@ -3051,8 +3051,6 @@ struct types::ArrayTableKey
: type(Type::UndefinedType()), proto(NULL)
{}
typedef ArrayTableKey Lookup;
static inline uint32_t hash(const ArrayTableKey &v) {
return (uint32_t) (v.type.raw() ^ ((uint32_t)(size_t)v.proto >> 2));
}

View File

@ -1106,7 +1106,7 @@ struct TypeObject : gc::Cell
* Entries for the per-compartment set of type objects which are the default
* 'new' or the lazy types of some prototype.
*/
struct TypeObjectEntry
struct TypeObjectEntry : DefaultHasher<ReadBarriered<TypeObject> >
{
struct Lookup {
Class *clasp;

View File

@ -764,7 +764,7 @@ TypeScript::StandardType(JSContext *cx, JSProtoKey key)
return cx->getNewType(GetClassForProtoKey(key), proto.get());
}
struct AllocationSiteKey {
struct AllocationSiteKey : public DefaultHasher<AllocationSiteKey> {
JSScript *script;
uint32_t offset : 24;
@ -774,8 +774,6 @@ struct AllocationSiteKey {
AllocationSiteKey() { mozilla::PodZero(this); }
typedef AllocationSiteKey Lookup;
static inline uint32_t hash(AllocationSiteKey key) {
return uint32_t(size_t(key.script->code + key.offset)) ^ key.kind;
}

View File

@ -1112,7 +1112,7 @@ extern const char js_hasOwnProperty_str[];
extern const char js_isPrototypeOf_str[];
extern const char js_propertyIsEnumerable_str[];
#ifdef OLD_GETTER_SETTER_METHODS
#ifdef JS_OLD_GETTER_SETTER_METHODS
extern const char js_defineGetter_str[];
extern const char js_defineSetter_str[];
extern const char js_lookupGetter_str[];

View File

@ -149,7 +149,7 @@ class JS_FRIEND_API(BaseProxyHandler)
uint32_t index, MutableHandleValue vp, bool *present);
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
/* See comment for weakmapKeyDelegateOp in jsclass.h. */
/* See comment for weakmapKeyDelegateOp in js/Class.h. */
virtual JSObject *weakmapKeyDelegate(JSObject *proxy);
};

View File

@ -17,6 +17,8 @@
#include "jstypes.h"
#include "jsversion.h" // #include here so it's seen everywhere
#include "js/IdForward.h"
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING) || defined(DEBUG)
# define JSGC_TRACK_EXACT_ROOTS
#endif
@ -44,38 +46,6 @@ struct Zone;
} /* namespace JS */
/*
* In release builds, jsid is defined to be an integral type. This
* prevents many bugs from being caught at compile time. E.g.:
*
* jsid id = ...
* if (id) // error
* ...
*
* size_t n = id; // error
*
* To catch more errors, jsid is given a struct type in C++ debug builds.
* Struct assignment and (in C++) operator== allow correct code to be mostly
* oblivious to the change. This feature can be explicitly disabled in debug
* builds by defining JS_NO_JSVAL_JSID_STRUCT_TYPES.
*/
# if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
# define JS_USE_JSID_STRUCT_TYPES
# endif
# ifdef JS_USE_JSID_STRUCT_TYPES
struct jsid
{
size_t asBits;
bool operator==(jsid rhs) const { return asBits == rhs.asBits; }
bool operator!=(jsid rhs) const { return asBits != rhs.asBits; }
};
# define JSID_BITS(id) (id.asBits)
# else /* defined(JS_USE_JSID_STRUCT_TYPES) */
typedef ptrdiff_t jsid;
# define JSID_BITS(id) (id)
# endif /* defined(JS_USE_JSID_STRUCT_TYPES) */
#ifdef WIN32
typedef wchar_t jschar;
#else

View File

@ -37,7 +37,6 @@
#include "jsopcode.h"
#include "jstypes.h"
#include "jsutil.h"
#include "jsversion.h"
#include "builtin/RegExp.h"
#include "vm/GlobalObject.h"

View File

@ -24,7 +24,14 @@
#include "mozilla/Attributes.h"
#include "mozilla/Types.h"
// jstypes.h is (or should be!) included by every file in SpiderMonkey.
// js-config.h and jsversion.h also should be included by every file.
// So include them here.
// XXX: including them in js/RequiredDefines.h should be a better option, since
// that is by definition the header file that should be included in all
// SpiderMonkey code. However, Gecko doesn't do this! See bug 909576.
#include "js-config.h"
#include "jsversion.h"
/***********************************************************************
** MACROS: JS_EXTERN_API

View File

@ -7,19 +7,6 @@
#ifndef jsversion_h
#define jsversion_h
/*
* Deprecated JS_VERSION handler.
*/
#ifdef JS_VERSION
# if JS_VERSION == 185
# warning "JS_VERSION defined but unsupported (legacy)"
# elif JS_VERSION < 185
# error "Unsupported JS_VERSION"
# else
# error "Unknown JS_VERSION"
# endif
#endif
/*
* JS Capability Macros.
*/
@ -52,15 +39,15 @@
* Feature for Object.prototype.__{define,lookup}{G,S}etter__ legacy support;
* support likely to be made opt-in at some future time.
*/
#define OLD_GETTER_SETTER_METHODS 1
#define JS_OLD_GETTER_SETTER_METHODS 1
/* A kill-switch for bug 586842. Embedders shouldn't touch this! */
#define USE_NEW_OBJECT_REPRESENTATION 0
#define JS_USE_NEW_OBJECT_REPRESENTATION 0
#if USE_NEW_OBJECT_REPRESENTATION
# define NEW_OBJECT_REPRESENTATION_ONLY() ((void)0)
#if JS_USE_NEW_OBJECT_REPRESENTATION
# define JS_NEW_OBJECT_REPRESENTATION_ONLY() ((void)0)
#else
# define NEW_OBJECT_REPRESENTATION_ONLY() \
# define JS_NEW_OBJECT_REPRESENTATION_ONLY() \
MOZ_ASSUME_UNREACHABLE("don't call this! to be used in the new object representation")
#endif

View File

@ -37,13 +37,19 @@ struct Watchpoint {
};
template <>
struct DefaultHasher<WatchKey> {
struct DefaultHasher<WatchKey>
{
typedef WatchKey Lookup;
static inline js::HashNumber hash(const Lookup &key);
static bool match(const WatchKey &k, const Lookup &l) {
return k.object == l.object && k.id.get() == l.id.get();
}
static void rekey(WatchKey &k, const WatchKey& newKey) {
k.object.unsafeSet(newKey.object);
k.id.unsafeSet(newKey.id);
}
};
class WatchpointMap {

View File

@ -180,19 +180,20 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
bool markedAny = false;
for (Enum e(*this); !e.empty(); e.popFront()) {
/* If the entry is live, ensure its key and value are marked. */
Key prior(e.front().key);
if (gc::IsMarked(const_cast<Key *>(&e.front().key))) {
Key key(e.front().key);
if (gc::IsMarked(const_cast<Key *>(&key))) {
if (markValue(trc, &e.front().value))
markedAny = true;
if (prior != e.front().key)
e.rekeyFront(e.front().key);
} else if (keyNeedsMark(e.front().key)) {
gc::Mark(trc, const_cast<Key *>(&e.front().key), "proxy-preserved WeakMap entry key");
if (prior != e.front().key)
e.rekeyFront(e.front().key);
if (e.front().key != key)
e.rekeyFront(key);
} else if (keyNeedsMark(key)) {
gc::Mark(trc, const_cast<Key *>(&key), "proxy-preserved WeakMap entry key");
if (e.front().key != key)
e.rekeyFront(key);
gc::Mark(trc, &e.front().value, "WeakMap entry value");
markedAny = true;
}
key.unsafeSet(NULL);
}
return markedAny;
}

View File

@ -35,7 +35,6 @@ EXPORTS += [
'jsalloc.h',
'jsapi.h',
'jsbytecode.h',
'jsclass.h',
'jsclist.h',
'jscpucfg.h',
'jsdbgapi.h',
@ -62,10 +61,13 @@ EXPORTS.js += [
'../public/Anchor.h',
'../public/CallArgs.h',
'../public/CharacterEncoding.h',
'../public/Class.h',
'../public/Date.h',
'../public/GCAPI.h',
'../public/HashTable.h',
'../public/HeapAPI.h',
'../public/Id.h',
'../public/IdForward.h',
'../public/LegacyIntTypes.h',
'../public/MemoryMetrics.h',
'../public/ProfilingStack.h',
@ -91,6 +93,7 @@ CPP_SOURCES += [
'FoldConstants.cpp',
'ForkJoin.cpp',
'GlobalObject.cpp',
'Id.cpp',
'Interpreter.cpp',
'Intl.cpp',
'Iteration.cpp',

View File

@ -10,7 +10,6 @@
#define vm_CommonPropertyNames_h
#include "jsprototypes.h"
#include "jsversion.h"
#define FOR_EACH_COMMON_PROPERTYNAME(macro) \
macro(anonymous, anonymous, "anonymous") \

View File

@ -58,6 +58,7 @@ class DebuggerWeakMap : private WeakMap<Key, Value, DefaultHasher<Key> >
public:
/* Expose those parts of HashMap public interface that are used by Debugger methods. */
typedef typename Base::Entry Entry;
typedef typename Base::Ptr Ptr;
typedef typename Base::AddPtr AddPtr;
typedef typename Base::Range Range;
@ -104,10 +105,12 @@ class DebuggerWeakMap : private WeakMap<Key, Value, DefaultHasher<Key> >
public:
void markKeys(JSTracer *tracer) {
for (Range r = all(); !r.empty(); r.popFront()) {
Key key = r.front().key;
gc::Mark(tracer, &key, "cross-compartment WeakMap key");
JS_ASSERT(key == r.front().key);
for (Enum e(*static_cast<Base *>(this)); !e.empty(); e.popFront()) {
Key key = e.front().key;
gc::Mark(tracer, &key, "Debugger WeakMap key");
if (key != e.front().key)
e.rekeyFront(key);
key.unsafeSet(NULL);
}
}

13
js/src/vm/Id.cpp Normal file
View File

@ -0,0 +1,13 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "js/Id.h"
#ifdef JS_USE_JSID_STRUCT_TYPES
const jsid JSID_VOID = { size_t(JSID_TYPE_VOID) };
const jsid JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
#endif

View File

@ -9,8 +9,6 @@
#ifndef vm_Keywords_h
#define vm_Keywords_h
#include "jsversion.h"
#if JS_HAS_CONST
# define FOR_CONST_KEYWORD(macro) \
macro(const, const_, TOK_CONST, JSVERSION_DEFAULT)

View File

@ -561,7 +561,7 @@ bool
js::GetOwnProperty(JSContext *cx, Handle<ObjectImpl*> obj, PropertyId pid_, unsigned resolveFlags,
PropDesc *desc)
{
NEW_OBJECT_REPRESENTATION_ONLY();
JS_NEW_OBJECT_REPRESENTATION_ONLY();
JS_CHECK_RECURSION(cx, return false);
@ -651,7 +651,7 @@ bool
js::GetProperty(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> receiver,
Handle<PropertyId> pid, unsigned resolveFlags, MutableHandle<Value> vp)
{
NEW_OBJECT_REPRESENTATION_ONLY();
JS_NEW_OBJECT_REPRESENTATION_ONLY();
MOZ_ASSERT(receiver);
@ -714,7 +714,7 @@ bool
js::GetElement(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> receiver, uint32_t index,
unsigned resolveFlags, Value *vp)
{
NEW_OBJECT_REPRESENTATION_ONLY();
JS_NEW_OBJECT_REPRESENTATION_ONLY();
Rooted<ObjectImpl*> current(cx, obj);
@ -777,7 +777,7 @@ bool
js::HasElement(JSContext *cx, Handle<ObjectImpl*> obj, uint32_t index, unsigned resolveFlags,
bool *found)
{
NEW_OBJECT_REPRESENTATION_ONLY();
JS_NEW_OBJECT_REPRESENTATION_ONLY();
Rooted<ObjectImpl*> current(cx, obj);
@ -811,7 +811,7 @@ bool
js::DefineElement(JSContext *cx, Handle<ObjectImpl*> obj, uint32_t index, const PropDesc &desc,
bool shouldThrow, unsigned resolveFlags, bool *succeeded)
{
NEW_OBJECT_REPRESENTATION_ONLY();
JS_NEW_OBJECT_REPRESENTATION_ONLY();
ElementsHeader &header = obj->elementsHeader();
@ -937,7 +937,7 @@ bool
js::SetElement(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> receiver,
uint32_t index, const Value &v, unsigned resolveFlags, bool *succeeded)
{
NEW_OBJECT_REPRESENTATION_ONLY();
JS_NEW_OBJECT_REPRESENTATION_ONLY();
Rooted<ObjectImpl*> current(cx, obj);
RootedValue setter(cx);

View File

@ -1284,7 +1284,7 @@ class ObjectImpl : public gc::Cell
}
bool makeElementsSparse(JSContext *cx) {
NEW_OBJECT_REPRESENTATION_ONLY();
JS_NEW_OBJECT_REPRESENTATION_ONLY();
MOZ_ASSUME_UNREACHABLE("NYI");
}
@ -1412,7 +1412,7 @@ class ObjectImpl : public gc::Cell
DenseElementsResult ensureDenseElementsInitialized(JSContext *cx, uint32_t index,
uint32_t extra)
{
NEW_OBJECT_REPRESENTATION_ONLY();
JS_NEW_OBJECT_REPRESENTATION_ONLY();
MOZ_ASSUME_UNREACHABLE("NYI");
}
@ -1623,7 +1623,7 @@ class ObjectImpl : public gc::Cell
}
ElementsHeader & elementsHeader() const {
NEW_OBJECT_REPRESENTATION_ONLY();
JS_NEW_OBJECT_REPRESENTATION_ONLY();
return *ElementsHeader::fromElements(elements);
}

View File

@ -972,6 +972,7 @@ struct InitialShapeEntry
static inline HashNumber hash(const Lookup &lookup);
static inline bool match(const InitialShapeEntry &key, const Lookup &lookup);
static void rekey(InitialShapeEntry &k, const InitialShapeEntry& newKey) { k = newKey; }
};
typedef HashSet<InitialShapeEntry, InitialShapeEntry, SystemAllocPolicy> InitialShapeSet;

View File

@ -23,7 +23,6 @@
#include "jsobj.h"
#include "jstypes.h"
#include "jsutil.h"
#include "jsversion.h"
#ifdef XP_WIN
# include "jswin.h"
#endif
@ -43,7 +42,7 @@
#include "vm/GlobalObject-inl.h"
#if USE_NEW_OBJECT_REPRESENTATION
#if JS_USE_NEW_OBJECT_REPRESENTATION
// See the comment above OldObjectRepresentationHack.
# error "TypedArray support for new object representation unimplemented."
#endif
@ -294,7 +293,7 @@ PostBarrierTypedArrayObject(JSObject *obj)
// the slots are already being used for the element storage and the private
// field is used for a delegate object. The ObjectElements header has space
// for it, but I don't want to mess around with adding unions to it with
// USE_NEW_OBJECT_REPRESENTATION pending, since it will solve this much
// JS_USE_NEW_OBJECT_REPRESENTATION pending, since it will solve this much
// more cleanly.
struct OldObjectRepresentationHack {
uint32_t capacity;

View File

@ -8,9 +8,10 @@
#define vm_TypedArrayObject_h
#include "jsapi.h"
#include "jsclass.h"
#include "jsobj.h"
#include "js/Class.h"
typedef struct JSProperty JSProperty;
namespace js {

View File

@ -273,6 +273,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormData)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBlobProtocolHandler)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMediaStreamProtocolHandler)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMediaSourceProtocolHandler)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFontTableProtocolHandler)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHostObjectURI)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMParser)
NS_GENERIC_FACTORY_CONSTRUCTOR(DOMSessionStorageManager)
@ -736,6 +737,7 @@ NS_DEFINE_NAMED_CID(NS_FORMDATA_CID);
NS_DEFINE_NAMED_CID(NS_BLOBPROTOCOLHANDLER_CID);
NS_DEFINE_NAMED_CID(NS_MEDIASTREAMPROTOCOLHANDLER_CID);
NS_DEFINE_NAMED_CID(NS_MEDIASOURCEPROTOCOLHANDLER_CID);
NS_DEFINE_NAMED_CID(NS_FONTTABLEPROTOCOLHANDLER_CID);
NS_DEFINE_NAMED_CID(NS_HOSTOBJECTURI_CID);
NS_DEFINE_NAMED_CID(NS_XMLHTTPREQUEST_CID);
NS_DEFINE_NAMED_CID(NS_EVENTSOURCE_CID);
@ -1025,6 +1027,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_BLOBPROTOCOLHANDLER_CID, false, NULL, nsBlobProtocolHandlerConstructor },
{ &kNS_MEDIASTREAMPROTOCOLHANDLER_CID, false, NULL, nsMediaStreamProtocolHandlerConstructor },
{ &kNS_MEDIASOURCEPROTOCOLHANDLER_CID, false, NULL, nsMediaSourceProtocolHandlerConstructor },
{ &kNS_FONTTABLEPROTOCOLHANDLER_CID, false, NULL, nsFontTableProtocolHandlerConstructor },
{ &kNS_HOSTOBJECTURI_CID, false, NULL, nsHostObjectURIConstructor },
{ &kNS_XMLHTTPREQUEST_CID, false, NULL, nsXMLHttpRequestConstructor },
{ &kNS_EVENTSOURCE_CID, false, NULL, EventSourceConstructor },
@ -1181,6 +1184,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX BLOBURI_SCHEME, &kNS_BLOBPROTOCOLHANDLER_CID },
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASTREAMURI_SCHEME, &kNS_MEDIASTREAMPROTOCOLHANDLER_CID },
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASOURCEURI_SCHEME, &kNS_MEDIASOURCEPROTOCOLHANDLER_CID },
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX FONTTABLEURI_SCHEME, &kNS_FONTTABLEPROTOCOLHANDLER_CID },
{ NS_XMLHTTPREQUEST_CONTRACTID, &kNS_XMLHTTPREQUEST_CID },
{ NS_EVENTSOURCE_CONTRACTID, &kNS_EVENTSOURCE_CID },
{ NS_DOMACTIVITY_CONTRACTID, &kNS_DOMACTIVITY_CID },

View File

@ -119,6 +119,8 @@ using namespace mozilla::system;
#include "nsDocument.h"
#include "mozilla/dom/HTMLVideoElement.h"
extern void NS_ShutdownEventTargetChainRecycler();
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::dom::ipc;
@ -376,6 +378,8 @@ nsLayoutStatics::Shutdown()
nsRegion::ShutdownStatic();
NS_ShutdownEventTargetChainRecycler();
HTMLInputElement::DestroyUploadLastDir();
nsLayoutUtils::Shutdown();

View File

@ -16,6 +16,7 @@
#include "nsDisplayList.h"
#include "nsCSSFrameConstructor.h"
#include "nsFrameManager.h"
#include "gfxPlatform.h"
// for focus
#include "nsIScrollableFrame.h"
@ -217,13 +218,32 @@ nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
// to snap for this context, because we checked HasNonIntegerTranslation above.
destRect.Round();
surf = static_cast<gfxASurface*>(Frame()->Properties().Get(nsIFrame::CachedBackgroundImage()));
nsRefPtr<gfxASurface> destSurf = dest->CurrentSurface();
if (surf && surf->GetType() == destSurf->GetType()) {
BlitSurface(dest, destRect, surf);
return;
if (dest->IsCairo()) {
nsRefPtr<gfxASurface> destSurf = dest->CurrentSurface();
if (surf && surf->GetType() == destSurf->GetType()) {
BlitSurface(dest, destRect, surf);
return;
}
surf = destSurf->CreateSimilarSurface(
gfxASurface::CONTENT_COLOR_ALPHA,
gfxIntSize(ceil(destRect.width), ceil(destRect.height)));
} else {
if (surf) {
mozilla::gfx::DrawTarget* dt = dest->GetDrawTarget();
mozilla::RefPtr<mozilla::gfx::SourceSurface> source =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, surf);
if (source) {
// Could be non-integer pixel alignment
dt->DrawSurface(source,
mozilla::gfx::Rect(destRect.x, destRect.y, destRect.width, destRect.height),
mozilla::gfx::Rect(0, 0, destRect.width, destRect.height));
return;
}
}
surf = gfxPlatform::GetPlatform()->CreateOffscreenImageSurface(
gfxIntSize(ceil(destRect.width), ceil(destRect.height)),
gfxASurface::CONTENT_COLOR_ALPHA);
}
surf = destSurf->CreateSimilarSurface(gfxASurface::CONTENT_COLOR_ALPHA,
gfxIntSize(destRect.width, destRect.height));
if (surf) {
ctx = new gfxContext(surf);
ctx->Translate(-gfxPoint(destRect.x, destRect.y));

Some files were not shown because too many files have changed in this diff Show More