mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge latest green b2g-inbound changeset and mozilla-central
This commit is contained in:
commit
d4ffac9dcd
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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 ---------------------------------------------------------- */
|
||||
|
||||
|
BIN
browser/metro/theme/images/progresscircle-bg.png
Normal file
BIN
browser/metro/theme/images/progresscircle-bg.png
Normal file
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 |
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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;
|
||||
|
@ -812,6 +812,7 @@ protected:
|
||||
bool mAllowMedia;
|
||||
bool mAllowDNSPrefetch;
|
||||
bool mAllowWindowControl;
|
||||
bool mAllowContentRetargeting;
|
||||
bool mCreatingDocument; // (should be) debugging only
|
||||
bool mUseErrorPages;
|
||||
bool mObserveErrorPages;
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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)
|
||||
|
7
docshell/test/chrome/allowContentRetargeting.sjs
Normal file
7
docshell/test/chrome/allowContentRetargeting.sjs
Normal 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");
|
||||
}
|
94
docshell/test/chrome/test_allowContentRetargeting.html
Normal file
94
docshell/test/chrome/test_allowContentRetargeting.html
Normal 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>
|
@ -11,6 +11,7 @@
|
||||
#include "nsIXPCScriptable.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "js/Id.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef GetClassName
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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/.
|
||||
|
@ -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>
|
||||
|
@ -13,5 +13,3 @@ DIRS += [
|
||||
'geolocation',
|
||||
'notification',
|
||||
]
|
||||
|
||||
TEST_DIRS += ['foo']
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -57,6 +57,8 @@ private:
|
||||
nsCOMPtr<nsIPresShell> mPresShell;
|
||||
|
||||
nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
|
||||
|
||||
nsAutoCString mSVGGlyphsDocumentURI;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -1,6 +1,8 @@
|
||||
include protocol PTestDataStructuresSub;
|
||||
include PTestDataStructuresCommon;
|
||||
|
||||
include "mozilla/GfxMessageUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
721
js/public/Class.h
Normal 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 */
|
@ -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
150
js/public/Id.h
Normal 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
55
js/public/IdForward.h
Normal 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 */
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "js/IdForward.h"
|
||||
#include "js/Utility.h"
|
||||
|
||||
/*
|
||||
|
@ -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),
|
||||
|
@ -217,7 +217,7 @@ struct FieldInfo
|
||||
};
|
||||
|
||||
// Hash policy for FieldInfos.
|
||||
struct FieldHashPolicy
|
||||
struct FieldHashPolicy : DefaultHasher<JSFlatString*>
|
||||
{
|
||||
typedef JSFlatString* Key;
|
||||
typedef Key Lookup;
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "jsopcode.h"
|
||||
#include "jsscript.h"
|
||||
#include "jstypes.h"
|
||||
#include "jsversion.h"
|
||||
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "frontend/FoldConstants.h"
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsversion.h"
|
||||
|
||||
#include "js/Vector.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -245,8 +245,9 @@
|
||||
_(AsmJSCall) \
|
||||
_(AsmJSCheckOverRecursed) \
|
||||
_(CheckInterruptPar) \
|
||||
_(RangeAssert) \
|
||||
_(DoubleRangeAssert)
|
||||
_(AssertRangeI) \
|
||||
_(AssertRangeD) \
|
||||
_(AssertRangeV)
|
||||
|
||||
#if defined(JS_CPU_X86)
|
||||
# include "jit/x86/LOpcodes-x86.h"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -74,6 +74,7 @@ namespace ion {
|
||||
_(Unbox) \
|
||||
_(GuardObject) \
|
||||
_(GuardString) \
|
||||
_(AssertRange) \
|
||||
_(ToDouble) \
|
||||
_(ToInt32) \
|
||||
_(TruncateToInt32) \
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -81,6 +81,7 @@ class RangeAnalysis
|
||||
graph_(graph) {}
|
||||
bool addBetaNobes();
|
||||
bool analyze();
|
||||
bool addRangeAssertions();
|
||||
bool removeBetaNobes();
|
||||
bool truncate();
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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_},
|
||||
|
461
js/src/jsapi.h
461
js/src/jsapi.h
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
408
js/src/jsclass.h
408
js/src/jsclass.h
@ -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 */
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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[];
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -37,7 +37,6 @@
|
||||
#include "jsopcode.h"
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsversion.h"
|
||||
|
||||
#include "builtin/RegExp.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -10,7 +10,6 @@
|
||||
#define vm_CommonPropertyNames_h
|
||||
|
||||
#include "jsprototypes.h"
|
||||
#include "jsversion.h"
|
||||
|
||||
#define FOR_EACH_COMMON_PROPERTYNAME(macro) \
|
||||
macro(anonymous, anonymous, "anonymous") \
|
||||
|
@ -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
13
js/src/vm/Id.cpp
Normal 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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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 },
|
||||
|
@ -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();
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user