зеркало из https://github.com/mozilla/gecko-dev.git
Merge latest green b2g-inbound changeset and mozilla-central
This commit is contained in:
Коммит
f5a01c7e10
|
@ -223,7 +223,8 @@ if test "$GNU_CC"; then
|
||||||
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
|
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
|
||||||
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
|
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
|
||||||
fi
|
fi
|
||||||
CXXFLAGS="$CXXFLAGS -fno-exceptions"
|
CFLAGS="$CFLAGS -fno-math-errno"
|
||||||
|
CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
|
|
17
configure.in
17
configure.in
|
@ -9227,19 +9227,32 @@ fi
|
||||||
dist=$MOZ_BUILD_ROOT/dist
|
dist=$MOZ_BUILD_ROOT/dist
|
||||||
ac_configure_args="$_SUBDIR_CONFIG_ARGS"
|
ac_configure_args="$_SUBDIR_CONFIG_ARGS"
|
||||||
ac_configure_args="$ac_configure_args --enable-threadsafe"
|
ac_configure_args="$ac_configure_args --enable-threadsafe"
|
||||||
|
|
||||||
|
MOZ_ARG_WITH_STRING(intl-api,
|
||||||
|
[ --with-intl-api, --with-intl-api=build, --without-intl-api
|
||||||
|
Determine the status of the ECMAScript Internationalization API. The first
|
||||||
|
(or lack of any of these) builds and exposes the API. The second builds it
|
||||||
|
but doesn't use ICU or expose the API to script. The third doesn't build
|
||||||
|
ICU at all.],
|
||||||
|
WITH_INTL="--with-intl-api=$withval"
|
||||||
|
])
|
||||||
|
if test -z "$WITH_INTL"; then
|
||||||
if test "$NIGHTLY_BUILD" = "1" -a "$MOZ_BUILD_APP" = "browser"; then
|
if test "$NIGHTLY_BUILD" = "1" -a "$MOZ_BUILD_APP" = "browser"; then
|
||||||
# In desktop nightlies the Internationalization API is disabled, but all
|
# In desktop nightlies the Internationalization API is disabled, but all
|
||||||
# code for it is still built. Bug 853301 will remove this so that it's
|
# code for it is still built. Bug 853301 will remove this so that it's
|
||||||
# built and the API is enabled.
|
# built and the API is enabled.
|
||||||
ac_configure_args="$ac_configure_args --with-intl-api=build"
|
WITH_INTL="--with-intl-api=build"
|
||||||
else
|
else
|
||||||
# Internationalization isn't built or exposed by default in non-desktop and
|
# Internationalization isn't built or exposed by default in non-desktop and
|
||||||
# non-nightly builds. Bugs to enable:
|
# non-nightly builds. Bugs to enable:
|
||||||
#
|
#
|
||||||
# Android: bug 864843
|
# Android: bug 864843
|
||||||
# B2G: bug 866301
|
# B2G: bug 866301
|
||||||
ac_configure_args="$ac_configure_args --without-intl-api"
|
WITH_INTL="--without-intl-api"
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
ac_configure_args="$ac_configure_args $WITH_INTL"
|
||||||
|
|
||||||
if test "$BUILD_CTYPES"; then
|
if test "$BUILD_CTYPES"; then
|
||||||
# Build js-ctypes on the platforms we can.
|
# Build js-ctypes on the platforms we can.
|
||||||
ac_configure_args="$ac_configure_args --enable-ctypes"
|
ac_configure_args="$ac_configure_args --enable-ctypes"
|
||||||
|
|
|
@ -149,6 +149,7 @@ protected:
|
||||||
|
|
||||||
nsString mContentType;
|
nsString mContentType;
|
||||||
nsString mName;
|
nsString mName;
|
||||||
|
nsString mPath; // The path relative to a directory chosen by the user
|
||||||
|
|
||||||
uint64_t mStart;
|
uint64_t mStart;
|
||||||
uint64_t mLength;
|
uint64_t mLength;
|
||||||
|
@ -300,6 +301,8 @@ public:
|
||||||
NS_IMETHOD GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE;
|
NS_IMETHOD GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE;
|
||||||
NS_IMETHOD GetInternalStream(nsIInputStream**) MOZ_OVERRIDE;
|
NS_IMETHOD GetInternalStream(nsIInputStream**) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
void SetPath(const nsAString& aFullPath);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Create slice
|
// Create slice
|
||||||
nsDOMFileFile(const nsDOMFileFile* aOther, uint64_t aStart, uint64_t aLength,
|
nsDOMFileFile(const nsDOMFileFile* aOther, uint64_t aStart, uint64_t aLength,
|
||||||
|
|
|
@ -59,11 +59,13 @@ interface nsIDOMBlob : nsISupports
|
||||||
[notxpcom] FileInfo getFileInfo(in FileManager aFileManager);
|
[notxpcom] FileInfo getFileInfo(in FileManager aFileManager);
|
||||||
};
|
};
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(6928584d-7d87-4d56-9ce1-1c89c24f2c6a)]
|
[scriptable, builtinclass, uuid(0acb4135-9f79-4516-ba92-b5fba5203620)]
|
||||||
interface nsIDOMFile : nsIDOMBlob
|
interface nsIDOMFile : nsIDOMBlob
|
||||||
{
|
{
|
||||||
readonly attribute DOMString name;
|
readonly attribute DOMString name;
|
||||||
|
|
||||||
|
readonly attribute DOMString path;
|
||||||
|
|
||||||
[implicit_jscontext]
|
[implicit_jscontext]
|
||||||
readonly attribute jsval lastModifiedDate;
|
readonly attribute jsval lastModifiedDate;
|
||||||
|
|
||||||
|
|
|
@ -299,6 +299,16 @@ public:
|
||||||
mMatchNameSpaceId == aKey.mMatchNameSpaceId;
|
mMatchNameSpaceId == aKey.mMatchNameSpaceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the state to LIST_DIRTY and clears mElements array.
|
||||||
|
* @note This is the only acceptable way to set state to LIST_DIRTY.
|
||||||
|
*/
|
||||||
|
void SetDirty()
|
||||||
|
{
|
||||||
|
mState = LIST_DIRTY;
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Returns whether the element matches our criterion
|
* Returns whether the element matches our criterion
|
||||||
|
@ -350,16 +360,6 @@ protected:
|
||||||
*/
|
*/
|
||||||
inline void BringSelfUpToDate(bool aDoFlush);
|
inline void BringSelfUpToDate(bool aDoFlush);
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the state to LIST_DIRTY and clears mElements array.
|
|
||||||
* @note This is the only acceptable way to set state to LIST_DIRTY.
|
|
||||||
*/
|
|
||||||
void SetDirty()
|
|
||||||
{
|
|
||||||
mState = LIST_DIRTY;
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To be called from non-destructor locations that want to remove from caches.
|
* To be called from non-destructor locations that want to remove from caches.
|
||||||
* Needed because if subclasses want to have cache behavior they can't just
|
* Needed because if subclasses want to have cache behavior they can't just
|
||||||
|
|
|
@ -126,6 +126,14 @@ nsDOMFileBase::GetName(nsAString &aFileName)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDOMFileBase::GetPath(nsAString &aPath)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(mIsFile, "Should only be called on files");
|
||||||
|
aPath = mPath;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMFileBase::GetLastModifiedDate(JSContext* cx, JS::Value *aLastModifiedDate)
|
nsDOMFileBase::GetLastModifiedDate(JSContext* cx, JS::Value *aLastModifiedDate)
|
||||||
{
|
{
|
||||||
|
@ -591,6 +599,12 @@ nsDOMFileFile::GetInternalStream(nsIInputStream **aStream)
|
||||||
-1, -1, sFileStreamFlags);
|
-1, -1, sFileStreamFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsDOMFileFile::SetPath(const nsAString& aPath)
|
||||||
|
{
|
||||||
|
mPath = aPath;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// nsDOMMemoryFile implementation
|
// nsDOMMemoryFile implementation
|
||||||
|
|
||||||
|
|
|
@ -289,7 +289,7 @@ nsXMLHttpRequest::nsXMLHttpRequest()
|
||||||
mProgressSinceLastProgressEvent(false),
|
mProgressSinceLastProgressEvent(false),
|
||||||
mRequestSentTime(0), mTimeoutMilliseconds(0),
|
mRequestSentTime(0), mTimeoutMilliseconds(0),
|
||||||
mErrorLoad(false), mWaitingForOnStopRequest(false),
|
mErrorLoad(false), mWaitingForOnStopRequest(false),
|
||||||
mProgressTimerIsActive(false), mProgressEventWasDelayed(false),
|
mProgressTimerIsActive(false),
|
||||||
mIsHtml(false),
|
mIsHtml(false),
|
||||||
mWarnAboutSyncHtml(false),
|
mWarnAboutSyncHtml(false),
|
||||||
mLoadLengthComputable(false), mLoadTotal(0),
|
mLoadLengthComputable(false), mLoadTotal(0),
|
||||||
|
@ -3752,7 +3752,6 @@ nsXMLHttpRequest::StartProgressEventTimer()
|
||||||
mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
|
mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||||
}
|
}
|
||||||
if (mProgressNotifier) {
|
if (mProgressNotifier) {
|
||||||
mProgressEventWasDelayed = false;
|
|
||||||
mProgressTimerIsActive = true;
|
mProgressTimerIsActive = true;
|
||||||
mProgressNotifier->Cancel();
|
mProgressNotifier->Cancel();
|
||||||
mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
|
mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
|
||||||
|
|
|
@ -673,7 +673,6 @@ protected:
|
||||||
bool mErrorLoad;
|
bool mErrorLoad;
|
||||||
bool mWaitingForOnStopRequest;
|
bool mWaitingForOnStopRequest;
|
||||||
bool mProgressTimerIsActive;
|
bool mProgressTimerIsActive;
|
||||||
bool mProgressEventWasDelayed;
|
|
||||||
bool mIsHtml;
|
bool mIsHtml;
|
||||||
bool mWarnAboutMultipartHtml;
|
bool mWarnAboutMultipartHtml;
|
||||||
bool mWarnAboutSyncHtml;
|
bool mWarnAboutSyncHtml;
|
||||||
|
|
|
@ -240,13 +240,13 @@ class HTMLInputElementState MOZ_FINAL : public nsISupports
|
||||||
mValue = aValue;
|
mValue = aValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nsCOMArray<nsIDOMFile>& GetFiles() {
|
const nsTArray<nsCOMPtr<nsIDOMFile> >& GetFiles() {
|
||||||
return mFiles;
|
return mFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFiles(const nsCOMArray<nsIDOMFile>& aFiles) {
|
void SetFiles(const nsTArray<nsCOMPtr<nsIDOMFile> >& aFiles) {
|
||||||
mFiles.Clear();
|
mFiles.Clear();
|
||||||
mFiles.AppendObjects(aFiles);
|
mFiles.AppendElements(aFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
HTMLInputElementState()
|
HTMLInputElementState()
|
||||||
|
@ -257,7 +257,7 @@ class HTMLInputElementState MOZ_FINAL : public nsISupports
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsString mValue;
|
nsString mValue;
|
||||||
nsCOMArray<nsIDOMFile> mFiles;
|
nsTArray<nsCOMPtr<nsIDOMFile> > mFiles;
|
||||||
bool mChecked;
|
bool mChecked;
|
||||||
bool mCheckedSet;
|
bool mCheckedSet;
|
||||||
};
|
};
|
||||||
|
@ -314,6 +314,221 @@ UploadLastDir::ContentPrefCallback::HandleError(nsresult error)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This enumerator returns nsDOMFileFile objects after wrapping a single
|
||||||
|
* nsIFile representing a directory. It enumerates the files under that
|
||||||
|
* directory and its subdirectories as a flat list of files, ignoring/skipping
|
||||||
|
* over symbolic links.
|
||||||
|
*
|
||||||
|
* The enumeration involves I/O, so this class must NOT be used on the main
|
||||||
|
* thread or else the main thread could be blocked for a very long time.
|
||||||
|
*
|
||||||
|
* This enumerator does not walk the directory tree breadth-first, but it also
|
||||||
|
* is not guaranteed to walk it depth-first either (since it uses
|
||||||
|
* nsIFile::GetDirectoryEntries, which is not guaranteed to group a directory's
|
||||||
|
* subdirectories at the beginning of the list that it returns).
|
||||||
|
*/
|
||||||
|
class DirPickerRecursiveFileEnumerator MOZ_FINAL
|
||||||
|
: public nsISimpleEnumerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
DirPickerRecursiveFileEnumerator(nsIFile* aTopDir)
|
||||||
|
: mTopDir(aTopDir)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!NS_IsMainThread(), "This class blocks on I/O!");
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
bool isDir;
|
||||||
|
aTopDir->IsDirectory(&isDir);
|
||||||
|
MOZ_ASSERT(isDir);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||||
|
if (NS_SUCCEEDED(mTopDir->GetDirectoryEntries(getter_AddRefs(entries))) &&
|
||||||
|
entries) {
|
||||||
|
mDirEnumeratorStack.AppendElement(entries);
|
||||||
|
LookupAndCacheNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD
|
||||||
|
GetNext(nsISupports** aResult)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!NS_IsMainThread(),
|
||||||
|
"Walking the directory tree involves I/O, so using this "
|
||||||
|
"enumerator can block a thread for a long time!");
|
||||||
|
|
||||||
|
if (!mNextFile) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
nsRefPtr<nsDOMFileFile> domFile = new nsDOMFileFile(mNextFile);
|
||||||
|
nsCString relDescriptor;
|
||||||
|
nsresult rv = mNextFile->GetRelativeDescriptor(mTopDir, relDescriptor);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
NS_ConvertUTF8toUTF16 path(relDescriptor);
|
||||||
|
nsAutoString leafName;
|
||||||
|
mNextFile->GetLeafName(leafName);
|
||||||
|
MOZ_ASSERT(leafName.Length() <= path.Length());
|
||||||
|
int32_t length = path.Length() - leafName.Length() - 1; // -1 for "/"
|
||||||
|
MOZ_ASSERT(length >= -1);
|
||||||
|
if (length > 0) {
|
||||||
|
domFile->SetPath(Substring(path, 0, uint32_t(length)));
|
||||||
|
}
|
||||||
|
*aResult = static_cast<nsIDOMFile*>(domFile.forget().get());
|
||||||
|
LookupAndCacheNext();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD
|
||||||
|
HasMoreElements(bool* aResult)
|
||||||
|
{
|
||||||
|
*aResult = !!mNextFile;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void
|
||||||
|
LookupAndCacheNext()
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
if (mDirEnumeratorStack.IsEmpty()) {
|
||||||
|
mNextFile = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsISimpleEnumerator* currentDirEntries =
|
||||||
|
mDirEnumeratorStack.LastElement();
|
||||||
|
|
||||||
|
bool hasMore;
|
||||||
|
DebugOnly<nsresult> rv = currentDirEntries->HasMoreElements(&hasMore);
|
||||||
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||||
|
|
||||||
|
if (!hasMore) {
|
||||||
|
mDirEnumeratorStack.RemoveElementAt(mDirEnumeratorStack.Length() - 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsISupports> entry;
|
||||||
|
rv = currentDirEntries->GetNext(getter_AddRefs(entry));
|
||||||
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
|
||||||
|
MOZ_ASSERT(file);
|
||||||
|
|
||||||
|
bool isLink, isSpecial;
|
||||||
|
file->IsSymlink(&isLink);
|
||||||
|
file->IsSpecial(&isSpecial);
|
||||||
|
if (isLink || isSpecial) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDir;
|
||||||
|
file->IsDirectory(&isDir);
|
||||||
|
if (isDir) {
|
||||||
|
nsCOMPtr<nsISimpleEnumerator> subDirEntries;
|
||||||
|
rv = file->GetDirectoryEntries(getter_AddRefs(subDirEntries));
|
||||||
|
MOZ_ASSERT(NS_SUCCEEDED(rv) && subDirEntries);
|
||||||
|
mDirEnumeratorStack.AppendElement(subDirEntries);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
bool isFile;
|
||||||
|
file->IsFile(&isFile);
|
||||||
|
MOZ_ASSERT(isFile);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mNextFile.swap(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsCOMPtr<nsIFile> mTopDir;
|
||||||
|
nsCOMPtr<nsIFile> mNextFile;
|
||||||
|
nsTArray<nsCOMPtr<nsISimpleEnumerator> > mDirEnumeratorStack;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS1(DirPickerRecursiveFileEnumerator, nsISimpleEnumerator)
|
||||||
|
|
||||||
|
class DirPickerBuildFileListTask MOZ_FINAL
|
||||||
|
: public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DirPickerBuildFileListTask(HTMLInputElement* aInput, nsIFile* aTopDir)
|
||||||
|
: mInput(aInput)
|
||||||
|
, mTopDir(aTopDir)
|
||||||
|
{}
|
||||||
|
|
||||||
|
NS_IMETHOD Run() {
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
// Build up list of nsDOMFileFile objects on this dedicated thread:
|
||||||
|
nsCOMPtr<nsISimpleEnumerator> iter =
|
||||||
|
new DirPickerRecursiveFileEnumerator(mTopDir);
|
||||||
|
bool hasMore = true;
|
||||||
|
nsCOMPtr<nsISupports> tmp;
|
||||||
|
while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
|
||||||
|
iter->GetNext(getter_AddRefs(tmp));
|
||||||
|
nsCOMPtr<nsIDOMFile> domFile = do_QueryInterface(tmp);
|
||||||
|
MOZ_ASSERT(domFile);
|
||||||
|
mFileList.AppendElement(domFile);
|
||||||
|
}
|
||||||
|
return NS_DispatchToMainThread(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now back on the main thread, set the list on our HTMLInputElement:
|
||||||
|
if (mFileList.IsEmpty()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
// The text control frame (if there is one) isn't going to send a change
|
||||||
|
// event because it will think this is done by a script.
|
||||||
|
// So, we can safely send one by ourself.
|
||||||
|
mInput->SetFiles(mFileList, true);
|
||||||
|
nsresult rv =
|
||||||
|
nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
|
||||||
|
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
|
||||||
|
NS_LITERAL_STRING("change"), true,
|
||||||
|
false);
|
||||||
|
// Clear mInput to make sure that it can't lose its last strong ref off the
|
||||||
|
// main thread (which may happen if our dtor runs off the main thread)!
|
||||||
|
mInput = nullptr;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<HTMLInputElement> mInput;
|
||||||
|
nsCOMPtr<nsIFile> mTopDir;
|
||||||
|
nsTArray<nsCOMPtr<nsIDOMFile> > mFileList;
|
||||||
|
};
|
||||||
|
|
||||||
|
static already_AddRefed<nsIFile>
|
||||||
|
DOMFileToLocalFile(nsIDOMFile* aDomFile)
|
||||||
|
{
|
||||||
|
nsString path;
|
||||||
|
nsresult rv = aDomFile->GetMozFullPathInternal(path);
|
||||||
|
if (NS_FAILED(rv) || path.IsEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIFile> localFile;
|
||||||
|
rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
|
||||||
|
getter_AddRefs(localFile));
|
||||||
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||||
|
|
||||||
|
return localFile.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
||||||
{
|
{
|
||||||
|
@ -323,11 +538,43 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
||||||
|
|
||||||
int16_t mode;
|
int16_t mode;
|
||||||
mFilePicker->GetMode(&mode);
|
mFilePicker->GetMode(&mode);
|
||||||
bool multi = mode == static_cast<int16_t>(nsIFilePicker::modeOpenMultiple);
|
|
||||||
|
if (mode == static_cast<int16_t>(nsIFilePicker::modeGetFolder)) {
|
||||||
|
// Directory picking is different, since we still need to do more I/O to
|
||||||
|
// build up the list of nsDOMFileFile objects. Since this may block for a
|
||||||
|
// long time, we need to build the list off on another dedicated thread to
|
||||||
|
// avoid blocking any other activities that the browser is carrying out.
|
||||||
|
|
||||||
|
// The user selected this directory, so we always save this dir, even if
|
||||||
|
// no files are found under it.
|
||||||
|
nsCOMPtr<nsIFile> pickedDir;
|
||||||
|
mFilePicker->GetFile(getter_AddRefs(pickedDir));
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
bool isDir;
|
||||||
|
pickedDir->IsDirectory(&isDir);
|
||||||
|
MOZ_ASSERT(isDir);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
|
||||||
|
mInput->OwnerDoc(), pickedDir);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIEventTarget> target
|
||||||
|
= do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
||||||
|
NS_ASSERTION(target, "Must have stream transport service");
|
||||||
|
|
||||||
|
// DirPickerBuildFileListTask takes care of calling SetFiles() and
|
||||||
|
// dispatching the "change" event.
|
||||||
|
nsRefPtr<DirPickerBuildFileListTask> event =
|
||||||
|
new DirPickerBuildFileListTask(mInput.get(), pickedDir.get());
|
||||||
|
return target->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
// Collect new selected filenames
|
// Collect new selected filenames
|
||||||
nsCOMArray<nsIDOMFile> newFiles;
|
nsTArray<nsCOMPtr<nsIDOMFile> > newFiles;
|
||||||
if (multi) {
|
if (mode == static_cast<int16_t>(nsIFilePicker::modeOpenMultiple)) {
|
||||||
nsCOMPtr<nsISimpleEnumerator> iter;
|
nsCOMPtr<nsISimpleEnumerator> iter;
|
||||||
nsresult rv = mFilePicker->GetDomfiles(getter_AddRefs(iter));
|
nsresult rv = mFilePicker->GetDomfiles(getter_AddRefs(iter));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
@ -337,41 +584,35 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> tmp;
|
nsCOMPtr<nsISupports> tmp;
|
||||||
bool prefSaved = false;
|
bool hasMore = true;
|
||||||
bool loop = true;
|
|
||||||
|
|
||||||
while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) {
|
while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
|
||||||
iter->GetNext(getter_AddRefs(tmp));
|
iter->GetNext(getter_AddRefs(tmp));
|
||||||
nsCOMPtr<nsIDOMFile> domFile = do_QueryInterface(tmp);
|
nsCOMPtr<nsIDOMFile> domFile = do_QueryInterface(tmp);
|
||||||
MOZ_ASSERT(domFile);
|
MOZ_ASSERT(domFile);
|
||||||
|
newFiles.AppendElement(domFile);
|
||||||
newFiles.AppendObject(domFile);
|
|
||||||
|
|
||||||
if (!prefSaved) {
|
|
||||||
// Store the last used directory using the content pref service
|
|
||||||
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
|
|
||||||
mInput->OwnerDoc(), domFile);
|
|
||||||
prefSaved = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
MOZ_ASSERT(mode == static_cast<int16_t>(nsIFilePicker::modeOpen));
|
||||||
nsCOMPtr<nsIDOMFile> domFile;
|
nsCOMPtr<nsIDOMFile> domFile;
|
||||||
nsresult rv = mFilePicker->GetDomfile(getter_AddRefs(domFile));
|
nsresult rv = mFilePicker->GetDomfile(getter_AddRefs(domFile));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
if (domFile) {
|
if (domFile) {
|
||||||
newFiles.AppendObject(domFile);
|
newFiles.AppendElement(domFile);
|
||||||
|
|
||||||
// Store the last used directory using the content pref service
|
|
||||||
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
|
|
||||||
mInput->OwnerDoc(), domFile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newFiles.Count()) {
|
if (newFiles.IsEmpty()) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store the last used directory using the content pref service:
|
||||||
|
nsCOMPtr<nsIFile> file = DOMFileToLocalFile(newFiles[0]);
|
||||||
|
nsCOMPtr<nsIFile> lastUsedDir;
|
||||||
|
file->GetParent(getter_AddRefs(lastUsedDir));
|
||||||
|
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
|
||||||
|
mInput->OwnerDoc(), lastUsedDir);
|
||||||
|
|
||||||
// The text control frame (if there is one) isn't going to send a change
|
// The text control frame (if there is one) isn't going to send a change
|
||||||
// event because it will think this is done by a script.
|
// event because it will think this is done by a script.
|
||||||
// So, we can safely send one by ourself.
|
// So, we can safely send one by ourself.
|
||||||
|
@ -543,7 +784,7 @@ HTMLInputElement::InitColorPicker()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLInputElement::InitFilePicker()
|
HTMLInputElement::InitFilePicker(FilePickerType aType)
|
||||||
{
|
{
|
||||||
// Get parent nsPIDOMWindow object.
|
// Get parent nsPIDOMWindow object.
|
||||||
nsCOMPtr<nsIDocument> doc = OwnerDoc();
|
nsCOMPtr<nsIDocument> doc = OwnerDoc();
|
||||||
|
@ -567,15 +808,23 @@ HTMLInputElement::InitFilePicker()
|
||||||
if (!filePicker)
|
if (!filePicker)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
bool multi = HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
|
int16_t mode;
|
||||||
|
|
||||||
nsresult rv = filePicker->Init(win, title,
|
if (aType == FILE_PICKER_DIRECTORY) {
|
||||||
multi
|
mode = static_cast<int16_t>(nsIFilePicker::modeGetFolder);
|
||||||
? static_cast<int16_t>(nsIFilePicker::modeOpenMultiple)
|
} else if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
|
||||||
: static_cast<int16_t>(nsIFilePicker::modeOpen));
|
mode = static_cast<int16_t>(nsIFilePicker::modeOpenMultiple);
|
||||||
|
} else {
|
||||||
|
mode = static_cast<int16_t>(nsIFilePicker::modeOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult rv = filePicker->Init(win, title, mode);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::accept)) {
|
// Native directory pickers ignore file type filters, so we don't spend
|
||||||
|
// cycles adding them for FILE_PICKER_DIRECTORY.
|
||||||
|
if (HasAttr(kNameSpaceID_None, nsGkAtoms::accept) &&
|
||||||
|
aType != FILE_PICKER_DIRECTORY) {
|
||||||
SetFilePickerFiltersFromAccept(filePicker);
|
SetFilePickerFiltersFromAccept(filePicker);
|
||||||
} else {
|
} else {
|
||||||
filePicker->AppendFilters(nsIFilePicker::filterAll);
|
filePicker->AppendFilters(nsIFilePicker::filterAll);
|
||||||
|
@ -584,12 +833,13 @@ HTMLInputElement::InitFilePicker()
|
||||||
// Set default directry and filename
|
// Set default directry and filename
|
||||||
nsAutoString defaultName;
|
nsAutoString defaultName;
|
||||||
|
|
||||||
const nsCOMArray<nsIDOMFile>& oldFiles = GetFilesInternal();
|
const nsTArray<nsCOMPtr<nsIDOMFile> >& oldFiles = GetFilesInternal();
|
||||||
|
|
||||||
nsCOMPtr<nsIFilePickerShownCallback> callback =
|
nsCOMPtr<nsIFilePickerShownCallback> callback =
|
||||||
new HTMLInputElement::nsFilePickerShownCallback(this, filePicker);
|
new HTMLInputElement::nsFilePickerShownCallback(this, filePicker);
|
||||||
|
|
||||||
if (oldFiles.Count()) {
|
if (!oldFiles.IsEmpty() &&
|
||||||
|
aType != FILE_PICKER_DIRECTORY) {
|
||||||
nsString path;
|
nsString path;
|
||||||
|
|
||||||
oldFiles[0]->GetMozFullPathInternal(path);
|
oldFiles[0]->GetMozFullPathInternal(path);
|
||||||
|
@ -608,7 +858,7 @@ HTMLInputElement::InitFilePicker()
|
||||||
// Unfortunately nsIFilePicker doesn't allow multiple files to be
|
// Unfortunately nsIFilePicker doesn't allow multiple files to be
|
||||||
// default-selected, so only select something by default if exactly
|
// default-selected, so only select something by default if exactly
|
||||||
// one file was selected before.
|
// one file was selected before.
|
||||||
if (oldFiles.Count() == 1) {
|
if (oldFiles.Length() == 1) {
|
||||||
nsAutoString leafName;
|
nsAutoString leafName;
|
||||||
oldFiles[0]->GetName(leafName);
|
oldFiles[0]->GetName(leafName);
|
||||||
if (!leafName.IsEmpty()) {
|
if (!leafName.IsEmpty()) {
|
||||||
|
@ -621,7 +871,6 @@ HTMLInputElement::InitFilePicker()
|
||||||
|
|
||||||
HTMLInputElement::gUploadLastDir->FetchDirectoryAndDisplayPicker(doc, filePicker, callback);
|
HTMLInputElement::gUploadLastDir->FetchDirectoryAndDisplayPicker(doc, filePicker, callback);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CPS_PREF_NAME NS_LITERAL_STRING("browser.upload.lastDir")
|
#define CPS_PREF_NAME NS_LITERAL_STRING("browser.upload.lastDir")
|
||||||
|
@ -680,31 +929,16 @@ UploadLastDir::FetchDirectoryAndDisplayPicker(nsIDocument* aDoc,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIDOMFile* aDomFile)
|
UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aDir)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(aDoc, "aDoc is null");
|
NS_PRECONDITION(aDoc, "aDoc is null");
|
||||||
NS_PRECONDITION(aDomFile, "aDomFile is null");
|
if (!aDir) {
|
||||||
|
|
||||||
nsString path;
|
|
||||||
nsresult rv = aDomFile->GetMozFullPathInternal(path);
|
|
||||||
if (NS_FAILED(rv) || path.IsEmpty()) {
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> localFile;
|
|
||||||
rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
|
|
||||||
getter_AddRefs(localFile));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> docURI = aDoc->GetDocumentURI();
|
nsCOMPtr<nsIURI> docURI = aDoc->GetDocumentURI();
|
||||||
NS_PRECONDITION(docURI, "docURI is null");
|
NS_PRECONDITION(docURI, "docURI is null");
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> parentFile;
|
|
||||||
localFile->GetParent(getter_AddRefs(parentFile));
|
|
||||||
if (!parentFile) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to get the CPS, if it's not present we'll just return
|
// Attempt to get the CPS, if it's not present we'll just return
|
||||||
nsCOMPtr<nsIContentPrefService2> contentPrefService =
|
nsCOMPtr<nsIContentPrefService2> contentPrefService =
|
||||||
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
||||||
|
@ -717,7 +951,7 @@ UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIDOMFile* aDomFile)
|
||||||
|
|
||||||
// Find the parent of aFile, and store it
|
// Find the parent of aFile, and store it
|
||||||
nsString unicodePath;
|
nsString unicodePath;
|
||||||
parentFile->GetPath(unicodePath);
|
aDir->GetPath(unicodePath);
|
||||||
if (unicodePath.IsEmpty()) // nothing to do
|
if (unicodePath.IsEmpty()) // nothing to do
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
nsCOMPtr<nsIWritableVariant> prefValue = do_CreateInstance(NS_VARIANT_CONTRACTID);
|
nsCOMPtr<nsIWritableVariant> prefValue = do_CreateInstance(NS_VARIANT_CONTRACTID);
|
||||||
|
@ -906,7 +1140,7 @@ HTMLInputElement::Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const
|
||||||
GetDisplayFileName(it->mStaticDocFileList);
|
GetDisplayFileName(it->mStaticDocFileList);
|
||||||
} else {
|
} else {
|
||||||
it->mFiles.Clear();
|
it->mFiles.Clear();
|
||||||
it->mFiles.AppendObjects(mFiles);
|
it->mFiles.AppendElements(mFiles);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VALUE_MODE_DEFAULT_ON:
|
case VALUE_MODE_DEFAULT_ON:
|
||||||
|
@ -1264,7 +1498,7 @@ HTMLInputElement::GetValueInternal(nsAString& aValue) const
|
||||||
|
|
||||||
case VALUE_MODE_FILENAME:
|
case VALUE_MODE_FILENAME:
|
||||||
if (nsContentUtils::IsCallerChrome()) {
|
if (nsContentUtils::IsCallerChrome()) {
|
||||||
if (mFiles.Count()) {
|
if (!mFiles.IsEmpty()) {
|
||||||
return mFiles[0]->GetMozFullPath(aValue);
|
return mFiles[0]->GetMozFullPath(aValue);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1272,7 +1506,7 @@ HTMLInputElement::GetValueInternal(nsAString& aValue) const
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Just return the leaf name
|
// Just return the leaf name
|
||||||
if (mFiles.Count() == 0 || NS_FAILED(mFiles[0]->GetName(aValue))) {
|
if (mFiles.IsEmpty() || NS_FAILED(mFiles[0]->GetName(aValue))) {
|
||||||
aValue.Truncate();
|
aValue.Truncate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1818,7 +2052,7 @@ HTMLInputElement::StepUp(int32_t n, uint8_t optional_argc)
|
||||||
void
|
void
|
||||||
HTMLInputElement::MozGetFileNameArray(nsTArray< nsString >& aArray)
|
HTMLInputElement::MozGetFileNameArray(nsTArray< nsString >& aArray)
|
||||||
{
|
{
|
||||||
for (int32_t i = 0; i < mFiles.Count(); i++) {
|
for (uint32_t i = 0; i < mFiles.Length(); i++) {
|
||||||
nsString str;
|
nsString str;
|
||||||
mFiles[i]->GetMozFullPathInternal(str);
|
mFiles[i]->GetMozFullPathInternal(str);
|
||||||
aArray.AppendElement(str);
|
aArray.AppendElement(str);
|
||||||
|
@ -1857,7 +2091,7 @@ HTMLInputElement::MozGetFileNameArray(uint32_t* aLength, PRUnichar*** aFileNames
|
||||||
void
|
void
|
||||||
HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames)
|
HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames)
|
||||||
{
|
{
|
||||||
nsCOMArray<nsIDOMFile> files;
|
nsTArray<nsCOMPtr<nsIDOMFile> > files;
|
||||||
for (uint32_t i = 0; i < aFileNames.Length(); ++i) {
|
for (uint32_t i = 0; i < aFileNames.Length(); ++i) {
|
||||||
nsCOMPtr<nsIFile> file;
|
nsCOMPtr<nsIFile> file;
|
||||||
|
|
||||||
|
@ -1876,7 +2110,7 @@ HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames)
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(file);
|
nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(file);
|
||||||
files.AppendObject(domFile);
|
files.AppendElement(domFile);
|
||||||
} else {
|
} else {
|
||||||
continue; // Not much we can do if the file doesn't exist
|
continue; // Not much we can do if the file doesn't exist
|
||||||
}
|
}
|
||||||
|
@ -2068,14 +2302,14 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFiles.Count() == 1) {
|
if (mFiles.Length() == 1) {
|
||||||
mFiles[0]->GetName(aValue);
|
mFiles[0]->GetName(aValue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsXPIDLString value;
|
nsXPIDLString value;
|
||||||
|
|
||||||
if (mFiles.Count() == 0) {
|
if (mFiles.IsEmpty()) {
|
||||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
|
if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
|
||||||
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
||||||
"NoFilesSelected", value);
|
"NoFilesSelected", value);
|
||||||
|
@ -2085,7 +2319,7 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nsString count;
|
nsString count;
|
||||||
count.AppendInt(mFiles.Count());
|
count.AppendInt(mFiles.Length());
|
||||||
|
|
||||||
const PRUnichar* params[] = { count.get() };
|
const PRUnichar* params[] = { count.get() };
|
||||||
nsContentUtils::FormatLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
nsContentUtils::FormatLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
||||||
|
@ -2096,11 +2330,11 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HTMLInputElement::SetFiles(const nsCOMArray<nsIDOMFile>& aFiles,
|
HTMLInputElement::SetFiles(const nsTArray<nsCOMPtr<nsIDOMFile> >& aFiles,
|
||||||
bool aSetValueChanged)
|
bool aSetValueChanged)
|
||||||
{
|
{
|
||||||
mFiles.Clear();
|
mFiles.Clear();
|
||||||
mFiles.AppendObjects(aFiles);
|
mFiles.AppendElements(aFiles);
|
||||||
|
|
||||||
AfterSetFiles(aSetValueChanged);
|
AfterSetFiles(aSetValueChanged);
|
||||||
}
|
}
|
||||||
|
@ -2117,7 +2351,7 @@ HTMLInputElement::SetFiles(nsIDOMFileList* aFiles,
|
||||||
for (uint32_t i = 0; i < listLength; i++) {
|
for (uint32_t i = 0; i < listLength; i++) {
|
||||||
nsCOMPtr<nsIDOMFile> file;
|
nsCOMPtr<nsIDOMFile> file;
|
||||||
aFiles->Item(i, getter_AddRefs(file));
|
aFiles->Item(i, getter_AddRefs(file));
|
||||||
mFiles.AppendObject(file);
|
mFiles.AppendElement(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2179,14 +2413,23 @@ HTMLInputElement::GetFiles()
|
||||||
return mFileList;
|
return mFileList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLInputElement::OpenDirectoryPicker(ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
if (mType != NS_FORM_INPUT_FILE) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
|
}
|
||||||
|
InitFilePicker(FILE_PICKER_DIRECTORY);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLInputElement::UpdateFileList()
|
HTMLInputElement::UpdateFileList()
|
||||||
{
|
{
|
||||||
if (mFileList) {
|
if (mFileList) {
|
||||||
mFileList->Clear();
|
mFileList->Clear();
|
||||||
|
|
||||||
const nsCOMArray<nsIDOMFile>& files = GetFilesInternal();
|
const nsTArray<nsCOMPtr<nsIDOMFile> >& files = GetFilesInternal();
|
||||||
for (int32_t i = 0; i < files.Count(); ++i) {
|
for (uint32_t i = 0; i < files.Length(); ++i) {
|
||||||
if (!mFileList->Append(files[i])) {
|
if (!mFileList->Append(files[i])) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -2890,7 +3133,7 @@ HTMLInputElement::MaybeInitPickers(nsEventChainPostVisitor& aVisitor)
|
||||||
if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) &&
|
if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) &&
|
||||||
!aVisitor.mEvent->mFlags.mDefaultPrevented) {
|
!aVisitor.mEvent->mFlags.mDefaultPrevented) {
|
||||||
if (mType == NS_FORM_INPUT_FILE) {
|
if (mType == NS_FORM_INPUT_FILE) {
|
||||||
return InitFilePicker();
|
return InitFilePicker(FILE_PICKER_FILE);
|
||||||
}
|
}
|
||||||
if (mType == NS_FORM_INPUT_COLOR) {
|
if (mType == NS_FORM_INPUT_COLOR) {
|
||||||
return InitColorPicker();
|
return InitColorPicker();
|
||||||
|
@ -4574,13 +4817,13 @@ HTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
|
||||||
if (mType == NS_FORM_INPUT_FILE) {
|
if (mType == NS_FORM_INPUT_FILE) {
|
||||||
// Submit files
|
// Submit files
|
||||||
|
|
||||||
const nsCOMArray<nsIDOMFile>& files = GetFilesInternal();
|
const nsTArray<nsCOMPtr<nsIDOMFile> >& files = GetFilesInternal();
|
||||||
|
|
||||||
for (int32_t i = 0; i < files.Count(); ++i) {
|
for (uint32_t i = 0; i < files.Length(); ++i) {
|
||||||
aFormSubmission->AddNameFilePair(name, files[i], NullString());
|
aFormSubmission->AddNameFilePair(name, files[i], NullString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files.Count() == 0) {
|
if (files.IsEmpty()) {
|
||||||
// If no file was selected, pretend we had an empty file with an
|
// If no file was selected, pretend we had an empty file with an
|
||||||
// empty filename.
|
// empty filename.
|
||||||
aFormSubmission->AddNameFilePair(name, nullptr, NullString());
|
aFormSubmission->AddNameFilePair(name, nullptr, NullString());
|
||||||
|
@ -4617,7 +4860,7 @@ HTMLInputElement::SaveState()
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VALUE_MODE_FILENAME:
|
case VALUE_MODE_FILENAME:
|
||||||
if (mFiles.Count()) {
|
if (!mFiles.IsEmpty()) {
|
||||||
inputState = new HTMLInputElementState();
|
inputState = new HTMLInputElementState();
|
||||||
inputState->SetFiles(mFiles);
|
inputState->SetFiles(mFiles);
|
||||||
}
|
}
|
||||||
|
@ -4790,7 +5033,7 @@ HTMLInputElement::RestoreState(nsPresState* aState)
|
||||||
break;
|
break;
|
||||||
case VALUE_MODE_FILENAME:
|
case VALUE_MODE_FILENAME:
|
||||||
{
|
{
|
||||||
const nsCOMArray<nsIDOMFile>& files = inputState->GetFiles();
|
const nsTArray<nsCOMPtr<nsIDOMFile> >& files = inputState->GetFiles();
|
||||||
SetFiles(files, true);
|
SetFiles(files, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -5257,8 +5500,8 @@ HTMLInputElement::IsValueMissing() const
|
||||||
return IsValueEmpty();
|
return IsValueEmpty();
|
||||||
case VALUE_MODE_FILENAME:
|
case VALUE_MODE_FILENAME:
|
||||||
{
|
{
|
||||||
const nsCOMArray<nsIDOMFile>& files = GetFilesInternal();
|
const nsTArray<nsCOMPtr<nsIDOMFile> >& files = GetFilesInternal();
|
||||||
return !files.Count();
|
return files.IsEmpty();
|
||||||
}
|
}
|
||||||
case VALUE_MODE_DEFAULT_ON:
|
case VALUE_MODE_DEFAULT_ON:
|
||||||
// This should not be used for type radio.
|
// This should not be used for type radio.
|
||||||
|
|
|
@ -54,10 +54,9 @@ public:
|
||||||
* Store the last used directory for this location using the
|
* Store the last used directory for this location using the
|
||||||
* content pref service, if it is available
|
* content pref service, if it is available
|
||||||
* @param aURI URI of the current page
|
* @param aURI URI of the current page
|
||||||
* @param aDomFile file chosen by the user - the path to the parent of this
|
* @param aDir Parent directory of the file(s)/directory chosen by the user
|
||||||
* file will be stored
|
|
||||||
*/
|
*/
|
||||||
nsresult StoreLastUsedDirectory(nsIDocument* aDoc, nsIDOMFile* aDomFile);
|
nsresult StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aDir);
|
||||||
|
|
||||||
class ContentPrefCallback MOZ_FINAL : public nsIContentPrefCallback2
|
class ContentPrefCallback MOZ_FINAL : public nsIContentPrefCallback2
|
||||||
{
|
{
|
||||||
|
@ -191,12 +190,12 @@ public:
|
||||||
|
|
||||||
void GetDisplayFileName(nsAString& aFileName) const;
|
void GetDisplayFileName(nsAString& aFileName) const;
|
||||||
|
|
||||||
const nsCOMArray<nsIDOMFile>& GetFilesInternal() const
|
const nsTArray<nsCOMPtr<nsIDOMFile> >& GetFilesInternal() const
|
||||||
{
|
{
|
||||||
return mFiles;
|
return mFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFiles(const nsCOMArray<nsIDOMFile>& aFiles, bool aSetValueChanged);
|
void SetFiles(const nsTArray<nsCOMPtr<nsIDOMFile> >& aFiles, bool aSetValueChanged);
|
||||||
void SetFiles(nsIDOMFileList* aFiles, bool aSetValueChanged);
|
void SetFiles(nsIDOMFileList* aFiles, bool aSetValueChanged);
|
||||||
|
|
||||||
void SetCheckedChangedInternal(bool aCheckedChanged);
|
void SetCheckedChangedInternal(bool aCheckedChanged);
|
||||||
|
@ -393,6 +392,8 @@ public:
|
||||||
|
|
||||||
nsDOMFileList* GetFiles();
|
nsDOMFileList* GetFiles();
|
||||||
|
|
||||||
|
void OpenDirectoryPicker(ErrorResult& aRv);
|
||||||
|
|
||||||
// XPCOM GetFormAction() is OK
|
// XPCOM GetFormAction() is OK
|
||||||
void SetFormAction(const nsAString& aValue, ErrorResult& aRv)
|
void SetFormAction(const nsAString& aValue, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
|
@ -734,7 +735,7 @@ protected:
|
||||||
bool IsValueEmpty() const;
|
bool IsValueEmpty() const;
|
||||||
|
|
||||||
void ClearFiles(bool aSetValueChanged) {
|
void ClearFiles(bool aSetValueChanged) {
|
||||||
nsCOMArray<nsIDOMFile> files;
|
nsTArray<nsCOMPtr<nsIDOMFile> > files;
|
||||||
SetFiles(files, aSetValueChanged);
|
SetFiles(files, aSetValueChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1080,7 +1081,11 @@ protected:
|
||||||
*/
|
*/
|
||||||
nsresult MaybeInitPickers(nsEventChainPostVisitor& aVisitor);
|
nsresult MaybeInitPickers(nsEventChainPostVisitor& aVisitor);
|
||||||
|
|
||||||
nsresult InitFilePicker();
|
enum FilePickerType {
|
||||||
|
FILE_PICKER_FILE,
|
||||||
|
FILE_PICKER_DIRECTORY
|
||||||
|
};
|
||||||
|
nsresult InitFilePicker(FilePickerType aType);
|
||||||
nsresult InitColorPicker();
|
nsresult InitColorPicker();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1122,7 +1127,7 @@ protected:
|
||||||
* the frame. Whenever the frame wants to change the filename it has to call
|
* the frame. Whenever the frame wants to change the filename it has to call
|
||||||
* SetFileNames to update this member.
|
* SetFileNames to update this member.
|
||||||
*/
|
*/
|
||||||
nsCOMArray<nsIDOMFile> mFiles;
|
nsTArray<nsCOMPtr<nsIDOMFile> > mFiles;
|
||||||
|
|
||||||
nsRefPtr<nsDOMFileList> mFileList;
|
nsRefPtr<nsDOMFileList> mFileList;
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "mozilla/dom/HTMLSelectElementBinding.h"
|
#include "mozilla/dom/HTMLSelectElementBinding.h"
|
||||||
#include "mozilla/Util.h"
|
#include "mozilla/Util.h"
|
||||||
#include "nsContentCreatorFunctions.h"
|
#include "nsContentCreatorFunctions.h"
|
||||||
|
#include "nsContentList.h"
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
#include "nsEventDispatcher.h"
|
#include "nsEventDispatcher.h"
|
||||||
#include "nsEventStates.h"
|
#include "nsEventStates.h"
|
||||||
|
@ -139,10 +140,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLSelectElement,
|
||||||
nsGenericHTMLFormElementWithState)
|
nsGenericHTMLFormElementWithState)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOptions)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOptions)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectedOptions)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLSelectElement,
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLSelectElement,
|
||||||
nsGenericHTMLFormElementWithState)
|
nsGenericHTMLFormElementWithState)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectedOptions)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
NS_IMPL_ADDREF_INHERITED(HTMLSelectElement, Element)
|
NS_IMPL_ADDREF_INHERITED(HTMLSelectElement, Element)
|
||||||
|
@ -769,6 +772,34 @@ HTMLSelectElement::SetLength(uint32_t aLength, ErrorResult& aRv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool
|
||||||
|
HTMLSelectElement::MatchSelectedOptions(nsIContent* aContent,
|
||||||
|
int32_t /* unused */,
|
||||||
|
nsIAtom* /* unused */,
|
||||||
|
void* /* unused*/)
|
||||||
|
{
|
||||||
|
HTMLOptionElement* option = HTMLOptionElement::FromContent(aContent);
|
||||||
|
return option && option->Selected();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIHTMLCollection*
|
||||||
|
HTMLSelectElement::SelectedOptions()
|
||||||
|
{
|
||||||
|
if (!mSelectedOptions) {
|
||||||
|
mSelectedOptions = new nsContentList(this, MatchSelectedOptions, nullptr,
|
||||||
|
nullptr, /* deep */ true);
|
||||||
|
}
|
||||||
|
return mSelectedOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
HTMLSelectElement::GetSelectedOptions(nsIDOMHTMLCollection** aSelectedOptions)
|
||||||
|
{
|
||||||
|
NS_ADDREF(*aSelectedOptions = SelectedOptions());
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
//NS_IMPL_INT_ATTR(HTMLSelectElement, SelectedIndex, selectedindex)
|
//NS_IMPL_INT_ATTR(HTMLSelectElement, SelectedIndex, selectedindex)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -847,6 +878,7 @@ HTMLSelectElement::OnOptionSelected(nsISelectControlFrame* aSelectFrame,
|
||||||
aSelectFrame->OnOptionSelected(aIndex, aSelected);
|
aSelectFrame->OnOptionSelected(aIndex, aSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateSelectedOptions();
|
||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
UpdateState(aNotify);
|
UpdateState(aNotify);
|
||||||
}
|
}
|
||||||
|
@ -1848,6 +1880,8 @@ HTMLSelectElement::SetSelectionChanged(bool aValue, bool aNotify)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateSelectedOptions();
|
||||||
|
|
||||||
bool previousSelectionChangedValue = mSelectionHasChanged;
|
bool previousSelectionChangedValue = mSelectionHasChanged;
|
||||||
mSelectionHasChanged = aValue;
|
mSelectionHasChanged = aValue;
|
||||||
|
|
||||||
|
@ -1856,6 +1890,14 @@ HTMLSelectElement::SetSelectionChanged(bool aValue, bool aNotify)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLSelectElement::UpdateSelectedOptions()
|
||||||
|
{
|
||||||
|
if (mSelectedOptions) {
|
||||||
|
mSelectedOptions->SetDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
HTMLSelectElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
HTMLSelectElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,9 @@
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
#include "mozilla/dom/HTMLFormElement.h"
|
#include "mozilla/dom/HTMLFormElement.h"
|
||||||
|
|
||||||
|
class nsContentList;
|
||||||
class nsIDOMHTMLOptionElement;
|
class nsIDOMHTMLOptionElement;
|
||||||
|
class nsIHTMLCollection;
|
||||||
class nsISelectControlFrame;
|
class nsISelectControlFrame;
|
||||||
class nsPresState;
|
class nsPresState;
|
||||||
|
|
||||||
|
@ -208,6 +210,11 @@ public:
|
||||||
mOptions->IndexedSetter(aIndex, aOption, aRv);
|
mOptions->IndexedSetter(aIndex, aOption, aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool MatchSelectedOptions(nsIContent* aContent, int32_t, nsIAtom*,
|
||||||
|
void*);
|
||||||
|
|
||||||
|
nsIHTMLCollection* SelectedOptions();
|
||||||
|
|
||||||
int32_t SelectedIndex() const
|
int32_t SelectedIndex() const
|
||||||
{
|
{
|
||||||
return mSelectedIndex;
|
return mSelectedIndex;
|
||||||
|
@ -553,6 +560,12 @@ protected:
|
||||||
|
|
||||||
void SetSelectionChanged(bool aValue, bool aNotify);
|
void SetSelectionChanged(bool aValue, bool aNotify);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the selectedOptions list as dirty, so that it'll populate itself
|
||||||
|
* again.
|
||||||
|
*/
|
||||||
|
void UpdateSelectedOptions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether an element should have a validity UI.
|
* Return whether an element should have a validity UI.
|
||||||
* (with :-moz-ui-invalid and :-moz-ui-valid pseudo-classes).
|
* (with :-moz-ui-invalid and :-moz-ui-valid pseudo-classes).
|
||||||
|
@ -618,6 +631,11 @@ protected:
|
||||||
* done adding options
|
* done adding options
|
||||||
*/
|
*/
|
||||||
nsCOMPtr<SelectState> mRestoreState;
|
nsCOMPtr<SelectState> mRestoreState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The live list of selected options.
|
||||||
|
*/
|
||||||
|
nsRefPtr<nsContentList> mSelectedOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
@ -470,6 +470,13 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
|
||||||
|
|
||||||
if (filename16.IsEmpty()) {
|
if (filename16.IsEmpty()) {
|
||||||
filename16.AssignLiteral("blob");
|
filename16.AssignLiteral("blob");
|
||||||
|
} else {
|
||||||
|
nsAutoString filepath16;
|
||||||
|
rv = file->GetPath(filepath16);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
if (!filepath16.IsEmpty()) {
|
||||||
|
filename16 = filepath16 + NS_LITERAL_STRING("/") + filename16;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = EncodeVal(filename16, filename, true);
|
rv = EncodeVal(filename16, filename, true);
|
||||||
|
|
|
@ -67,6 +67,7 @@ MOCHITEST_FILES = \
|
||||||
test_input_color_picker_popup.html \
|
test_input_color_picker_popup.html \
|
||||||
test_input_color_input_change_events.html \
|
test_input_color_input_change_events.html \
|
||||||
test_restore_form_elements.html \
|
test_restore_form_elements.html \
|
||||||
|
test_select_selectedOptions.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=596681
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for HTMLSelectElement.selectedOptions</title>
|
||||||
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596681">Mozilla Bug 596681</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript;version=1.7">
|
||||||
|
|
||||||
|
/** Test for HTMLSelectElement's selectedOptions attribute.
|
||||||
|
*
|
||||||
|
* selectedOptions is a live list of the options that have selectedness of true
|
||||||
|
* (not the selected content attribute).
|
||||||
|
*
|
||||||
|
* See http://www.whatwg.org/html/#dom-select-selectedoptions
|
||||||
|
**/
|
||||||
|
|
||||||
|
function checkSelectedOptions(size, elements)
|
||||||
|
{
|
||||||
|
is(selectedOptions.length, size,
|
||||||
|
"select should have " + size + " selected options");
|
||||||
|
for (let i = 0; i < size; ++i) {
|
||||||
|
ok(selectedOptions[i], "selected option is valid");
|
||||||
|
if (selectedOptions[i]) {
|
||||||
|
is(selectedOptions[i].value, elements[i].value, "selected options are correct");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let select = document.createElement("select");
|
||||||
|
document.body.appendChild(select);
|
||||||
|
let selectedOptions = select.selectedOptions;
|
||||||
|
|
||||||
|
ok("selectedOptions" in select,
|
||||||
|
"select element should have a selectedOptions IDL attribute");
|
||||||
|
|
||||||
|
ok(select.selectedOptions instanceof HTMLCollection,
|
||||||
|
"selectedOptions should be an HTMLCollection instance");
|
||||||
|
|
||||||
|
let option1 = document.createElement("option");
|
||||||
|
let option2 = document.createElement("option");
|
||||||
|
let option3 = document.createElement("option");
|
||||||
|
option1.id = "option1";
|
||||||
|
option1.value = "option1";
|
||||||
|
option2.value = "option2";
|
||||||
|
option3.value = "option3";
|
||||||
|
|
||||||
|
checkSelectedOptions(0, null);
|
||||||
|
|
||||||
|
select.add(option1, null);
|
||||||
|
is(selectedOptions.namedItem("option1").value, "option1", "named getter works");
|
||||||
|
checkSelectedOptions(1, [option1]);
|
||||||
|
|
||||||
|
select.add(option2, null);
|
||||||
|
checkSelectedOptions(1, [option1]);
|
||||||
|
|
||||||
|
select.options[1].selected = true;
|
||||||
|
checkSelectedOptions(1, [option2]);
|
||||||
|
|
||||||
|
select.multiple = true;
|
||||||
|
checkSelectedOptions(1, [option2]);
|
||||||
|
|
||||||
|
select.options[0].selected = true;
|
||||||
|
checkSelectedOptions(2, [option1, option2]);
|
||||||
|
|
||||||
|
option1.selected = false;
|
||||||
|
// Usinig selected directly on the option should work.
|
||||||
|
checkSelectedOptions(1, [option2]);
|
||||||
|
|
||||||
|
select.remove(1);
|
||||||
|
select.add(option2, 0);
|
||||||
|
select.options[0].selected = true;
|
||||||
|
select.options[1].selected = true;
|
||||||
|
// Should be in tree order.
|
||||||
|
checkSelectedOptions(2, [option2, option1]);
|
||||||
|
|
||||||
|
select.add(option3, null);
|
||||||
|
checkSelectedOptions(2, [option2, option1]);
|
||||||
|
|
||||||
|
select.options[2].selected = true;
|
||||||
|
checkSelectedOptions(3, [option2, option1, option3]);
|
||||||
|
|
||||||
|
select.length = 0;
|
||||||
|
option1.selected = false;
|
||||||
|
option2.selected = false;
|
||||||
|
option3.selected = false;
|
||||||
|
var optgroup1 = document.createElement("optgroup");
|
||||||
|
optgroup1.appendChild(option1);
|
||||||
|
optgroup1.appendChild(option2);
|
||||||
|
select.add(optgroup1)
|
||||||
|
var optgroup2 = document.createElement("optgroup");
|
||||||
|
optgroup2.appendChild(option3);
|
||||||
|
select.add(optgroup2);
|
||||||
|
|
||||||
|
checkSelectedOptions(0, null);
|
||||||
|
|
||||||
|
option2.selected = true;
|
||||||
|
checkSelectedOptions(1, [option2]);
|
||||||
|
|
||||||
|
option3.selected = true;
|
||||||
|
checkSelectedOptions(2, [option2, option3]);
|
||||||
|
|
||||||
|
optgroup1.removeChild(option2);
|
||||||
|
checkSelectedOptions(1, [option3]);
|
||||||
|
|
||||||
|
document.body.removeChild(select);
|
||||||
|
option1.selected = true;
|
||||||
|
checkSelectedOptions(2, [option1, option3]);
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -107,9 +107,6 @@ static bool IsOmxSupported()
|
||||||
// nullptr is returned if Omx decoding is not supported on the device,
|
// nullptr is returned if Omx decoding is not supported on the device,
|
||||||
static const char* GetOmxLibraryName()
|
static const char* GetOmxLibraryName()
|
||||||
{
|
{
|
||||||
if (!IsOmxSupported())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
|
#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
|
||||||
nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
|
nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
|
||||||
NS_ASSERTION(infoService, "Could not find a system info service");
|
NS_ASSERTION(infoService, "Could not find a system info service");
|
||||||
|
@ -138,19 +135,18 @@ static const char* GetOmxLibraryName()
|
||||||
ALOG("Android Manufacturer is: %s", NS_LossyConvertUTF16toASCII(manufacturer).get());
|
ALOG("Android Manufacturer is: %s", NS_LossyConvertUTF16toASCII(manufacturer).get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version >= 16 && manufacturer.Find("HTC") == 0) {
|
nsAutoString hardware;
|
||||||
return "libomxpluginjb-htc.so";
|
rv = infoService->GetPropertyAsAString(NS_LITERAL_STRING("hardware"), hardware);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
ALOG("Android Hardware is: %s", NS_LossyConvertUTF16toASCII(hardware).get());
|
||||||
}
|
}
|
||||||
else if (version == 15 &&
|
#endif
|
||||||
(device.Find("LT28", false) == 0 ||
|
|
||||||
device.Find("LT26", false) == 0 ||
|
if (!IsOmxSupported())
|
||||||
device.Find("LT22", false) == 0 ||
|
return nullptr;
|
||||||
device.Find("IS12", false) == 0 ||
|
|
||||||
device.Find("MT27", false) == 0)) {
|
#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
|
||||||
// Sony Ericsson devices running ICS
|
if (version == 13 || version == 12 || version == 11) {
|
||||||
return "libomxpluginsony.so";
|
|
||||||
}
|
|
||||||
else if (version == 13 || version == 12 || version == 11) {
|
|
||||||
return "libomxpluginhc.so";
|
return "libomxpluginhc.so";
|
||||||
}
|
}
|
||||||
else if (version == 10 && release_version >= NS_LITERAL_STRING("2.3.6")) {
|
else if (version == 10 && release_version >= NS_LITERAL_STRING("2.3.6")) {
|
||||||
|
|
|
@ -61,7 +61,6 @@ MOCHITEST_FILES := \
|
||||||
test_convolverNode_mono_mono.html \
|
test_convolverNode_mono_mono.html \
|
||||||
test_currentTime.html \
|
test_currentTime.html \
|
||||||
test_delayNode.html \
|
test_delayNode.html \
|
||||||
test_delayNodeAtMax.html \
|
|
||||||
test_delayNodeSmallMaxDelay.html \
|
test_delayNodeSmallMaxDelay.html \
|
||||||
test_delayNodeWithGain.html \
|
test_delayNodeWithGain.html \
|
||||||
test_dynamicsCompressorNode.html \
|
test_dynamicsCompressorNode.html \
|
||||||
|
@ -113,4 +112,10 @@ MOCHITEST_FILES := \
|
||||||
audio-quad.wav \
|
audio-quad.wav \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
ifneq ($(MOZ_DEBUG)+$(MOZ_WIDGET_TOOLKIT),+gtk2) # bug 911777
|
||||||
|
MOCHITEST_FILES += \
|
||||||
|
test_delayNodeAtMax.html \
|
||||||
|
$(NULL)
|
||||||
|
endif
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
interface nsIDOMValidityState;
|
interface nsIDOMValidityState;
|
||||||
|
|
||||||
[scriptable, uuid(846578b2-6d4f-4399-86cc-2c05f19469d0)]
|
[scriptable, uuid(d8914a2d-3556-4b66-911c-a84c4394e7fa)]
|
||||||
interface nsIDOMHTMLSelectElement : nsISupports
|
interface nsIDOMHTMLSelectElement : nsISupports
|
||||||
{
|
{
|
||||||
attribute boolean autofocus;
|
attribute boolean autofocus;
|
||||||
|
@ -44,6 +44,7 @@ interface nsIDOMHTMLSelectElement : nsISupports
|
||||||
raises(DOMException);
|
raises(DOMException);
|
||||||
void remove(in long index);
|
void remove(in long index);
|
||||||
|
|
||||||
|
readonly attribute nsIDOMHTMLCollection selectedOptions;
|
||||||
attribute long selectedIndex;
|
attribute long selectedIndex;
|
||||||
attribute DOMString value;
|
attribute DOMString value;
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ interface HTMLInputElement : HTMLElement {
|
||||||
readonly attribute HTMLFormElement? form;
|
readonly attribute HTMLFormElement? form;
|
||||||
[Pure]
|
[Pure]
|
||||||
readonly attribute FileList? files;
|
readonly attribute FileList? files;
|
||||||
|
[Throws, Pref="dom.input.dirpicker"]
|
||||||
|
void openDirectoryPicker();
|
||||||
[Pure, SetterThrows]
|
[Pure, SetterThrows]
|
||||||
attribute DOMString formAction;
|
attribute DOMString formAction;
|
||||||
[Pure, SetterThrows]
|
[Pure, SetterThrows]
|
||||||
|
|
|
@ -38,7 +38,7 @@ interface HTMLSelectElement : HTMLElement {
|
||||||
[Throws]
|
[Throws]
|
||||||
setter creator void (unsigned long index, HTMLOptionElement? option);
|
setter creator void (unsigned long index, HTMLOptionElement? option);
|
||||||
|
|
||||||
// NYI: readonly attribute HTMLCollection selectedOptions;
|
readonly attribute HTMLCollection selectedOptions;
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute long selectedIndex;
|
attribute long selectedIndex;
|
||||||
[Pure]
|
[Pure]
|
||||||
|
|
|
@ -353,6 +353,29 @@ private:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
GetPath(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
|
||||||
|
JS::MutableHandle<JS::Value> aVp)
|
||||||
|
{
|
||||||
|
nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "path");
|
||||||
|
if (!file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsString path;
|
||||||
|
if (NS_FAILED(file->GetPath(path))) {
|
||||||
|
path.Truncate();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSString* jsPath = JS_NewUCStringCopyN(aCx, path.get(), path.Length());
|
||||||
|
if (!jsPath) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aVp.set(STRING_TO_JSVAL(jsPath));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
GetLastModifiedDate(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
|
GetLastModifiedDate(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
|
||||||
JS::MutableHandle<JS::Value> aVp)
|
JS::MutableHandle<JS::Value> aVp)
|
||||||
|
@ -382,6 +405,8 @@ JSClass File::sClass = {
|
||||||
const JSPropertySpec File::sProperties[] = {
|
const JSPropertySpec File::sProperties[] = {
|
||||||
{ "name", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetName),
|
{ "name", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetName),
|
||||||
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
|
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
|
||||||
|
{ "path", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetPath),
|
||||||
|
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
|
||||||
{ "lastModifiedDate", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetLastModifiedDate),
|
{ "lastModifiedDate", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetLastModifiedDate),
|
||||||
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
|
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
|
||||||
{ "mozFullPath", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetMozFullPath),
|
{ "mozFullPath", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetMozFullPath),
|
||||||
|
|
|
@ -514,13 +514,13 @@ LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */)
|
||||||
|
|
||||||
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
|
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
|
||||||
"gc_allocation_threshold_mb");
|
"gc_allocation_threshold_mb");
|
||||||
if (memPrefName == matchName || (!rts && index == 9)) {
|
if (memPrefName == matchName || (!rts && index == 8)) {
|
||||||
UpdateCommonJSGCMemoryOption(rts, matchName, JSGC_ALLOCATION_THRESHOLD);
|
UpdateCommonJSGCMemoryOption(rts, matchName, JSGC_ALLOCATION_THRESHOLD);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_incremental_slice_ms");
|
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_incremental_slice_ms");
|
||||||
if (memPrefName == matchName || (!rts && index == 10)) {
|
if (memPrefName == matchName || (!rts && index == 9)) {
|
||||||
int32_t prefValue = GetWorkerPref(matchName, -1);
|
int32_t prefValue = GetWorkerPref(matchName, -1);
|
||||||
uint32_t value =
|
uint32_t value =
|
||||||
(prefValue <= 0 || prefValue >= 100000) ? 0 : uint32_t(prefValue);
|
(prefValue <= 0 || prefValue >= 100000) ? 0 : uint32_t(prefValue);
|
||||||
|
@ -529,7 +529,7 @@ LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */)
|
||||||
}
|
}
|
||||||
|
|
||||||
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_dynamic_heap_growth");
|
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_dynamic_heap_growth");
|
||||||
if (memPrefName == matchName || (!rts && index == 11)) {
|
if (memPrefName == matchName || (!rts && index == 10)) {
|
||||||
bool prefValue = GetWorkerPref(matchName, false);
|
bool prefValue = GetWorkerPref(matchName, false);
|
||||||
UpdatOtherJSGCMemoryOption(rts, JSGC_DYNAMIC_HEAP_GROWTH,
|
UpdatOtherJSGCMemoryOption(rts, JSGC_DYNAMIC_HEAP_GROWTH,
|
||||||
prefValue ? 0 : 1);
|
prefValue ? 0 : 1);
|
||||||
|
@ -537,7 +537,7 @@ LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */)
|
||||||
}
|
}
|
||||||
|
|
||||||
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_dynamic_mark_slice");
|
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_dynamic_mark_slice");
|
||||||
if (memPrefName == matchName || (!rts && index == 12)) {
|
if (memPrefName == matchName || (!rts && index == 11)) {
|
||||||
bool prefValue = GetWorkerPref(matchName, false);
|
bool prefValue = GetWorkerPref(matchName, false);
|
||||||
UpdatOtherJSGCMemoryOption(rts, JSGC_DYNAMIC_MARK_SLICE,
|
UpdatOtherJSGCMemoryOption(rts, JSGC_DYNAMIC_MARK_SLICE,
|
||||||
prefValue ? 0 : 1);
|
prefValue ? 0 : 1);
|
||||||
|
|
|
@ -9,6 +9,7 @@ onmessage = function(event) {
|
||||||
rtnObj.size = file.size;
|
rtnObj.size = file.size;
|
||||||
rtnObj.type = file.type;
|
rtnObj.type = file.type;
|
||||||
rtnObj.name = file.name;
|
rtnObj.name = file.name;
|
||||||
|
rtnObj.path = file.path;
|
||||||
rtnObj.lastModifiedDate = file.lastModifiedDate;
|
rtnObj.lastModifiedDate = file.lastModifiedDate;
|
||||||
rtnObj.mozFullPath = file.mozFullPath;
|
rtnObj.mozFullPath = file.mozFullPath;
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=123456
|
||||||
is(event.data.size, expectedSize, "size proproperty accessed from worker is not the same as on main thread.");
|
is(event.data.size, expectedSize, "size proproperty accessed from worker is not the same as on main thread.");
|
||||||
is(event.data.type, expectedType, "type proproperty accessed from worker is incorrect.");
|
is(event.data.type, expectedType, "type proproperty accessed from worker is incorrect.");
|
||||||
is(event.data.name, file.name, "name proproperty accessed from worker is incorrect.");
|
is(event.data.name, file.name, "name proproperty accessed from worker is incorrect.");
|
||||||
|
is(event.data.path, file.path, "path proproperty accessed from worker is incorrect.");
|
||||||
is(event.data.lastModifiedDate.toString(), file.lastModifiedDate.toString(), "lastModifiedDate proproperty accessed from worker is incorrect.");
|
is(event.data.lastModifiedDate.toString(), file.lastModifiedDate.toString(), "lastModifiedDate proproperty accessed from worker is incorrect.");
|
||||||
is(event.data.mozFullPath, file.mozFullPath, "mozFullPath proproperty accessed from worker is not the same as on main thread.");
|
is(event.data.mozFullPath, file.mozFullPath, "mozFullPath proproperty accessed from worker is not the same as on main thread.");
|
||||||
finish();
|
finish();
|
||||||
|
|
|
@ -256,7 +256,8 @@ ImageClientSingle::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, Texture
|
||||||
TemporaryRef<BufferTextureClient>
|
TemporaryRef<BufferTextureClient>
|
||||||
ImageClientSingle::CreateBufferTextureClient(gfx::SurfaceFormat aFormat)
|
ImageClientSingle::CreateBufferTextureClient(gfx::SurfaceFormat aFormat)
|
||||||
{
|
{
|
||||||
return CompositableClient::CreateBufferTextureClient(aFormat, mTextureFlags);
|
return CompositableClient::CreateBufferTextureClient(aFormat,
|
||||||
|
mTextureFlags | TEXTURE_FLAGS_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -4383,7 +4383,36 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PR_LOGGING
|
||||||
|
PRLogModuleInfo *log = (mStyle.systemFont ?
|
||||||
|
gfxPlatform::GetLog(eGfxLog_textrunui) :
|
||||||
|
gfxPlatform::GetLog(eGfxLog_textrun));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (sizeof(T) == sizeof(uint8_t) && !transformedString) {
|
if (sizeof(T) == sizeof(uint8_t) && !transformedString) {
|
||||||
|
|
||||||
|
#ifdef PR_LOGGING
|
||||||
|
if (MOZ_UNLIKELY(log)) {
|
||||||
|
nsAutoCString lang;
|
||||||
|
mStyle.language->ToUTF8String(lang);
|
||||||
|
nsAutoCString str((const char*)aString, aLength);
|
||||||
|
PR_LOG(log, PR_LOG_WARNING,\
|
||||||
|
("(%s) fontgroup: [%s] lang: %s script: %d len %d "
|
||||||
|
"weight: %d width: %d style: %s size: %6.2f %d-byte "
|
||||||
|
"TEXTRUN [%s] ENDTEXTRUN\n",
|
||||||
|
(mStyle.systemFont ? "textrunui" : "textrun"),
|
||||||
|
NS_ConvertUTF16toUTF8(mFamilies).get(),
|
||||||
|
lang.get(), MOZ_SCRIPT_LATIN, aLength,
|
||||||
|
uint32_t(mStyle.weight), uint32_t(mStyle.stretch),
|
||||||
|
(mStyle.style & NS_FONT_STYLE_ITALIC ? "italic" :
|
||||||
|
(mStyle.style & NS_FONT_STYLE_OBLIQUE ? "oblique" :
|
||||||
|
"normal")),
|
||||||
|
mStyle.size,
|
||||||
|
sizeof(T),
|
||||||
|
str.get()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// the text is still purely 8-bit; bypass the script-run itemizer
|
// the text is still purely 8-bit; bypass the script-run itemizer
|
||||||
// and treat it as a single Latin run
|
// and treat it as a single Latin run
|
||||||
InitScriptRun(aContext, aTextRun, aString,
|
InitScriptRun(aContext, aTextRun, aString,
|
||||||
|
@ -4402,12 +4431,6 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
|
||||||
// the font matching process below
|
// the font matching process below
|
||||||
gfxScriptItemizer scriptRuns(textPtr, aLength);
|
gfxScriptItemizer scriptRuns(textPtr, aLength);
|
||||||
|
|
||||||
#ifdef PR_LOGGING
|
|
||||||
PRLogModuleInfo *log = (mStyle.systemFont ?
|
|
||||||
gfxPlatform::GetLog(eGfxLog_textrunui) :
|
|
||||||
gfxPlatform::GetLog(eGfxLog_textrun));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t runStart = 0, runLimit = aLength;
|
uint32_t runStart = 0, runLimit = aLength;
|
||||||
int32_t runScript = MOZ_SCRIPT_LATIN;
|
int32_t runScript = MOZ_SCRIPT_LATIN;
|
||||||
while (scriptRuns.Next(runStart, runLimit, runScript)) {
|
while (scriptRuns.Next(runStart, runLimit, runScript)) {
|
||||||
|
@ -4419,7 +4442,7 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
|
||||||
uint32_t runLen = runLimit - runStart;
|
uint32_t runLen = runLimit - runStart;
|
||||||
PR_LOG(log, PR_LOG_WARNING,\
|
PR_LOG(log, PR_LOG_WARNING,\
|
||||||
("(%s) fontgroup: [%s] lang: %s script: %d len %d "
|
("(%s) fontgroup: [%s] lang: %s script: %d len %d "
|
||||||
"weight: %d width: %d style: %s "
|
"weight: %d width: %d style: %s size: %6.2f %d-byte "
|
||||||
"TEXTRUN [%s] ENDTEXTRUN\n",
|
"TEXTRUN [%s] ENDTEXTRUN\n",
|
||||||
(mStyle.systemFont ? "textrunui" : "textrun"),
|
(mStyle.systemFont ? "textrunui" : "textrun"),
|
||||||
NS_ConvertUTF16toUTF8(mFamilies).get(),
|
NS_ConvertUTF16toUTF8(mFamilies).get(),
|
||||||
|
@ -4428,6 +4451,8 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
|
||||||
(mStyle.style & NS_FONT_STYLE_ITALIC ? "italic" :
|
(mStyle.style & NS_FONT_STYLE_ITALIC ? "italic" :
|
||||||
(mStyle.style & NS_FONT_STYLE_OBLIQUE ? "oblique" :
|
(mStyle.style & NS_FONT_STYLE_OBLIQUE ? "oblique" :
|
||||||
"normal")),
|
"normal")),
|
||||||
|
mStyle.size,
|
||||||
|
sizeof(T),
|
||||||
NS_ConvertUTF16toUTF8(textPtr + runStart, runLen).get()));
|
NS_ConvertUTF16toUTF8(textPtr + runStart, runLen).get()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,9 +39,9 @@ class JavaScriptParent
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc, unsigned flags);
|
JS::MutableHandle<JSPropertyDescriptor> desc, unsigned flags);
|
||||||
bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||||
bool getOwnPropertyNames(JSContext *cx, JS::HandleObject proxy, js::AutoIdVector &props);
|
bool getOwnPropertyNames(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||||
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||||
bool enumerate(JSContext *cx, JS::HandleObject proxy, js::AutoIdVector &props);
|
bool enumerate(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||||
|
|
||||||
// Derived proxy traps. Implementing these is useful for perfomance.
|
// Derived proxy traps. Implementing these is useful for perfomance.
|
||||||
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||||
|
@ -50,7 +50,7 @@ class JavaScriptParent
|
||||||
JS::HandleId id, JS::MutableHandleValue vp);
|
JS::HandleId id, JS::MutableHandleValue vp);
|
||||||
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp);
|
JS::HandleId id, bool strict, JS::MutableHandleValue vp);
|
||||||
bool keys(JSContext *cx, JS::HandleObject proxy, js::AutoIdVector &props);
|
bool keys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||||
// We use "iterate" provided by the base class here.
|
// We use "iterate" provided by the base class here.
|
||||||
|
|
||||||
// SpiderMonkey Extensions.
|
// SpiderMonkey Extensions.
|
||||||
|
@ -82,7 +82,8 @@ class JavaScriptParent
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool makeId(JSContext *cx, JSObject *obj, ObjectId *idp);
|
bool makeId(JSContext *cx, JSObject *obj, ObjectId *idp);
|
||||||
bool getPropertyNames(JSContext *cx, JS::HandleObject proxy, uint32_t flags, js::AutoIdVector &props);
|
bool getPropertyNames(JSContext *cx, JS::HandleObject proxy, uint32_t flags,
|
||||||
|
JS::AutoIdVector &props);
|
||||||
ObjectId idOf(JSObject *obj);
|
ObjectId idOf(JSObject *obj);
|
||||||
|
|
||||||
// Catastrophic IPC failure.
|
// Catastrophic IPC failure.
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
/* -*- 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/. */
|
||||||
|
|
||||||
|
// This file imports some common JS:: names into the js namespace so we can
|
||||||
|
// make unqualified references to them.
|
||||||
|
|
||||||
|
#ifndef NamespaceImports_h
|
||||||
|
#define NamespaceImports_h
|
||||||
|
|
||||||
|
// These includes are needed these for some typedefs (e.g. HandleValue) and
|
||||||
|
// functions (e.g. NullValue())...
|
||||||
|
#include "js/CallNonGenericMethod.h"
|
||||||
|
#include "js/TypeDecls.h"
|
||||||
|
#include "js/Value.h"
|
||||||
|
|
||||||
|
// ... but we do forward declarations of the structs and classes not pulled in
|
||||||
|
// by the headers included above.
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
class Latin1CharsZ;
|
||||||
|
class StableCharPtr;
|
||||||
|
class TwoByteChars;
|
||||||
|
|
||||||
|
class AutoFunctionVector;
|
||||||
|
class AutoIdVector;
|
||||||
|
class AutoObjectVector;
|
||||||
|
class AutoScriptVector;
|
||||||
|
class AutoValueVector;
|
||||||
|
|
||||||
|
class AutoIdArray;
|
||||||
|
|
||||||
|
class AutoGCRooter;
|
||||||
|
class AutoArrayRooter;
|
||||||
|
template <typename T> class AutoVectorRooter;
|
||||||
|
template<typename K, typename V> class AutoHashMapRooter;
|
||||||
|
template<typename T> class AutoHashSetRooter;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the importing.
|
||||||
|
namespace js {
|
||||||
|
|
||||||
|
using JS::Value;
|
||||||
|
using JS::BooleanValue;
|
||||||
|
using JS::DoubleValue;
|
||||||
|
using JS::Int32Value;
|
||||||
|
using JS::IsPoisonedValue;
|
||||||
|
using JS::MagicValue;
|
||||||
|
using JS::NullValue;
|
||||||
|
using JS::NumberValue;
|
||||||
|
using JS::ObjectOrNullValue;
|
||||||
|
using JS::ObjectValue;
|
||||||
|
using JS::PrivateUint32Value;
|
||||||
|
using JS::PrivateValue;
|
||||||
|
using JS::StringValue;
|
||||||
|
using JS::UndefinedValue;
|
||||||
|
|
||||||
|
using JS::IsPoisonedPtr;
|
||||||
|
|
||||||
|
using JS::Latin1CharsZ;
|
||||||
|
using JS::StableCharPtr;
|
||||||
|
using JS::TwoByteChars;
|
||||||
|
|
||||||
|
using JS::AutoFunctionVector;
|
||||||
|
using JS::AutoIdVector;
|
||||||
|
using JS::AutoObjectVector;
|
||||||
|
using JS::AutoScriptVector;
|
||||||
|
using JS::AutoValueVector;
|
||||||
|
|
||||||
|
using JS::AutoIdArray;
|
||||||
|
|
||||||
|
using JS::AutoGCRooter;
|
||||||
|
using JS::AutoArrayRooter;
|
||||||
|
using JS::AutoHashMapRooter;
|
||||||
|
using JS::AutoHashSetRooter;
|
||||||
|
using JS::AutoVectorRooter;
|
||||||
|
|
||||||
|
using JS::CallArgs;
|
||||||
|
using JS::CallNonGenericMethod;
|
||||||
|
using JS::CallReceiver;
|
||||||
|
using JS::CompileOptions;
|
||||||
|
using JS::IsAcceptableThis;
|
||||||
|
using JS::NativeImpl;
|
||||||
|
|
||||||
|
using JS::Rooted;
|
||||||
|
using JS::RootedFunction;
|
||||||
|
using JS::RootedId;
|
||||||
|
using JS::RootedObject;
|
||||||
|
using JS::RootedScript;
|
||||||
|
using JS::RootedString;
|
||||||
|
using JS::RootedValue;
|
||||||
|
|
||||||
|
using JS::Handle;
|
||||||
|
using JS::HandleFunction;
|
||||||
|
using JS::HandleId;
|
||||||
|
using JS::HandleObject;
|
||||||
|
using JS::HandleScript;
|
||||||
|
using JS::HandleString;
|
||||||
|
using JS::HandleValue;
|
||||||
|
|
||||||
|
using JS::MutableHandle;
|
||||||
|
using JS::MutableHandleFunction;
|
||||||
|
using JS::MutableHandleId;
|
||||||
|
using JS::MutableHandleObject;
|
||||||
|
using JS::MutableHandleScript;
|
||||||
|
using JS::MutableHandleString;
|
||||||
|
using JS::MutableHandleValue;
|
||||||
|
|
||||||
|
using JS::Zone;
|
||||||
|
|
||||||
|
} /* namespace js */
|
||||||
|
|
||||||
|
#endif /* NamespaceImports_h */
|
|
@ -223,7 +223,8 @@ if test "$GNU_CC"; then
|
||||||
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
|
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
|
||||||
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
|
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
|
||||||
fi
|
fi
|
||||||
CXXFLAGS="$CXXFLAGS -fno-exceptions"
|
CFLAGS="$CFLAGS -fno-math-errno"
|
||||||
|
CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#ifndef builtin_BinaryData_h
|
#ifndef builtin_BinaryData_h
|
||||||
#define builtin_BinaryData_h
|
#define builtin_BinaryData_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
|
||||||
#include "jsobj.h"
|
#include "jsobj.h"
|
||||||
|
|
||||||
#include "builtin/TypeRepresentation.h"
|
#include "builtin/TypeRepresentation.h"
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
#ifndef builtin_Eval_h
|
#ifndef builtin_Eval_h
|
||||||
#define builtin_Eval_h
|
#define builtin_Eval_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
|
||||||
#include "jsbytecode.h"
|
#include "jsbytecode.h"
|
||||||
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#ifndef builtin_Intl_h
|
#ifndef builtin_Intl_h
|
||||||
#define builtin_Intl_h
|
#define builtin_Intl_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
#include "js/RootingAPI.h"
|
#include "js/RootingAPI.h"
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#ifndef builtin_TestingFunctions_h
|
#ifndef builtin_TestingFunctions_h
|
||||||
#define builtin_TestingFunctions_h
|
#define builtin_TestingFunctions_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
@ -15,10 +15,10 @@ bool
|
||||||
DefineTestingFunctions(JSContext *cx, HandleObject obj);
|
DefineTestingFunctions(JSContext *cx, HandleObject obj);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
testingFunc_inParallelSection(JSContext *cx, unsigned argc, jsval *vp);
|
testingFunc_inParallelSection(JSContext *cx, unsigned argc, Value *vp);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
testingFunc_bailout(JSContext *cx, unsigned argc, jsval *vp);
|
testingFunc_bailout(JSContext *cx, unsigned argc, Value *vp);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,7 @@ changequote(,)
|
||||||
MOZJS_MAJOR_VERSION=`echo $MOZILLA_VERSION | sed "s|\(^[0-9]*\)\.[0-9]*.*|\1|"`
|
MOZJS_MAJOR_VERSION=`echo $MOZILLA_VERSION | sed "s|\(^[0-9]*\)\.[0-9]*.*|\1|"`
|
||||||
MOZJS_MINOR_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.\([0-9]*\).*|\1|"`
|
MOZJS_MINOR_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.\([0-9]*\).*|\1|"`
|
||||||
MOZJS_PATCH_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.[0-9]*[^0-9]*||"`
|
MOZJS_PATCH_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.[0-9]*[^0-9]*||"`
|
||||||
IS_ALPHA=`echo $MOZILLA_VERSION | grep [ab]`
|
IS_ALPHA=`echo $MOZILLA_VERSION | grep '[ab]'`
|
||||||
|
|
||||||
dnl XXX in a temporary bid to avoid developer anger at renaming files
|
dnl XXX in a temporary bid to avoid developer anger at renaming files
|
||||||
dnl XXX before "js" symlinks exist, don't change names.
|
dnl XXX before "js" symlinks exist, don't change names.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#ifndef ds_IdValuePair_h
|
#ifndef ds_IdValuePair_h
|
||||||
#define ds_IdValuePair_h
|
#define ds_IdValuePair_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#ifndef frontend_BytecodeCompiler_h
|
#ifndef frontend_BytecodeCompiler_h
|
||||||
#define frontend_BytecodeCompiler_h
|
#define frontend_BytecodeCompiler_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
class JSLinearString;
|
class JSLinearString;
|
||||||
|
|
||||||
|
|
|
@ -317,6 +317,12 @@ struct CompileError {
|
||||||
}
|
}
|
||||||
~CompileError();
|
~CompileError();
|
||||||
void throwError(JSContext *cx);
|
void throwError(JSContext *cx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// CompileError owns raw allocated memory, so disable assignment and copying
|
||||||
|
// for safety.
|
||||||
|
void operator=(const CompileError &) MOZ_DELETE;
|
||||||
|
CompileError(const CompileError &) MOZ_DELETE;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ideally, tokenizing would be entirely independent of context. But the
|
// Ideally, tokenizing would be entirely independent of context. But the
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define gc_Barrier_h
|
#define gc_Barrier_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
#include "gc/Heap.h"
|
#include "gc/Heap.h"
|
||||||
#include "js/HashTable.h"
|
#include "js/HashTable.h"
|
||||||
|
|
|
@ -10,10 +10,11 @@
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/PodOperations.h"
|
#include "mozilla/PodOperations.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsalloc.h"
|
||||||
#include "jspubtd.h"
|
#include "jspubtd.h"
|
||||||
|
|
||||||
#include "js/GCAPI.h"
|
#include "js/GCAPI.h"
|
||||||
|
#include "js/Vector.h"
|
||||||
|
|
||||||
struct JSCompartment;
|
struct JSCompartment;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
// actually run.)
|
// actually run.)
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
void breakpoint();
|
void breakpoint();
|
||||||
|
|
||||||
|
|
|
@ -5223,7 +5223,7 @@ StackDecrementForCall(MacroAssembler &masm, const VectorT &argTypes, unsigned ex
|
||||||
|
|
||||||
static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * STACK_SLOT_SIZE +
|
static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * STACK_SLOT_SIZE +
|
||||||
NonVolatileRegs.fpus().size() * sizeof(double);
|
NonVolatileRegs.fpus().size() * sizeof(double);
|
||||||
#ifndef JS_CPU_ARM
|
|
||||||
static bool
|
static bool
|
||||||
GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFunc)
|
GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFunc)
|
||||||
{
|
{
|
||||||
|
@ -5237,72 +5237,85 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
|
||||||
// PushRegsInMask(NonVolatileRegs).
|
// PushRegsInMask(NonVolatileRegs).
|
||||||
masm.setFramePushed(0);
|
masm.setFramePushed(0);
|
||||||
masm.PushRegsInMask(NonVolatileRegs);
|
masm.PushRegsInMask(NonVolatileRegs);
|
||||||
|
JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
|
||||||
|
|
||||||
// Remember the stack pointer in the current AsmJSActivation. This will be
|
// Remember the stack pointer in the current AsmJSActivation. This will be
|
||||||
// used by error exit paths to set the stack pointer back to what it was
|
// used by error exit paths to set the stack pointer back to what it was
|
||||||
// right after the (C++) caller's non-volatile registers were saved so that
|
// right after the (C++) caller's non-volatile registers were saved so that
|
||||||
// they can be restored.
|
// they can be restored.
|
||||||
JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
|
|
||||||
Register activation = ABIArgGenerator::NonArgReturnVolatileReg0;
|
Register activation = ABIArgGenerator::NonArgReturnVolatileReg0;
|
||||||
LoadAsmJSActivationIntoRegister(masm, activation);
|
LoadAsmJSActivationIntoRegister(masm, activation);
|
||||||
masm.movePtr(StackPointer, Operand(activation, AsmJSActivation::offsetOfErrorRejoinSP()));
|
masm.storePtr(StackPointer, Address(activation, AsmJSActivation::offsetOfErrorRejoinSP()));
|
||||||
|
|
||||||
#if defined(JS_CPU_X64)
|
// ARM has a globally-pinned GlobalReg (x64 uses RIP-relative addressing,
|
||||||
// Install the heap pointer into the globally-pinned HeapReg. The heap
|
// x86 uses immediates in effective addresses) and NaN register (used as
|
||||||
// pointer is stored in the global data section and is patched at dynamic
|
// part of the out-of-bounds handling in heap loads/stores).
|
||||||
// link time.
|
#if defined(JS_CPU_ARM)
|
||||||
CodeOffsetLabel label = masm.loadRipRelativeInt64(HeapReg);
|
masm.movePtr(IntArgReg1, GlobalReg);
|
||||||
m.addGlobalAccess(AsmJSGlobalAccess(label.offset(), m.module().heapOffset()));
|
masm.ma_vimm(js_NaN, NANReg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// ARM and x64 have a globally-pinned HeapReg (x86 uses immediates in
|
||||||
|
// effective addresses).
|
||||||
|
#if defined(JS_CPU_X64) || defined(JS_CPU_ARM)
|
||||||
|
masm.loadPtr(Address(IntArgReg1, m.module().heapOffset()), HeapReg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Get 'argv' into a non-arg register and save it on the stack.
|
||||||
Register argv = ABIArgGenerator::NonArgReturnVolatileReg0;
|
Register argv = ABIArgGenerator::NonArgReturnVolatileReg0;
|
||||||
Register scratch = ABIArgGenerator::NonArgReturnVolatileReg1;
|
Register scratch = ABIArgGenerator::NonArgReturnVolatileReg1;
|
||||||
#if defined(JS_CPU_X86)
|
#if defined(JS_CPU_X86)
|
||||||
masm.movl(Operand(StackPointer, NativeFrameSize + masm.framePushed()), argv);
|
masm.loadPtr(Address(StackPointer, NativeFrameSize + masm.framePushed()), argv);
|
||||||
#elif defined(JS_CPU_X64)
|
#else
|
||||||
masm.movq(IntArgReg0, argv);
|
masm.movePtr(IntArgReg0, argv);
|
||||||
masm.Push(argv);
|
|
||||||
#endif
|
#endif
|
||||||
|
masm.Push(argv);
|
||||||
|
|
||||||
// Bump the stack for the call.
|
// Bump the stack for the call.
|
||||||
const ModuleCompiler::Func &func = *m.lookupFunction(exportedFunc.name());
|
const ModuleCompiler::Func &func = *m.lookupFunction(exportedFunc.name());
|
||||||
unsigned stackDec = StackDecrementForCall(masm, func.sig().args());
|
unsigned stackDec = StackDecrementForCall(masm, func.sig().args());
|
||||||
masm.reserveStack(stackDec);
|
masm.reserveStack(stackDec);
|
||||||
|
|
||||||
|
// Copy parameters out of argv and into the registers/stack-slots specified by
|
||||||
|
// the system ABI.
|
||||||
for (ABIArgTypeIter iter(func.sig().args()); !iter.done(); iter++) {
|
for (ABIArgTypeIter iter(func.sig().args()); !iter.done(); iter++) {
|
||||||
Operand src(argv, iter.index() * sizeof(uint64_t));
|
unsigned argOffset = iter.index() * sizeof(uint64_t);
|
||||||
|
Address src(argv, argOffset);
|
||||||
switch (iter->kind()) {
|
switch (iter->kind()) {
|
||||||
case ABIArg::GPR:
|
case ABIArg::GPR:
|
||||||
masm.load32(src, iter->gpr());
|
masm.load32(src, iter->gpr());
|
||||||
break;
|
break;
|
||||||
case ABIArg::FPU:
|
case ABIArg::FPU:
|
||||||
|
#if defined(JS_CPU_ARM) and !defined(JS_CPU_ARM_HARDFP)
|
||||||
|
masm.ma_dataTransferN(IsLoad, 64, true, argv, Imm32(argOffset),
|
||||||
|
Register::FromCode(iter->fpu().code()*2));
|
||||||
|
#else
|
||||||
masm.loadDouble(src, iter->fpu());
|
masm.loadDouble(src, iter->fpu());
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case ABIArg::Stack:
|
case ABIArg::Stack:
|
||||||
if (iter.mirType() == MIRType_Int32) {
|
if (iter.mirType() == MIRType_Int32) {
|
||||||
masm.load32(src, scratch);
|
masm.load32(src, scratch);
|
||||||
masm.storePtr(scratch, Operand(StackPointer, iter->offsetFromArgBase()));
|
masm.storePtr(scratch, Address(StackPointer, iter->offsetFromArgBase()));
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(iter.mirType() == MIRType_Double);
|
JS_ASSERT(iter.mirType() == MIRType_Double);
|
||||||
masm.loadDouble(src, ScratchFloatReg);
|
masm.loadDouble(src, ScratchFloatReg);
|
||||||
masm.storeDouble(ScratchFloatReg, Operand(StackPointer, iter->offsetFromArgBase()));
|
masm.storeDouble(ScratchFloatReg, Address(StackPointer, iter->offsetFromArgBase()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call into the real function.
|
||||||
AssertStackAlignment(masm);
|
AssertStackAlignment(masm);
|
||||||
masm.call(func.code());
|
masm.call(func.code());
|
||||||
|
|
||||||
|
// Pop the stack and recover the original 'argv' argument passed to the
|
||||||
|
// trampoline (which was pushed on the stack).
|
||||||
masm.freeStack(stackDec);
|
masm.freeStack(stackDec);
|
||||||
|
|
||||||
#if defined(JS_CPU_X86)
|
|
||||||
masm.movl(Operand(StackPointer, NativeFrameSize + masm.framePushed()), argv);
|
|
||||||
#elif defined(JS_CPU_X64)
|
|
||||||
masm.Pop(argv);
|
masm.Pop(argv);
|
||||||
#endif
|
|
||||||
|
|
||||||
// Store return value in argv[0]
|
// Store the return value in argv[0]
|
||||||
switch (func.sig().retType().which()) {
|
switch (func.sig().retType().which()) {
|
||||||
case RetType::Void:
|
case RetType::Void:
|
||||||
break;
|
break;
|
||||||
|
@ -5310,119 +5323,7 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
|
||||||
masm.storeValue(JSVAL_TYPE_INT32, ReturnReg, Address(argv, 0));
|
masm.storeValue(JSVAL_TYPE_INT32, ReturnReg, Address(argv, 0));
|
||||||
break;
|
break;
|
||||||
case RetType::Double:
|
case RetType::Double:
|
||||||
masm.canonicalizeDouble(ReturnFloatReg);
|
#if defined(JS_CPU_ARM) and !defined(JS_CPU_ARM_HARDFP)
|
||||||
masm.storeDouble(ReturnFloatReg, Address(argv, 0));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore clobbered registers.
|
|
||||||
masm.PopRegsInMask(NonVolatileRegs);
|
|
||||||
JS_ASSERT(masm.framePushed() == 0);
|
|
||||||
|
|
||||||
masm.move32(Imm32(true), ReturnReg);
|
|
||||||
masm.ret();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static bool
|
|
||||||
GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFunc)
|
|
||||||
{
|
|
||||||
const ModuleCompiler::Func &func = *m.lookupFunction(exportedFunc.name());
|
|
||||||
|
|
||||||
MacroAssembler &masm = m.masm();
|
|
||||||
|
|
||||||
// In constrast to the X64 system ABI, the Ion convention is that all
|
|
||||||
// registers are clobbered by calls. Thus, we must save the caller's
|
|
||||||
// non-volatile registers.
|
|
||||||
//
|
|
||||||
// NB: GenerateExits assumes that masm.framePushed() == 0 before
|
|
||||||
// PushRegsInMask(NonVolatileRegs).
|
|
||||||
masm.setFramePushed(0);
|
|
||||||
masm.PushRegsInMask(NonVolatileRegs);
|
|
||||||
JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
|
|
||||||
JS_ASSERT(masm.framePushed() % 8 == 0);
|
|
||||||
|
|
||||||
// Remember the stack pointer in the current AsmJSActivation. This will be
|
|
||||||
// used by error exit paths to set the stack pointer back to what it was
|
|
||||||
// right after the (C++) caller's non-volatile registers were saved so that
|
|
||||||
// they can be restored.
|
|
||||||
|
|
||||||
LoadAsmJSActivationIntoRegister(masm, r9);
|
|
||||||
masm.ma_str(StackPointer, Address(r9, AsmJSActivation::offsetOfErrorRejoinSP()));
|
|
||||||
// masm.storeErrorRejoinSp();
|
|
||||||
|
|
||||||
// Move the parameters into non-argument registers since we are about to
|
|
||||||
// clobber these registers with the contents of argv.
|
|
||||||
Register argv = r9;
|
|
||||||
masm.movePtr(IntArgReg1, GlobalReg); // globalData
|
|
||||||
masm.movePtr(IntArgReg0, argv); // argv
|
|
||||||
|
|
||||||
masm.ma_ldr(Operand(GlobalReg, Imm32(m.module().heapOffset())), HeapReg);
|
|
||||||
// Remember argv so that we can load argv[0] after the call.
|
|
||||||
JS_ASSERT(masm.framePushed() % 8 == 0);
|
|
||||||
masm.Push(argv);
|
|
||||||
JS_ASSERT(masm.framePushed() % 8 == 4);
|
|
||||||
|
|
||||||
// Determine how many stack slots we need to hold arguments that don't fit
|
|
||||||
// in registers.
|
|
||||||
unsigned numStackArgs = 0;
|
|
||||||
for (ABIArgTypeIter iter(func.sig().args()); !iter.done(); iter++) {
|
|
||||||
if (iter->kind() == ABIArg::Stack)
|
|
||||||
numStackArgs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before calling, we must ensure sp % 16 == 0. Since (sp % 16) = 8 on
|
|
||||||
// entry, we need to push 8 (mod 16) bytes.
|
|
||||||
//JS_ASSERT(AlignmentAtPrologue == 8);
|
|
||||||
JS_ASSERT(masm.framePushed() % 8 == 4);
|
|
||||||
unsigned stackDec = numStackArgs * sizeof(double) + (masm.framePushed() >> 2) % 2 * sizeof(uint32_t);
|
|
||||||
masm.reserveStack(stackDec);
|
|
||||||
//JS_ASSERT(masm.framePushed() % 8 == 0);
|
|
||||||
if(getenv("GDB_BREAK")) {
|
|
||||||
masm.breakpoint(js::jit::Assembler::Always);
|
|
||||||
}
|
|
||||||
// Copy parameters out of argv into the registers/stack-slots specified by
|
|
||||||
// the system ABI.
|
|
||||||
for (ABIArgTypeIter iter(func.sig().args()); !iter.done(); iter++) {
|
|
||||||
unsigned argOffset = iter.index() * sizeof(uint64_t);
|
|
||||||
switch (iter->kind()) {
|
|
||||||
case ABIArg::GPR:
|
|
||||||
masm.ma_ldr(Operand(argv, argOffset), iter->gpr());
|
|
||||||
break;
|
|
||||||
case ABIArg::FPU:
|
|
||||||
#if defined(JS_CPU_ARM_HARDFP)
|
|
||||||
masm.ma_vldr(Operand(argv, argOffset), iter->fpu());
|
|
||||||
#else
|
|
||||||
// The ABI is expecting a double value in a pair of gpr's. Figure out which gprs it is,
|
|
||||||
// and use them explicityl.
|
|
||||||
masm.ma_dataTransferN(IsLoad, 64, true, argv, Imm32(argOffset), Register::FromCode(iter->fpu().code()*2));
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case ABIArg::Stack:
|
|
||||||
if (iter.mirType() == MIRType_Int32) {
|
|
||||||
masm.memMove32(Address(argv, argOffset), Address(StackPointer, iter->offsetFromArgBase()));
|
|
||||||
} else {
|
|
||||||
masm.memMove64(Address(argv, argOffset), Address(StackPointer, iter->offsetFromArgBase()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
masm.ma_vimm(js_NaN, NANReg);
|
|
||||||
masm.call(func.code());
|
|
||||||
|
|
||||||
// Recover argv.
|
|
||||||
masm.freeStack(stackDec);
|
|
||||||
masm.Pop(argv);
|
|
||||||
|
|
||||||
// Store the result in argv[0].
|
|
||||||
switch (func.sig().retType().which()) {
|
|
||||||
case RetType::Void:
|
|
||||||
break;
|
|
||||||
case RetType::Signed:
|
|
||||||
masm.storeValue(JSVAL_TYPE_INT32, ReturnReg, Address(argv, 0));
|
|
||||||
break;
|
|
||||||
case RetType::Double:
|
|
||||||
#ifndef JS_CPU_ARM_HARDFP
|
|
||||||
masm.ma_vxfer(r0, r1, d0);
|
masm.ma_vxfer(r0, r1, d0);
|
||||||
#endif
|
#endif
|
||||||
masm.canonicalizeDouble(ReturnFloatReg);
|
masm.canonicalizeDouble(ReturnFloatReg);
|
||||||
|
@ -5430,13 +5331,15 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore clobbered non-volatile registers of the caller.
|
||||||
masm.PopRegsInMask(NonVolatileRegs);
|
masm.PopRegsInMask(NonVolatileRegs);
|
||||||
|
|
||||||
masm.ma_mov(Imm32(true), ReturnReg);
|
JS_ASSERT(masm.framePushed() == 0);
|
||||||
|
|
||||||
|
masm.move32(Imm32(true), ReturnReg);
|
||||||
masm.abiret();
|
masm.abiret();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex,
|
TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex,
|
||||||
|
@ -6029,16 +5932,9 @@ GenerateStackOverflowExit(ModuleCompiler &m, Label *throwLabel)
|
||||||
LoadAsmJSActivationIntoRegister(masm, eax);
|
LoadAsmJSActivationIntoRegister(masm, eax);
|
||||||
LoadJSContextFromActivation(masm, eax, eax);
|
LoadJSContextFromActivation(masm, eax, eax);
|
||||||
masm.storePtr(eax, Address(StackPointer, 0));
|
masm.storePtr(eax, Address(StackPointer, 0));
|
||||||
#elif defined(JS_CPU_X64)
|
|
||||||
LoadAsmJSActivationIntoRegister(masm, IntArgReg0);
|
|
||||||
LoadJSContextFromActivation(masm, IntArgReg0, IntArgReg0);
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// on ARM, we should always be aligned, just do the context manipulation
|
|
||||||
// and make the call.
|
|
||||||
LoadAsmJSActivationIntoRegister(masm, IntArgReg0);
|
LoadAsmJSActivationIntoRegister(masm, IntArgReg0);
|
||||||
LoadJSContextFromActivation(masm, IntArgReg0, IntArgReg0);
|
LoadJSContextFromActivation(masm, IntArgReg0, IntArgReg0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
void (*pf)(JSContext*) = js_ReportOverRecursed;
|
void (*pf)(JSContext*) = js_ReportOverRecursed;
|
||||||
masm.call(ImmWord(JS_FUNC_TO_DATA_PTR(void*, pf)));
|
masm.call(ImmWord(JS_FUNC_TO_DATA_PTR(void*, pf)));
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
#ifndef jit_AsmJS_h
|
#ifndef jit_AsmJS_h
|
||||||
#define jit_AsmJS_h
|
#define jit_AsmJS_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "js/TypeDecls.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
|
|
@ -362,13 +362,8 @@ CallAsmJS(JSContext *cx, unsigned argc, Value *vp)
|
||||||
JitActivation jitActivation(cx, /* firstFrameIsConstructing = */ false, /* active */ false);
|
JitActivation jitActivation(cx, /* firstFrameIsConstructing = */ false, /* active */ false);
|
||||||
|
|
||||||
// Call the per-exported-function trampoline created by GenerateEntry.
|
// Call the per-exported-function trampoline created by GenerateEntry.
|
||||||
#ifdef JS_CPU_ARM
|
|
||||||
if (!module.entryTrampoline(func)(coercedArgs.begin(), module.globalData()))
|
if (!module.entryTrampoline(func)(coercedArgs.begin(), module.globalData()))
|
||||||
return false;
|
return false;
|
||||||
#else
|
|
||||||
if (!module.entryTrampoline(func)(coercedArgs.begin()))
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (func.returnType()) {
|
switch (func.returnType()) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#ifndef jit_AsmJSLink_h
|
#ifndef jit_AsmJSLink_h
|
||||||
#define jit_AsmJSLink_h
|
#define jit_AsmJSLink_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
|
|
@ -183,11 +183,7 @@ class AsmJSModule
|
||||||
ionCodeOffset_ = off;
|
ionCodeOffset_ = off;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#ifdef JS_CPU_ARM
|
|
||||||
typedef int32_t (*CodePtr)(uint64_t *args, uint8_t *global);
|
typedef int32_t (*CodePtr)(uint64_t *args, uint8_t *global);
|
||||||
#else
|
|
||||||
typedef int32_t (*CodePtr)(uint64_t *args);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef Vector<AsmJSCoercion, 0, SystemAllocPolicy> ArgCoercionVector;
|
typedef Vector<AsmJSCoercion, 0, SystemAllocPolicy> ArgCoercionVector;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
#include "js/RootingAPI.h"
|
#include "js/RootingAPI.h"
|
||||||
|
|
||||||
|
|
|
@ -1786,6 +1786,9 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
|
||||||
if (!emitCallToUncompiledScriptPar(call, calleereg))
|
if (!emitCallToUncompiledScriptPar(call, calleereg))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
masm.bind(&end);
|
masm.bind(&end);
|
||||||
|
@ -1911,6 +1914,9 @@ CodeGenerator::visitCallKnown(LCallKnown *call)
|
||||||
if (!emitCallToUncompiledScriptPar(call, calleereg))
|
if (!emitCallToUncompiledScriptPar(call, calleereg))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
masm.bind(&end);
|
masm.bind(&end);
|
||||||
|
@ -4800,7 +4806,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool)
|
||||||
masm.jump(ool->rejoin());
|
masm.jump(ool->rejoin());
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case ParallelExecution:
|
case ParallelExecution: {
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
// If the problem is that we do not have sufficient capacity,
|
// If the problem is that we do not have sufficient capacity,
|
||||||
// try to reallocate the elements array and then branch back
|
// try to reallocate the elements array and then branch back
|
||||||
|
@ -4855,6 +4861,10 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool)
|
||||||
return false;
|
return false;
|
||||||
masm.jump(bail1->entry());
|
masm.jump(bail1->entry());
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ASSERT(false);
|
JS_ASSERT(false);
|
||||||
|
|
|
@ -30,11 +30,15 @@ CountArgSlots(JSScript *script, JSFunction *fun)
|
||||||
|
|
||||||
enum ExecutionMode {
|
enum ExecutionMode {
|
||||||
// Normal JavaScript execution
|
// Normal JavaScript execution
|
||||||
SequentialExecution = 0,
|
SequentialExecution,
|
||||||
|
|
||||||
// JavaScript code to be executed in parallel worker threads,
|
// JavaScript code to be executed in parallel worker threads,
|
||||||
// e.g. by ParallelArray
|
// e.g. by ParallelArray
|
||||||
ParallelExecution
|
ParallelExecution,
|
||||||
|
|
||||||
|
// MIR analysis performed when invoking 'new' on a script, to determine
|
||||||
|
// definite properties
|
||||||
|
DefinitePropertiesAnalysis
|
||||||
};
|
};
|
||||||
|
|
||||||
// Not as part of the enum so we don't get warnings about unhandled enum
|
// Not as part of the enum so we don't get warnings about unhandled enum
|
||||||
|
|
|
@ -22,6 +22,7 @@ HasIonScript(JSScript *script, ExecutionMode cmode)
|
||||||
switch (cmode) {
|
switch (cmode) {
|
||||||
case SequentialExecution: return script->hasIonScript();
|
case SequentialExecution: return script->hasIonScript();
|
||||||
case ParallelExecution: return script->hasParallelIonScript();
|
case ParallelExecution: return script->hasParallelIonScript();
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
@ -32,6 +33,7 @@ GetIonScript(JSScript *script, ExecutionMode cmode)
|
||||||
switch (cmode) {
|
switch (cmode) {
|
||||||
case SequentialExecution: return script->maybeIonScript();
|
case SequentialExecution: return script->maybeIonScript();
|
||||||
case ParallelExecution: return script->maybeParallelIonScript();
|
case ParallelExecution: return script->maybeParallelIonScript();
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
@ -42,6 +44,7 @@ SetIonScript(JSScript *script, ExecutionMode cmode, IonScript *ionScript)
|
||||||
switch (cmode) {
|
switch (cmode) {
|
||||||
case SequentialExecution: script->setIonScript(ionScript); return;
|
case SequentialExecution: script->setIonScript(ionScript); return;
|
||||||
case ParallelExecution: script->setParallelIonScript(ionScript); return;
|
case ParallelExecution: script->setParallelIonScript(ionScript); return;
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
@ -52,6 +55,7 @@ OffsetOfIonInJSScript(ExecutionMode cmode)
|
||||||
switch (cmode) {
|
switch (cmode) {
|
||||||
case SequentialExecution: return JSScript::offsetOfIonScript();
|
case SequentialExecution: return JSScript::offsetOfIonScript();
|
||||||
case ParallelExecution: return JSScript::offsetOfParallelIonScript();
|
case ParallelExecution: return JSScript::offsetOfParallelIonScript();
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
@ -62,6 +66,8 @@ CanIonCompile(JSScript *script, ExecutionMode cmode)
|
||||||
switch (cmode) {
|
switch (cmode) {
|
||||||
case SequentialExecution: return script->canIonCompile();
|
case SequentialExecution: return script->canIonCompile();
|
||||||
case ParallelExecution: return script->canParallelIonCompile();
|
case ParallelExecution: return script->canParallelIonCompile();
|
||||||
|
case DefinitePropertiesAnalysis: return true;
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
return false;
|
return false;
|
||||||
|
@ -79,6 +85,7 @@ CompilingOffThread(JSScript *script, ExecutionMode cmode)
|
||||||
switch (cmode) {
|
switch (cmode) {
|
||||||
case SequentialExecution: return script->isIonCompilingOffThread();
|
case SequentialExecution: return script->isIonCompilingOffThread();
|
||||||
case ParallelExecution: return script->isParallelIonCompilingOffThread();
|
case ParallelExecution: return script->isParallelIonCompilingOffThread();
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
@ -89,6 +96,7 @@ CompilingOffThread(HandleScript script, ExecutionMode cmode)
|
||||||
switch (cmode) {
|
switch (cmode) {
|
||||||
case SequentialExecution: return script->isIonCompilingOffThread();
|
case SequentialExecution: return script->isIonCompilingOffThread();
|
||||||
case ParallelExecution: return script->isParallelIonCompilingOffThread();
|
case ParallelExecution: return script->isParallelIonCompilingOffThread();
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
@ -99,6 +107,7 @@ CompilerOutputKind(ExecutionMode cmode)
|
||||||
switch (cmode) {
|
switch (cmode) {
|
||||||
case SequentialExecution: return types::CompilerOutput::Ion;
|
case SequentialExecution: return types::CompilerOutput::Ion;
|
||||||
case ParallelExecution: return types::CompilerOutput::ParallelIon;
|
case ParallelExecution: return types::CompilerOutput::ParallelIon;
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2451,6 +2451,8 @@ jit::Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetU
|
||||||
if (!scripts.append(script->parallelIonScript()->recompileInfo()))
|
if (!scripts.append(script->parallelIonScript()->recompileInfo()))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
Invalidate(cx, scripts, resetUses);
|
Invalidate(cx, scripts, resetUses);
|
||||||
|
@ -2542,6 +2544,9 @@ jit::ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode)
|
||||||
|
|
||||||
script->setParallelIonScript(ION_DISABLED_SCRIPT);
|
script->setParallelIonScript(ION_DISABLED_SCRIPT);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||||
|
|
|
@ -8,14 +8,20 @@
|
||||||
|
|
||||||
#include "jsanalyze.h"
|
#include "jsanalyze.h"
|
||||||
|
|
||||||
|
#include "jit/BaselineInspector.h"
|
||||||
#include "jit/Ion.h"
|
#include "jit/Ion.h"
|
||||||
#include "jit/IonBuilder.h"
|
#include "jit/IonBuilder.h"
|
||||||
#include "jit/LIR.h"
|
#include "jit/LIR.h"
|
||||||
#include "jit/MIRGraph.h"
|
#include "jit/MIRGraph.h"
|
||||||
|
|
||||||
|
#include "jsinferinlines.h"
|
||||||
|
#include "jsscriptinlines.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::jit;
|
using namespace js::jit;
|
||||||
|
|
||||||
|
using mozilla::DebugOnly;
|
||||||
|
|
||||||
// A critical edge is an edge which is neither its successor's only predecessor
|
// A critical edge is an edge which is neither its successor's only predecessor
|
||||||
// nor its predecessor's only successor. Critical edges must be split to
|
// nor its predecessor's only successor. Critical edges must be split to
|
||||||
// prevent copy-insertion and code motion from affecting other edges.
|
// prevent copy-insertion and code motion from affecting other edges.
|
||||||
|
@ -1605,3 +1611,263 @@ LinearSum::print(Sprinter &sp) const
|
||||||
else if (constant_ < 0)
|
else if (constant_ < 0)
|
||||||
sp.printf("%d", constant_);
|
sp.printf("%d", constant_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
AnalyzePoppedThis(JSContext *cx, types::TypeObject *type,
|
||||||
|
MDefinition *thisValue, MInstruction *ins, bool definitelyExecuted,
|
||||||
|
HandleObject baseobj,
|
||||||
|
Vector<types::TypeNewScript::Initializer> *initializerList,
|
||||||
|
Vector<jsid> *accessedProperties,
|
||||||
|
bool *phandled)
|
||||||
|
{
|
||||||
|
// Determine the effect that a use of the |this| value when calling |new|
|
||||||
|
// on a script has on the properties definitely held by the new object.
|
||||||
|
|
||||||
|
if (ins->isCallSetProperty()) {
|
||||||
|
MCallSetProperty *setprop = ins->toCallSetProperty();
|
||||||
|
|
||||||
|
if (setprop->obj() != thisValue)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Don't use GetAtomId here, we need to watch for SETPROP on
|
||||||
|
// integer properties and bail out. We can't mark the aggregate
|
||||||
|
// JSID_VOID type property as being in a definite slot.
|
||||||
|
RootedId id(cx, NameToId(setprop->name()));
|
||||||
|
if (types::IdToTypeId(id) != id ||
|
||||||
|
id == NameToId(cx->names().classPrototype) ||
|
||||||
|
id == NameToId(cx->names().proto) ||
|
||||||
|
id == NameToId(cx->names().constructor))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore assignments to properties that were already written to.
|
||||||
|
if (baseobj->nativeLookup(cx, id)) {
|
||||||
|
*phandled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't add definite properties for properties that were already
|
||||||
|
// read in the constructor.
|
||||||
|
for (size_t i = 0; i < accessedProperties->length(); i++) {
|
||||||
|
if ((*accessedProperties)[i] == id)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseobj->slotSpan() >= (types::TYPE_FLAG_DEFINITE_MASK >> types::TYPE_FLAG_DEFINITE_SHIFT)) {
|
||||||
|
// Maximum number of definite properties added.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assignments to new properties must always execute.
|
||||||
|
if (!definitelyExecuted)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!types::AddClearDefiniteGetterSetterForPrototypeChain(cx, type, id)) {
|
||||||
|
// The prototype chain already contains a getter/setter for this
|
||||||
|
// property, or type information is too imprecise.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugOnly<unsigned> slotSpan = baseobj->slotSpan();
|
||||||
|
RootedValue value(cx, UndefinedValue());
|
||||||
|
if (!DefineNativeProperty(cx, baseobj, id, value, NULL, NULL,
|
||||||
|
JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
JS_ASSERT(baseobj->slotSpan() != slotSpan);
|
||||||
|
JS_ASSERT(!baseobj->inDictionaryMode());
|
||||||
|
|
||||||
|
Vector<MResumePoint *> callerResumePoints(cx);
|
||||||
|
MBasicBlock *block = ins->block();
|
||||||
|
for (MResumePoint *rp = block->callerResumePoint();
|
||||||
|
rp;
|
||||||
|
block = rp->block(), rp = block->callerResumePoint())
|
||||||
|
{
|
||||||
|
JSScript *script = rp->block()->info().script();
|
||||||
|
types::AddClearDefiniteFunctionUsesInScript(cx, type, script, block->info().script());
|
||||||
|
if (!callerResumePoints.append(rp))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = callerResumePoints.length() - 1; i >= 0; i--) {
|
||||||
|
MResumePoint *rp = callerResumePoints[i];
|
||||||
|
JSScript *script = rp->block()->info().script();
|
||||||
|
types::TypeNewScript::Initializer entry(types::TypeNewScript::Initializer::SETPROP_FRAME,
|
||||||
|
rp->pc() - script->code);
|
||||||
|
if (!initializerList->append(entry))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSScript *script = ins->block()->info().script();
|
||||||
|
types::TypeNewScript::Initializer entry(types::TypeNewScript::Initializer::SETPROP,
|
||||||
|
setprop->resumePoint()->pc() - script->code);
|
||||||
|
if (!initializerList->append(entry))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*phandled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ins->isCallGetProperty()) {
|
||||||
|
MCallGetProperty *get = ins->toCallGetProperty();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Properties can be read from the 'this' object if the following hold:
|
||||||
|
*
|
||||||
|
* - The read is not on a getter along the prototype chain, which
|
||||||
|
* could cause 'this' to escape.
|
||||||
|
*
|
||||||
|
* - The accessed property is either already a definite property or
|
||||||
|
* is not later added as one. Since the definite properties are
|
||||||
|
* added to the object at the point of its creation, reading a
|
||||||
|
* definite property before it is assigned could incorrectly hit.
|
||||||
|
*/
|
||||||
|
RootedId id(cx, NameToId(get->name()));
|
||||||
|
if (types::IdToTypeId(id) != id)
|
||||||
|
return true;
|
||||||
|
if (!baseobj->nativeLookup(cx, id) && !accessedProperties->append(id.get()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!types::AddClearDefiniteGetterSetterForPrototypeChain(cx, type, id)) {
|
||||||
|
// The |this| value can escape if any property reads it does go
|
||||||
|
// through a getter.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*phandled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ins->isPostWriteBarrier()) {
|
||||||
|
*phandled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
CmpInstructions(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return (*static_cast<MInstruction * const *>(a))->id() -
|
||||||
|
(*static_cast<MInstruction * const *>(b))->id();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
jit::AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
|
||||||
|
types::TypeObject *type, HandleObject baseobj,
|
||||||
|
Vector<types::TypeNewScript::Initializer> *initializerList)
|
||||||
|
{
|
||||||
|
// When invoking 'new' on the specified script, try to find some properties
|
||||||
|
// which will definitely be added to the created object before it has a
|
||||||
|
// chance to escape and be accessed elsewhere.
|
||||||
|
|
||||||
|
if (!fun->nonLazyScript()->compileAndGo)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!fun->nonLazyScript()->ensureHasTypes(cx))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
types::TypeScript::SetThis(cx, fun->nonLazyScript(), types::Type::ObjectType(type));
|
||||||
|
|
||||||
|
Vector<jsid> accessedProperties(cx);
|
||||||
|
|
||||||
|
LifoAlloc alloc(JSCompartment::ANALYSIS_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
|
||||||
|
|
||||||
|
TempAllocator temp(&alloc);
|
||||||
|
IonContext ictx(cx, &temp);
|
||||||
|
|
||||||
|
types::AutoEnterAnalysis enter(cx);
|
||||||
|
|
||||||
|
if (!fun->nonLazyScript()->ensureRanAnalysis(cx))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MIRGraph graph(&temp);
|
||||||
|
CompileInfo info(fun->nonLazyScript(), fun,
|
||||||
|
/* osrPc = */ NULL, /* constructing = */ false,
|
||||||
|
DefinitePropertiesAnalysis);
|
||||||
|
|
||||||
|
AutoTempAllocatorRooter root(cx, &temp);
|
||||||
|
|
||||||
|
BaselineInspector inspector(cx, fun->nonLazyScript());
|
||||||
|
IonBuilder builder(cx, &temp, &graph, &inspector, &info, /* baselineFrame = */ NULL);
|
||||||
|
|
||||||
|
if (!builder.build()) {
|
||||||
|
if (builder.abortReason() == AbortReason_Alloc)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SplitCriticalEdges(graph))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!RenumberBlocks(graph))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!BuildDominatorTree(graph))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!EliminatePhis(&builder, graph, AggressiveObservability))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MDefinition *thisValue = graph.begin()->getSlot(info.thisSlot());
|
||||||
|
|
||||||
|
// Get a list of instructions using the |this| value in the order they
|
||||||
|
// appear in the graph.
|
||||||
|
Vector<MInstruction *> instructions(cx);
|
||||||
|
|
||||||
|
Vector<MDefinition *> useWorklist(cx);
|
||||||
|
for (MUseDefIterator uses(thisValue); uses; uses++) {
|
||||||
|
MDefinition *use = uses.def();
|
||||||
|
|
||||||
|
// Don't track |this| through assignments to phis.
|
||||||
|
if (!use->isInstruction())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!instructions.append(use->toInstruction()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the instructions to visit in increasing order.
|
||||||
|
qsort(instructions.begin(), instructions.length(),
|
||||||
|
sizeof(MInstruction *), CmpInstructions);
|
||||||
|
|
||||||
|
// Find all exit blocks in the graph.
|
||||||
|
Vector<MBasicBlock *> exitBlocks(cx);
|
||||||
|
for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++) {
|
||||||
|
if (!block->numSuccessors() && !exitBlocks.append(*block))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < instructions.length(); i++) {
|
||||||
|
MInstruction *ins = instructions[i];
|
||||||
|
|
||||||
|
// Track whether the use of |this| is in unconditional code, i.e.
|
||||||
|
// the block dominates all graph exits.
|
||||||
|
bool definitelyExecuted = true;
|
||||||
|
for (size_t i = 0; i < exitBlocks.length(); i++) {
|
||||||
|
for (MBasicBlock *exit = exitBlocks[i];
|
||||||
|
exit != ins->block();
|
||||||
|
exit = exit->immediateDominator())
|
||||||
|
{
|
||||||
|
if (exit == exit->immediateDominator()) {
|
||||||
|
definitelyExecuted = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
if (!AnalyzePoppedThis(cx, type, thisValue, ins, definitelyExecuted,
|
||||||
|
baseobj, initializerList, &accessedProperties, &handled))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!handled)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -124,6 +124,11 @@ class LinearSum
|
||||||
int32_t constant_;
|
int32_t constant_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
|
||||||
|
types::TypeObject *type, HandleObject baseobj,
|
||||||
|
Vector<types::TypeNewScript::Initializer> *initializerList);
|
||||||
|
|
||||||
} // namespace jit
|
} // namespace jit
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
|
|
@ -3929,16 +3929,21 @@ IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caller must be... somewhat hot.
|
// Caller must be... somewhat hot. Ignore use counts when inlining for
|
||||||
|
// the definite properties analysis, as the caller has not run yet.
|
||||||
uint32_t callerUses = script()->getUseCount();
|
uint32_t callerUses = script()->getUseCount();
|
||||||
if (callerUses < js_IonOptions.usesBeforeInlining()) {
|
if (callerUses < js_IonOptions.usesBeforeInlining() &&
|
||||||
|
info().executionMode() != DefinitePropertiesAnalysis)
|
||||||
|
{
|
||||||
IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: caller is insufficiently hot.",
|
IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: caller is insufficiently hot.",
|
||||||
targetScript->filename(), targetScript->lineno);
|
targetScript->filename(), targetScript->lineno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callee must be hot relative to the caller.
|
// Callee must be hot relative to the caller.
|
||||||
if (targetScript->getUseCount() * js_IonOptions.inlineUseCountRatio < callerUses) {
|
if (targetScript->getUseCount() * js_IonOptions.inlineUseCountRatio < callerUses &&
|
||||||
|
info().executionMode() != DefinitePropertiesAnalysis)
|
||||||
|
{
|
||||||
IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: callee is not hot.",
|
IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: callee is not hot.",
|
||||||
targetScript->filename(), targetScript->lineno);
|
targetScript->filename(), targetScript->lineno);
|
||||||
return false;
|
return false;
|
||||||
|
@ -4803,7 +4808,7 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
|
||||||
|
|
||||||
// When this script isn't inlined, use MApplyArgs,
|
// When this script isn't inlined, use MApplyArgs,
|
||||||
// to copy the arguments from the stack and call the function
|
// to copy the arguments from the stack and call the function
|
||||||
if (inliningDepth_ == 0) {
|
if (inliningDepth_ == 0 && info().executionMode() != DefinitePropertiesAnalysis) {
|
||||||
|
|
||||||
// Vp
|
// Vp
|
||||||
MPassArg *passVp = current->pop()->toPassArg();
|
MPassArg *passVp = current->pop()->toPassArg();
|
||||||
|
@ -4841,7 +4846,9 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
|
||||||
|
|
||||||
// When inlining we have the arguments the function gets called with
|
// When inlining we have the arguments the function gets called with
|
||||||
// and can optimize even more, by just calling the functions with the args.
|
// and can optimize even more, by just calling the functions with the args.
|
||||||
JS_ASSERT(inliningDepth_ > 0);
|
// We also try this path when doing the definite properties analysis, as we
|
||||||
|
// can inline the apply() target and don't care about the actual arguments
|
||||||
|
// that were passed in.
|
||||||
|
|
||||||
CallInfo callInfo(cx, false);
|
CallInfo callInfo(cx, false);
|
||||||
|
|
||||||
|
@ -4853,8 +4860,10 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
|
||||||
|
|
||||||
// Arguments
|
// Arguments
|
||||||
Vector<MDefinition *> args(cx);
|
Vector<MDefinition *> args(cx);
|
||||||
if (!args.append(inlineCallInfo_->argv().begin(), inlineCallInfo_->argv().end()))
|
if (inliningDepth_) {
|
||||||
return false;
|
if (!args.append(inlineCallInfo_->argv().begin(), inlineCallInfo_->argv().end()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
callInfo.setArgs(&args);
|
callInfo.setArgs(&args);
|
||||||
|
|
||||||
// This
|
// This
|
||||||
|
@ -5570,6 +5579,7 @@ IonBuilder::jsop_initprop(HandlePropertyName name)
|
||||||
// forkjoin.cpp for more information.
|
// forkjoin.cpp for more information.
|
||||||
switch (info().executionMode()) {
|
switch (info().executionMode()) {
|
||||||
case SequentialExecution:
|
case SequentialExecution:
|
||||||
|
case DefinitePropertiesAnalysis:
|
||||||
break;
|
break;
|
||||||
case ParallelExecution:
|
case ParallelExecution:
|
||||||
needsBarrier = false;
|
needsBarrier = false;
|
||||||
|
@ -8019,11 +8029,22 @@ IonBuilder::jsop_getprop(HandlePropertyName name)
|
||||||
if (!getPropTryArgumentsLength(&emitted) || emitted)
|
if (!getPropTryArgumentsLength(&emitted) || emitted)
|
||||||
return emitted;
|
return emitted;
|
||||||
|
|
||||||
|
bool barrier = PropertyReadNeedsTypeBarrier(cx, current->peek(-1), name, types);
|
||||||
|
|
||||||
// Try to hardcode known constants.
|
// Try to hardcode known constants.
|
||||||
if (!getPropTryConstant(&emitted, id, types) || emitted)
|
if (!getPropTryConstant(&emitted, id, types) || emitted)
|
||||||
return emitted;
|
return emitted;
|
||||||
|
|
||||||
bool barrier = PropertyReadNeedsTypeBarrier(cx, current->peek(-1), name, types);
|
// Except when loading constants above, always use a call if we are doing
|
||||||
|
// the definite properties analysis and not actually emitting code, to
|
||||||
|
// simplify later analysis.
|
||||||
|
if (info().executionMode() == DefinitePropertiesAnalysis) {
|
||||||
|
MDefinition *obj = current->pop();
|
||||||
|
MCallGetProperty *call = MCallGetProperty::New(obj, name);
|
||||||
|
current->add(call);
|
||||||
|
current->push(call);
|
||||||
|
return resumeAfter(call);
|
||||||
|
}
|
||||||
|
|
||||||
// Try to emit loads from definite slots.
|
// Try to emit loads from definite slots.
|
||||||
if (!getPropTryDefiniteSlot(&emitted, name, barrier, types) || emitted)
|
if (!getPropTryDefiniteSlot(&emitted, name, barrier, types) || emitted)
|
||||||
|
@ -8370,6 +8391,15 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
|
||||||
RootedId id(cx, NameToId(name));
|
RootedId id(cx, NameToId(name));
|
||||||
bool emitted = false;
|
bool emitted = false;
|
||||||
|
|
||||||
|
// Always use a call if we are doing the definite properties analysis and
|
||||||
|
// not actually emitting code, to simplify later analysis.
|
||||||
|
if (info().executionMode() == DefinitePropertiesAnalysis) {
|
||||||
|
MInstruction *ins = MCallSetProperty::New(obj, value, name, script()->strict);
|
||||||
|
current->add(ins);
|
||||||
|
current->push(value);
|
||||||
|
return resumeAfter(ins);
|
||||||
|
}
|
||||||
|
|
||||||
// Add post barrier if needed.
|
// Add post barrier if needed.
|
||||||
if (NeedsPostBarrier(info(), value))
|
if (NeedsPostBarrier(info(), value))
|
||||||
current->add(MPostWriteBarrier::New(obj, value));
|
current->add(MPostWriteBarrier::New(obj, value));
|
||||||
|
@ -8759,6 +8789,15 @@ IonBuilder::jsop_this()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we are doing a definite properties analysis, we don't yet know the
|
||||||
|
// |this| type as its type object is being created right now. Instead of
|
||||||
|
// bailing out just push the |this| slot, as this code won't actually
|
||||||
|
// execute and it does not matter whether |this| is primitive.
|
||||||
|
if (info().executionMode() == DefinitePropertiesAnalysis) {
|
||||||
|
current->pushSlot(info().thisSlot());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return abort("JSOP_THIS hard case not yet handled");
|
return abort("JSOP_THIS hard case not yet handled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1102,7 +1102,7 @@ IonBuilder::inlineForceSequentialOrInParallelSection(CallInfo &callInfo)
|
||||||
// access the "in warmup" flag of the runtime.
|
// access the "in warmup" flag of the runtime.
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
case ParallelExecution:
|
case ParallelExecution: {
|
||||||
// During Parallel Exec, we always force sequential, so
|
// During Parallel Exec, we always force sequential, so
|
||||||
// replace with true. This permits UCE to eliminate the
|
// replace with true. This permits UCE to eliminate the
|
||||||
// entire path as dead, which is important.
|
// entire path as dead, which is important.
|
||||||
|
@ -1111,6 +1111,9 @@ IonBuilder::inlineForceSequentialOrInParallelSection(CallInfo &callInfo)
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSUME_UNREACHABLE("Invalid execution mode");
|
MOZ_ASSUME_UNREACHABLE("Invalid execution mode");
|
||||||
|
@ -1285,6 +1288,7 @@ IonBuilder::inlineNewDenseArray(CallInfo &callInfo)
|
||||||
return inlineNewDenseArrayForSequentialExecution(callInfo);
|
return inlineNewDenseArrayForSequentialExecution(callInfo);
|
||||||
case ParallelExecution:
|
case ParallelExecution:
|
||||||
return inlineNewDenseArrayForParallelExecution(callInfo);
|
return inlineNewDenseArrayForParallelExecution(callInfo);
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSUME_UNREACHABLE("unknown ExecutionMode");
|
MOZ_ASSUME_UNREACHABLE("unknown ExecutionMode");
|
||||||
|
|
|
@ -147,7 +147,7 @@ PerfSpewer::writeProfile(JSScript *script,
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
fprintf(fp_,
|
fprintf(fp_,
|
||||||
"%lx %lx %s:%d: Func%02d\n",
|
"%lx %lx %s:%d: Func%02d\n",
|
||||||
reinterpret_cast<unsigned long>(code->raw()),
|
reinterpret_cast<uintptr_t>(code->raw()),
|
||||||
size,
|
size,
|
||||||
script->filename(),
|
script->filename(),
|
||||||
script->lineno,
|
script->lineno,
|
||||||
|
|
|
@ -1787,88 +1787,6 @@ ScriptAnalysis::needsArgsObj(JSContext *cx)
|
||||||
return needsArgsObj(cx, seen, SSAValue::PushedValue(pcOff, 0));
|
return needsArgsObj(cx, seen, SSAValue::PushedValue(pcOff, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
CrossSSAValue
|
|
||||||
CrossScriptSSA::foldValue(const CrossSSAValue &cv)
|
|
||||||
{
|
|
||||||
const Frame &frame = getFrame(cv.frame);
|
|
||||||
const SSAValue &v = cv.v;
|
|
||||||
|
|
||||||
JSScript *parentScript = NULL;
|
|
||||||
ScriptAnalysis *parentAnalysis = NULL;
|
|
||||||
if (frame.parent != INVALID_FRAME) {
|
|
||||||
parentScript = getFrame(frame.parent).script;
|
|
||||||
parentAnalysis = parentScript->analysis();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v.kind() == SSAValue::VAR && v.varInitial() && parentScript) {
|
|
||||||
uint32_t slot = v.varSlot();
|
|
||||||
if (slot >= ArgSlot(0) && slot < LocalSlot(frame.script, 0)) {
|
|
||||||
uint32_t argc = GET_ARGC(frame.parentpc);
|
|
||||||
SSAValue argv = parentAnalysis->poppedValue(frame.parentpc, argc - 1 - (slot - ArgSlot(0)));
|
|
||||||
return foldValue(CrossSSAValue(frame.parent, argv));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v.kind() == SSAValue::PUSHED) {
|
|
||||||
jsbytecode *pc = frame.script->code + v.pushedOffset();
|
|
||||||
|
|
||||||
switch (JSOp(*pc)) {
|
|
||||||
case JSOP_THIS:
|
|
||||||
if (parentScript) {
|
|
||||||
uint32_t argc = GET_ARGC(frame.parentpc);
|
|
||||||
SSAValue thisv = parentAnalysis->poppedValue(frame.parentpc, argc);
|
|
||||||
return foldValue(CrossSSAValue(frame.parent, thisv));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case JSOP_CALL: {
|
|
||||||
/*
|
|
||||||
* If there is a single inline callee with a single return site,
|
|
||||||
* propagate back to that.
|
|
||||||
*/
|
|
||||||
JSScript *callee = NULL;
|
|
||||||
uint32_t calleeFrame = INVALID_FRAME;
|
|
||||||
for (unsigned i = 0; i < numFrames(); i++) {
|
|
||||||
if (iterFrame(i).parent == cv.frame && iterFrame(i).parentpc == pc) {
|
|
||||||
if (callee)
|
|
||||||
return cv; /* Multiple callees */
|
|
||||||
callee = iterFrame(i).script;
|
|
||||||
calleeFrame = iterFrame(i).index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (callee && callee->analysis()->numReturnSites() == 1) {
|
|
||||||
ScriptAnalysis *analysis = callee->analysis();
|
|
||||||
uint32_t offset = 0;
|
|
||||||
while (offset < callee->length) {
|
|
||||||
jsbytecode *pc = callee->code + offset;
|
|
||||||
if (analysis->maybeCode(pc) && JSOp(*pc) == JSOP_RETURN)
|
|
||||||
return foldValue(CrossSSAValue(calleeFrame, analysis->poppedValue(pc, 0)));
|
|
||||||
offset += GetBytecodeLength(pc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case JSOP_TOID: {
|
|
||||||
/*
|
|
||||||
* TOID acts as identity for integers, so to get better precision
|
|
||||||
* we should propagate its popped values forward if it acted as
|
|
||||||
* identity.
|
|
||||||
*/
|
|
||||||
ScriptAnalysis *analysis = frame.script->analysis();
|
|
||||||
SSAValue toidv = analysis->poppedValue(pc, 0);
|
|
||||||
if (analysis->getValueTypes(toidv)->getKnownTypeTag() == JSVAL_TYPE_INT32)
|
|
||||||
return foldValue(CrossSSAValue(cv.frame, toidv));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cv;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -78,15 +78,6 @@ class Bytecode
|
||||||
/* Whether this is a catch/finally entry point. */
|
/* Whether this is a catch/finally entry point. */
|
||||||
bool exceptionEntry : 1;
|
bool exceptionEntry : 1;
|
||||||
|
|
||||||
/*
|
|
||||||
* Side effects of this bytecode were not determined by type inference.
|
|
||||||
* Either a property set with unknown lvalue, or call with unknown callee.
|
|
||||||
*/
|
|
||||||
bool monitoredTypes : 1;
|
|
||||||
|
|
||||||
/* Call whose result should be monitored. */
|
|
||||||
bool monitoredTypesReturn : 1;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dynamically observed state about the execution of this opcode. These are
|
* Dynamically observed state about the execution of this opcode. These are
|
||||||
* hints about the script for use during compilation.
|
* hints about the script for use during compilation.
|
||||||
|
@ -129,14 +120,6 @@ class Bytecode
|
||||||
*/
|
*/
|
||||||
Vector<SlotValue> *pendingValues;
|
Vector<SlotValue> *pendingValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* --------- Type inference --------- */
|
|
||||||
|
|
||||||
/* Types for all values pushed by this bytecode. */
|
|
||||||
types::StackTypeSet *pushedTypes;
|
|
||||||
|
|
||||||
/* Any type barriers in place at this bytecode. */
|
|
||||||
types::TypeBarrier *typeBarriers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -471,7 +454,6 @@ class SSAValue
|
||||||
uint32_t phiSlot() const;
|
uint32_t phiSlot() const;
|
||||||
uint32_t phiLength() const;
|
uint32_t phiLength() const;
|
||||||
const SSAValue &phiValue(uint32_t i) const;
|
const SSAValue &phiValue(uint32_t i) const;
|
||||||
types::TypeSet *phiTypes() const;
|
|
||||||
|
|
||||||
/* Offset at which this phi node was created. */
|
/* Offset at which this phi node was created. */
|
||||||
uint32_t phiOffset() const {
|
uint32_t phiOffset() const {
|
||||||
|
@ -571,7 +553,6 @@ class SSAValue
|
||||||
*/
|
*/
|
||||||
struct SSAPhiNode
|
struct SSAPhiNode
|
||||||
{
|
{
|
||||||
types::StackTypeSet types;
|
|
||||||
uint32_t slot;
|
uint32_t slot;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
SSAValue *options;
|
SSAValue *options;
|
||||||
|
@ -599,13 +580,6 @@ SSAValue::phiValue(uint32_t i) const
|
||||||
return u.phi.node->options[i];
|
return u.phi.node->options[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline types::TypeSet *
|
|
||||||
SSAValue::phiTypes() const
|
|
||||||
{
|
|
||||||
JS_ASSERT(kind() == PHI);
|
|
||||||
return &u.phi.node->types;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SSAUseChain
|
class SSAUseChain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -654,7 +628,6 @@ class ScriptAnalysis
|
||||||
bool ranBytecode_;
|
bool ranBytecode_;
|
||||||
bool ranSSA_;
|
bool ranSSA_;
|
||||||
bool ranLifetimes_;
|
bool ranLifetimes_;
|
||||||
bool ranInference_;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/* Whether the compartment was in debug mode when we performed the analysis. */
|
/* Whether the compartment was in debug mode when we performed the analysis. */
|
||||||
|
@ -689,15 +662,10 @@ class ScriptAnalysis
|
||||||
bool ranBytecode() { return ranBytecode_; }
|
bool ranBytecode() { return ranBytecode_; }
|
||||||
bool ranSSA() { return ranSSA_; }
|
bool ranSSA() { return ranSSA_; }
|
||||||
bool ranLifetimes() { return ranLifetimes_; }
|
bool ranLifetimes() { return ranLifetimes_; }
|
||||||
bool ranInference() { return ranInference_; }
|
|
||||||
|
|
||||||
void analyzeBytecode(JSContext *cx);
|
void analyzeBytecode(JSContext *cx);
|
||||||
void analyzeSSA(JSContext *cx);
|
void analyzeSSA(JSContext *cx);
|
||||||
void analyzeLifetimes(JSContext *cx);
|
void analyzeLifetimes(JSContext *cx);
|
||||||
void analyzeTypes(JSContext *cx);
|
|
||||||
|
|
||||||
/* Analyze the effect of invoking 'new' on script. */
|
|
||||||
void analyzeTypesNew(JSContext *cx);
|
|
||||||
|
|
||||||
bool OOM() const { return outOfMemory; }
|
bool OOM() const { return outOfMemory; }
|
||||||
bool failed() const { return hadFailure; }
|
bool failed() const { return hadFailure; }
|
||||||
|
@ -760,45 +728,6 @@ class ScriptAnalysis
|
||||||
}
|
}
|
||||||
const SlotValue *newValues(const jsbytecode *pc) { return newValues(pc - script_->code); }
|
const SlotValue *newValues(const jsbytecode *pc) { return newValues(pc - script_->code); }
|
||||||
|
|
||||||
inline types::StackTypeSet *pushedTypes(uint32_t offset, uint32_t which = 0);
|
|
||||||
inline types::StackTypeSet *pushedTypes(const jsbytecode *pc, uint32_t which);
|
|
||||||
|
|
||||||
bool hasPushedTypes(const jsbytecode *pc) { return getCode(pc).pushedTypes != NULL; }
|
|
||||||
|
|
||||||
types::TypeBarrier *typeBarriers(JSContext *cx, uint32_t offset) {
|
|
||||||
if (getCode(offset).typeBarriers)
|
|
||||||
pruneTypeBarriers(cx, offset);
|
|
||||||
return getCode(offset).typeBarriers;
|
|
||||||
}
|
|
||||||
types::TypeBarrier *typeBarriers(JSContext *cx, const jsbytecode *pc) {
|
|
||||||
return typeBarriers(cx, pc - script_->code);
|
|
||||||
}
|
|
||||||
void addTypeBarrier(JSContext *cx, const jsbytecode *pc,
|
|
||||||
types::TypeSet *target, types::Type type);
|
|
||||||
void addSingletonTypeBarrier(JSContext *cx, const jsbytecode *pc,
|
|
||||||
types::TypeSet *target,
|
|
||||||
HandleObject singleton, HandleId singletonId);
|
|
||||||
|
|
||||||
/* Remove obsolete type barriers at the given offset. */
|
|
||||||
void pruneTypeBarriers(JSContext *cx, uint32_t offset);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove still-active type barriers at the given offset. If 'all' is set,
|
|
||||||
* then all barriers are removed, otherwise only those deemed excessive
|
|
||||||
* are removed.
|
|
||||||
*/
|
|
||||||
void breakTypeBarriers(JSContext *cx, uint32_t offset, bool all);
|
|
||||||
|
|
||||||
/* Break all type barriers used in computing v. */
|
|
||||||
void breakTypeBarriersSSA(JSContext *cx, const SSAValue &v);
|
|
||||||
|
|
||||||
inline void addPushedType(JSContext *cx, uint32_t offset, uint32_t which, types::Type type);
|
|
||||||
|
|
||||||
inline types::StackTypeSet *getValueTypes(const SSAValue &v);
|
|
||||||
|
|
||||||
inline types::StackTypeSet *poppedTypes(uint32_t offset, uint32_t which);
|
|
||||||
inline types::StackTypeSet *poppedTypes(const jsbytecode *pc, uint32_t which);
|
|
||||||
|
|
||||||
bool trackUseChain(const SSAValue &v) {
|
bool trackUseChain(const SSAValue &v) {
|
||||||
JS_ASSERT_IF(v.kind() == SSAValue::VAR, trackSlot(v.varSlot()));
|
JS_ASSERT_IF(v.kind() == SSAValue::VAR, trackSlot(v.varSlot()));
|
||||||
return v.kind() != SSAValue::EMPTY &&
|
return v.kind() != SSAValue::EMPTY &&
|
||||||
|
@ -912,9 +841,6 @@ class ScriptAnalysis
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Type inference helpers */
|
|
||||||
bool analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferenceState &state);
|
|
||||||
|
|
||||||
typedef Vector<SSAValue, 16> SeenVector;
|
typedef Vector<SSAValue, 16> SeenVector;
|
||||||
bool needsArgsObj(JSContext *cx, SeenVector &seen, const SSAValue &v);
|
bool needsArgsObj(JSContext *cx, SeenVector &seen, const SSAValue &v);
|
||||||
bool needsArgsObj(JSContext *cx, SeenVector &seen, SSAUseChain *use);
|
bool needsArgsObj(JSContext *cx, SeenVector &seen, SSAUseChain *use);
|
||||||
|
@ -928,84 +854,6 @@ class ScriptAnalysis
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SSA value as used by CrossScriptSSA, identifies the frame it came from. */
|
|
||||||
struct CrossSSAValue
|
|
||||||
{
|
|
||||||
unsigned frame;
|
|
||||||
SSAValue v;
|
|
||||||
CrossSSAValue(unsigned frame, const SSAValue &v) : frame(frame), v(v) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Analysis for managing SSA values from multiple call stack frames. These are
|
|
||||||
* created by the backend compiler when inlining functions, and allow for
|
|
||||||
* values to be tracked as they flow into or out of the inlined frames.
|
|
||||||
*/
|
|
||||||
class CrossScriptSSA
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static const uint32_t OUTER_FRAME = UINT32_MAX;
|
|
||||||
static const unsigned INVALID_FRAME = uint32_t(-2);
|
|
||||||
|
|
||||||
struct Frame {
|
|
||||||
uint32_t index;
|
|
||||||
JSScript *script;
|
|
||||||
uint32_t depth; /* Distance from outer frame to this frame, in sizeof(Value) */
|
|
||||||
uint32_t parent;
|
|
||||||
jsbytecode *parentpc;
|
|
||||||
|
|
||||||
Frame(uint32_t index, JSScript *script, uint32_t depth, uint32_t parent,
|
|
||||||
jsbytecode *parentpc)
|
|
||||||
: index(index), script(script), depth(depth), parent(parent), parentpc(parentpc)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
const Frame &getFrame(uint32_t index) {
|
|
||||||
if (index == OUTER_FRAME)
|
|
||||||
return outerFrame;
|
|
||||||
return inlineFrames[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned numFrames() { return 1 + inlineFrames.length(); }
|
|
||||||
const Frame &iterFrame(unsigned i) {
|
|
||||||
if (i == 0)
|
|
||||||
return outerFrame;
|
|
||||||
return inlineFrames[i - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
JSScript *outerScript() { return outerFrame.script; }
|
|
||||||
|
|
||||||
/* Total length of scripts preceding a frame. */
|
|
||||||
size_t frameLength(uint32_t index) {
|
|
||||||
if (index == OUTER_FRAME)
|
|
||||||
return 0;
|
|
||||||
size_t res = outerFrame.script->length;
|
|
||||||
for (unsigned i = 0; i < index; i++)
|
|
||||||
res += inlineFrames[i].script->length;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline types::StackTypeSet *getValueTypes(const CrossSSAValue &cv);
|
|
||||||
|
|
||||||
bool addInlineFrame(JSScript *script, uint32_t depth, uint32_t parent,
|
|
||||||
jsbytecode *parentpc)
|
|
||||||
{
|
|
||||||
uint32_t index = inlineFrames.length();
|
|
||||||
return inlineFrames.append(Frame(index, script, depth, parent, parentpc));
|
|
||||||
}
|
|
||||||
|
|
||||||
CrossScriptSSA(JSContext *cx, JSScript *outer)
|
|
||||||
: outerFrame(OUTER_FRAME, outer, 0, INVALID_FRAME, NULL), inlineFrames(cx)
|
|
||||||
{}
|
|
||||||
|
|
||||||
CrossSSAValue foldValue(const CrossSSAValue &cv);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Frame outerFrame;
|
|
||||||
Vector<Frame> inlineFrames;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void PrintBytecode(JSContext *cx, HandleScript script, jsbytecode *pc);
|
void PrintBytecode(JSContext *cx, HandleScript script, jsbytecode *pc);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,64 +29,6 @@ ScriptAnalysis::poppedValue(const jsbytecode *pc, uint32_t which)
|
||||||
return poppedValue(pc - script_->code, which);
|
return poppedValue(pc - script_->code, which);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline types::StackTypeSet *
|
|
||||||
ScriptAnalysis::pushedTypes(uint32_t offset, uint32_t which)
|
|
||||||
{
|
|
||||||
JS_ASSERT(offset < script_->length);
|
|
||||||
JS_ASSERT(which < GetDefCount(script_, offset) +
|
|
||||||
(ExtendedDef(script_->code + offset) ? 1 : 0));
|
|
||||||
types::StackTypeSet *array = getCode(offset).pushedTypes;
|
|
||||||
JS_ASSERT(array);
|
|
||||||
return array + which;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline types::StackTypeSet *
|
|
||||||
ScriptAnalysis::pushedTypes(const jsbytecode *pc, uint32_t which)
|
|
||||||
{
|
|
||||||
return pushedTypes(pc - script_->code, which);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline types::StackTypeSet *
|
|
||||||
ScriptAnalysis::getValueTypes(const SSAValue &v)
|
|
||||||
{
|
|
||||||
switch (v.kind()) {
|
|
||||||
case SSAValue::PUSHED:
|
|
||||||
return pushedTypes(v.pushedOffset(), v.pushedIndex());
|
|
||||||
case SSAValue::VAR:
|
|
||||||
JS_ASSERT(!slotEscapes(v.varSlot()));
|
|
||||||
if (v.varInitial()) {
|
|
||||||
if (v.varSlot() < LocalSlot(script_, 0))
|
|
||||||
return types::TypeScript::SlotTypes(script_, v.varSlot());
|
|
||||||
return undefinedTypeSet;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Results of intermediate assignments have the same type as
|
|
||||||
* the first type pushed by the assignment op. Note that this
|
|
||||||
* may not be the exact same value as was pushed, due to
|
|
||||||
* post-inc/dec ops.
|
|
||||||
*/
|
|
||||||
return pushedTypes(v.varOffset(), 0);
|
|
||||||
}
|
|
||||||
case SSAValue::PHI:
|
|
||||||
return &v.phiNode()->types;
|
|
||||||
default:
|
|
||||||
/* Cannot compute types for empty SSA values. */
|
|
||||||
MOZ_ASSUME_UNREACHABLE("Bad SSA value");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline types::StackTypeSet *
|
|
||||||
ScriptAnalysis::poppedTypes(uint32_t offset, uint32_t which)
|
|
||||||
{
|
|
||||||
return getValueTypes(poppedValue(offset, which));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline types::StackTypeSet *
|
|
||||||
ScriptAnalysis::poppedTypes(const jsbytecode *pc, uint32_t which)
|
|
||||||
{
|
|
||||||
return getValueTypes(poppedValue(pc, which));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline SSAUseChain *&
|
inline SSAUseChain *&
|
||||||
ScriptAnalysis::useChain(const SSAValue &v)
|
ScriptAnalysis::useChain(const SSAValue &v)
|
||||||
{
|
{
|
||||||
|
@ -107,12 +49,6 @@ ScriptAnalysis::getCallPC(jsbytecode *pc)
|
||||||
return script_->code + uses->offset;
|
return script_->code + uses->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline types::StackTypeSet *
|
|
||||||
CrossScriptSSA::getValueTypes(const CrossSSAValue &cv)
|
|
||||||
{
|
|
||||||
return getFrame(cv.frame).script->analysis()->getValueTypes(cv.v);
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace analyze */
|
} /* namespace analyze */
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,9 @@
|
||||||
#ifndef jsapi_h
|
#ifndef jsapi_h
|
||||||
#define jsapi_h
|
#define jsapi_h
|
||||||
|
|
||||||
#include "mozilla/Compiler.h"
|
|
||||||
#include "mozilla/FloatingPoint.h"
|
#include "mozilla/FloatingPoint.h"
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/RangedPtr.h"
|
#include "mozilla/RangedPtr.h"
|
||||||
#include "mozilla/TypeTraits.h"
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -24,7 +22,6 @@
|
||||||
#include "jspubtd.h"
|
#include "jspubtd.h"
|
||||||
|
|
||||||
#include "js/CallArgs.h"
|
#include "js/CallArgs.h"
|
||||||
#include "js/CallNonGenericMethod.h"
|
|
||||||
#include "js/Class.h"
|
#include "js/Class.h"
|
||||||
#include "js/HashTable.h"
|
#include "js/HashTable.h"
|
||||||
#include "js/Id.h"
|
#include "js/Id.h"
|
||||||
|
@ -1358,7 +1355,7 @@ JS_EndRequest(JSContext *cx);
|
||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
JS_IsInRequest(JSRuntime *rt);
|
JS_IsInRequest(JSRuntime *rt);
|
||||||
|
|
||||||
namespace JS {
|
namespace js {
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
IsPoisonedId(jsid iden)
|
IsPoisonedId(jsid iden)
|
||||||
|
@ -1370,15 +1367,11 @@ IsPoisonedId(jsid iden)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace JS */
|
|
||||||
|
|
||||||
namespace js {
|
|
||||||
|
|
||||||
template <> struct GCMethods<jsid>
|
template <> struct GCMethods<jsid>
|
||||||
{
|
{
|
||||||
static jsid initial() { return JSID_VOID; }
|
static jsid initial() { return JSID_VOID; }
|
||||||
static ThingRootKind kind() { return THING_ROOT_ID; }
|
static ThingRootKind kind() { return THING_ROOT_ID; }
|
||||||
static bool poisoned(jsid id) { return JS::IsPoisonedId(id); }
|
static bool poisoned(jsid id) { return IsPoisonedId(id); }
|
||||||
static bool needsPostBarrier(jsid id) { return false; }
|
static bool needsPostBarrier(jsid id) { return false; }
|
||||||
#ifdef JSGC_GENERATIONAL
|
#ifdef JSGC_GENERATIONAL
|
||||||
static void postBarrier(jsid *idp) {}
|
static void postBarrier(jsid *idp) {}
|
||||||
|
@ -4586,81 +4579,4 @@ extern JS_PUBLIC_DATA(const Handle<jsid>) JSID_EMPTYHANDLE;
|
||||||
|
|
||||||
} /* namespace JS */
|
} /* namespace JS */
|
||||||
|
|
||||||
namespace js {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Import some JS:: names into the js namespace so we can make unqualified
|
|
||||||
* references to them.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using JS::Value;
|
|
||||||
using JS::IsPoisonedValue;
|
|
||||||
using JS::NullValue;
|
|
||||||
using JS::UndefinedValue;
|
|
||||||
using JS::Int32Value;
|
|
||||||
using JS::DoubleValue;
|
|
||||||
using JS::StringValue;
|
|
||||||
using JS::BooleanValue;
|
|
||||||
using JS::ObjectValue;
|
|
||||||
using JS::MagicValue;
|
|
||||||
using JS::NumberValue;
|
|
||||||
using JS::ObjectOrNullValue;
|
|
||||||
using JS::PrivateValue;
|
|
||||||
using JS::PrivateUint32Value;
|
|
||||||
|
|
||||||
using JS::IsPoisonedPtr;
|
|
||||||
using JS::IsPoisonedId;
|
|
||||||
|
|
||||||
using JS::StableCharPtr;
|
|
||||||
using JS::TwoByteChars;
|
|
||||||
using JS::Latin1CharsZ;
|
|
||||||
|
|
||||||
using JS::AutoIdVector;
|
|
||||||
using JS::AutoValueVector;
|
|
||||||
using JS::AutoObjectVector;
|
|
||||||
using JS::AutoFunctionVector;
|
|
||||||
using JS::AutoScriptVector;
|
|
||||||
using JS::AutoIdArray;
|
|
||||||
|
|
||||||
using JS::AutoGCRooter;
|
|
||||||
using JS::AutoArrayRooter;
|
|
||||||
using JS::AutoVectorRooter;
|
|
||||||
using JS::AutoHashMapRooter;
|
|
||||||
using JS::AutoHashSetRooter;
|
|
||||||
|
|
||||||
using JS::CallArgs;
|
|
||||||
using JS::IsAcceptableThis;
|
|
||||||
using JS::NativeImpl;
|
|
||||||
using JS::CallReceiver;
|
|
||||||
using JS::CompileOptions;
|
|
||||||
using JS::CallNonGenericMethod;
|
|
||||||
|
|
||||||
using JS::Rooted;
|
|
||||||
using JS::RootedObject;
|
|
||||||
using JS::RootedFunction;
|
|
||||||
using JS::RootedScript;
|
|
||||||
using JS::RootedString;
|
|
||||||
using JS::RootedId;
|
|
||||||
using JS::RootedValue;
|
|
||||||
|
|
||||||
using JS::Handle;
|
|
||||||
using JS::HandleObject;
|
|
||||||
using JS::HandleFunction;
|
|
||||||
using JS::HandleScript;
|
|
||||||
using JS::HandleString;
|
|
||||||
using JS::HandleId;
|
|
||||||
using JS::HandleValue;
|
|
||||||
|
|
||||||
using JS::MutableHandle;
|
|
||||||
using JS::MutableHandleObject;
|
|
||||||
using JS::MutableHandleFunction;
|
|
||||||
using JS::MutableHandleScript;
|
|
||||||
using JS::MutableHandleString;
|
|
||||||
using JS::MutableHandleId;
|
|
||||||
using JS::MutableHandleValue;
|
|
||||||
|
|
||||||
using JS::Zone;
|
|
||||||
|
|
||||||
} /* namespace js */
|
|
||||||
|
|
||||||
#endif /* jsapi_h */
|
#endif /* jsapi_h */
|
||||||
|
|
|
@ -6,11 +6,13 @@
|
||||||
|
|
||||||
#ifndef jsbool_h
|
#ifndef jsbool_h
|
||||||
#define jsbool_h
|
#define jsbool_h
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JS boolean interface.
|
* JS boolean interface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
extern JSObject *
|
extern JSObject *
|
||||||
js_InitBooleanClass(JSContext *cx, js::HandleObject obj);
|
js_InitBooleanClass(JSContext *cx, js::HandleObject obj);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#define jsexn_h
|
#define jsexn_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the exception constructor/prototype hierarchy.
|
* Initialize the exception constructor/prototype hierarchy.
|
||||||
|
|
2616
js/src/jsinfer.cpp
2616
js/src/jsinfer.cpp
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -571,22 +571,8 @@ class StackTypeSet : public TypeSet
|
||||||
*/
|
*/
|
||||||
static StackTypeSet *make(JSContext *cx, const char *name);
|
static StackTypeSet *make(JSContext *cx, const char *name);
|
||||||
|
|
||||||
/* Constraints for type inference. */
|
/* Propagate any types from this set into target. */
|
||||||
|
void addSubset(JSContext *cx, StackTypeSet *target);
|
||||||
void addSubset(JSContext *cx, TypeSet *target);
|
|
||||||
void addGetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|
||||||
StackTypeSet *target, jsid id);
|
|
||||||
void addSetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|
||||||
StackTypeSet *target, jsid id);
|
|
||||||
void addSetElement(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|
||||||
StackTypeSet *objectTypes, StackTypeSet *valueTypes);
|
|
||||||
void addCall(JSContext *cx, TypeCallsite *site);
|
|
||||||
void addArith(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|
||||||
TypeSet *target, TypeSet *other = NULL);
|
|
||||||
void addTransformThis(JSContext *cx, JSScript *script, TypeSet *target);
|
|
||||||
void addPropagateThis(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|
||||||
Type type, StackTypeSet *types = NULL);
|
|
||||||
void addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constraints for JIT compilation.
|
* Constraints for JIT compilation.
|
||||||
|
@ -679,16 +665,8 @@ class HeapTypeSet : public TypeSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/* Constraints for type inference. */
|
/* Propagate any types from this set into target. */
|
||||||
|
void addSubset(JSContext *cx, HeapTypeSet *target);
|
||||||
void addSubset(JSContext *cx, TypeSet *target);
|
|
||||||
void addGetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|
||||||
StackTypeSet *target, jsid id);
|
|
||||||
void addCallProperty(JSContext *cx, JSScript *script, jsbytecode *pc, jsid id);
|
|
||||||
void addFilterPrimitives(JSContext *cx, TypeSet *target);
|
|
||||||
void addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target);
|
|
||||||
|
|
||||||
/* Constraints for JIT compilation. */
|
|
||||||
|
|
||||||
/* Completely freeze the contents of this type set. */
|
/* Completely freeze the contents of this type set. */
|
||||||
void addFreeze(JSContext *cx);
|
void addFreeze(JSContext *cx);
|
||||||
|
@ -745,6 +723,13 @@ TypeSet::toHeapTypeSet()
|
||||||
return (HeapTypeSet *) this;
|
return (HeapTypeSet *) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, TypeObject *type, jsid id);
|
||||||
|
|
||||||
|
void
|
||||||
|
AddClearDefiniteFunctionUsesInScript(JSContext *cx, TypeObject *type,
|
||||||
|
JSScript *script, JSScript *calleeScript);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handler which persists information about dynamic types pushed within a
|
* Handler which persists information about dynamic types pushed within a
|
||||||
* script which can affect its behavior and are not covered by JOF_TYPESET ops,
|
* script which can affect its behavior and are not covered by JOF_TYPESET ops,
|
||||||
|
@ -932,14 +917,14 @@ struct TypeNewScript : public TypeObjectAddendum
|
||||||
* scripted setter is added to one of the object's prototypes while it is
|
* scripted setter is added to one of the object's prototypes while it is
|
||||||
* in the middle of being initialized, so we can walk the stack and fixup
|
* in the middle of being initialized, so we can walk the stack and fixup
|
||||||
* any objects which look for in-progress objects which were prematurely
|
* any objects which look for in-progress objects which were prematurely
|
||||||
* set with their final shape. Initialization can traverse stack frames,
|
* set with their final shape. Property assignments in inner frames are
|
||||||
* in which case FRAME_PUSH/FRAME_POP are used.
|
* preceded by a series of SETPROP_FRAME entries specifying the stack down
|
||||||
|
* to the frame containing the write.
|
||||||
*/
|
*/
|
||||||
struct Initializer {
|
struct Initializer {
|
||||||
enum Kind {
|
enum Kind {
|
||||||
SETPROP,
|
SETPROP,
|
||||||
FRAME_PUSH,
|
SETPROP_FRAME,
|
||||||
FRAME_POP,
|
|
||||||
DONE
|
DONE
|
||||||
} kind;
|
} kind;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
|
@ -1145,7 +1130,7 @@ struct TypeObject : gc::Cell
|
||||||
void clearAddendum(ExclusiveContext *cx);
|
void clearAddendum(ExclusiveContext *cx);
|
||||||
void clearNewScriptAddendum(ExclusiveContext *cx);
|
void clearNewScriptAddendum(ExclusiveContext *cx);
|
||||||
void clearBinaryDataAddendum(ExclusiveContext *cx);
|
void clearBinaryDataAddendum(ExclusiveContext *cx);
|
||||||
void getFromPrototypes(JSContext *cx, jsid id, TypeSet *types, bool force = false);
|
void getFromPrototypes(JSContext *cx, jsid id, HeapTypeSet *types, bool force = false);
|
||||||
|
|
||||||
void print();
|
void print();
|
||||||
|
|
||||||
|
@ -1493,10 +1478,6 @@ struct TypeCompartment
|
||||||
void addPendingRecompile(JSContext *cx, const RecompileInfo &info);
|
void addPendingRecompile(JSContext *cx, const RecompileInfo &info);
|
||||||
void addPendingRecompile(JSContext *cx, JSScript *script);
|
void addPendingRecompile(JSContext *cx, JSScript *script);
|
||||||
|
|
||||||
/* Monitor future effects on a bytecode. */
|
|
||||||
void monitorBytecode(JSContext *cx, JSScript *script, uint32_t offset,
|
|
||||||
bool returnOnly = false);
|
|
||||||
|
|
||||||
/* Mark any type set containing obj as having a generic object type. */
|
/* Mark any type set containing obj as having a generic object type. */
|
||||||
void markSetsUnknown(JSContext *cx, TypeObject *obj);
|
void markSetsUnknown(JSContext *cx, TypeObject *obj);
|
||||||
|
|
||||||
|
|
|
@ -1682,18 +1682,6 @@ JSScript::ensureRanAnalysis(JSContext *cx)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
|
||||||
JSScript::ensureRanInference(JSContext *cx)
|
|
||||||
{
|
|
||||||
if (!ensureRanAnalysis(cx))
|
|
||||||
return false;
|
|
||||||
if (!analysis()->ranInference()) {
|
|
||||||
js::types::AutoEnterAnalysis enter(cx);
|
|
||||||
analysis()->analyzeTypes(cx);
|
|
||||||
}
|
|
||||||
return !analysis()->OOM() && !cx->zone()->types.pendingNukeTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
JSScript::hasAnalysis()
|
JSScript::hasAnalysis()
|
||||||
{
|
{
|
||||||
|
@ -1723,14 +1711,6 @@ JSScript::clearPropertyReadTypes()
|
||||||
types->propertyReadTypes = NULL;
|
types->propertyReadTypes = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
|
||||||
js::analyze::ScriptAnalysis::addPushedType(JSContext *cx, uint32_t offset, uint32_t which,
|
|
||||||
js::types::Type type)
|
|
||||||
{
|
|
||||||
js::types::TypeSet *pushed = pushedTypes(offset, which);
|
|
||||||
pushed->addType(cx, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include "mozilla/FloatingPoint.h"
|
#include "mozilla/FloatingPoint.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
#include "vm/NumericConversions.h"
|
#include "vm/NumericConversions.h"
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define json_h
|
#define json_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
#include "js/RootingAPI.h"
|
#include "js/RootingAPI.h"
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jsbytecode.h"
|
#include "jsbytecode.h"
|
||||||
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
#include "frontend/SourceNotes.h"
|
#include "frontend/SourceNotes.h"
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "jspropertytree.h"
|
#include "jspropertytree.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
|
||||||
#include "jscntxt.h"
|
#include "jscntxt.h"
|
||||||
#include "jsgc.h"
|
#include "jsgc.h"
|
||||||
#include "jstypes.h"
|
#include "jstypes.h"
|
||||||
|
|
|
@ -2834,11 +2834,6 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (script->hasAnalysis() && script->analysis()->ranInference()) {
|
|
||||||
types::AutoEnterAnalysis enter(cx);
|
|
||||||
types::TypeScript::MonitorUnknown(cx, script, script->argumentsBytecode());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,13 @@
|
||||||
#include "mozilla/HashFunctions.h"
|
#include "mozilla/HashFunctions.h"
|
||||||
#include "mozilla/PodOperations.h"
|
#include "mozilla/PodOperations.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
|
||||||
#include "jsutil.h"
|
#include "jsutil.h"
|
||||||
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
#include "js/RootingAPI.h"
|
#include "js/RootingAPI.h"
|
||||||
#include "vm/Unicode.h"
|
#include "vm/Unicode.h"
|
||||||
|
|
||||||
|
class JSAutoByteString;
|
||||||
class JSFlatString;
|
class JSFlatString;
|
||||||
class JSLinearString;
|
class JSLinearString;
|
||||||
class JSStableString;
|
class JSStableString;
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#define jswatchpoint_h
|
#define jswatchpoint_h
|
||||||
|
|
||||||
#include "jsalloc.h"
|
#include "jsalloc.h"
|
||||||
#include "jsapi.h"
|
|
||||||
|
|
||||||
#include "gc/Barrier.h"
|
#include "gc/Barrier.h"
|
||||||
#include "js/HashTable.h"
|
#include "js/HashTable.h"
|
||||||
|
|
|
@ -202,6 +202,9 @@ ParseTask::~ParseTask()
|
||||||
|
|
||||||
// ParseTask takes over ownership of its input exclusive context.
|
// ParseTask takes over ownership of its input exclusive context.
|
||||||
js_delete(cx);
|
js_delete(cx);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < errors.length(); i++)
|
||||||
|
js_delete(errors[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -550,7 +553,7 @@ WorkerThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void *toke
|
||||||
if (maybecx) {
|
if (maybecx) {
|
||||||
AutoCompartment ac(maybecx, parseTask->scopeChain);
|
AutoCompartment ac(maybecx, parseTask->scopeChain);
|
||||||
for (size_t i = 0; i < parseTask->errors.length(); i++)
|
for (size_t i = 0; i < parseTask->errors.length(); i++)
|
||||||
parseTask->errors[i].throwError(maybecx);
|
parseTask->errors[i]->throwError(maybecx);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSScript *script = parseTask->script;
|
JSScript *script = parseTask->script;
|
||||||
|
@ -677,9 +680,12 @@ ExclusiveContext::setWorkerThread(WorkerThread *workerThread)
|
||||||
frontend::CompileError &
|
frontend::CompileError &
|
||||||
ExclusiveContext::addPendingCompileError()
|
ExclusiveContext::addPendingCompileError()
|
||||||
{
|
{
|
||||||
if (!workerThread->parseTask->errors.append(frontend::CompileError()))
|
frontend::CompileError *error = js_new<frontend::CompileError>();
|
||||||
|
if (!error)
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
return workerThread->parseTask->errors.back();
|
if (!workerThread->parseTask->errors.append(error))
|
||||||
|
MOZ_CRASH();
|
||||||
|
return *error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -389,7 +389,7 @@ struct ParseTask
|
||||||
|
|
||||||
// Any errors or warnings produced during compilation. These are reported
|
// Any errors or warnings produced during compilation. These are reported
|
||||||
// when finishing the script.
|
// when finishing the script.
|
||||||
Vector<frontend::CompileError> errors;
|
Vector<frontend::CompileError *> errors;
|
||||||
|
|
||||||
ParseTask(ExclusiveContext *cx, const CompileOptions &options,
|
ParseTask(ExclusiveContext *cx, const CompileOptions &options,
|
||||||
const jschar *chars, size_t length, JSObject *scopeChain,
|
const jschar *chars, size_t length, JSObject *scopeChain,
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
#ifndef perf_jsperf_h
|
#ifndef perf_jsperf_h
|
||||||
#define perf_jsperf_h
|
#define perf_jsperf_h
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jstypes.h"
|
||||||
|
|
||||||
|
#include "js/TypeDecls.h"
|
||||||
|
#include "js/Utility.h"
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
|
@ -118,12 +121,12 @@ extern JS_FRIEND_API(JSObject*)
|
||||||
RegisterPerfMeasurement(JSContext *cx, JSObject *global);
|
RegisterPerfMeasurement(JSContext *cx, JSObject *global);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given a jsval which contains an instance of the aforementioned
|
* Given a Value which contains an instance of the aforementioned
|
||||||
* wrapper class, extract the C++ object. Returns NULL if the
|
* wrapper class, extract the C++ object. Returns NULL if the
|
||||||
* jsval is not an instance of the wrapper.
|
* Value is not an instance of the wrapper.
|
||||||
*/
|
*/
|
||||||
extern JS_FRIEND_API(PerfMeasurement*)
|
extern JS_FRIEND_API(PerfMeasurement*)
|
||||||
ExtractPerfMeasurement(jsval wrapper);
|
ExtractPerfMeasurement(Value wrapper);
|
||||||
|
|
||||||
} // namespace JS
|
} // namespace JS
|
||||||
|
|
||||||
|
|
|
@ -953,8 +953,8 @@ TryNoteIter::settle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PUSH_COPY(v) do { *regs.sp++ = v; assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
|
#define PUSH_COPY(v) do { *regs.sp++ = (v); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
|
||||||
#define PUSH_COPY_SKIP_CHECK(v) *regs.sp++ = v
|
#define PUSH_COPY_SKIP_CHECK(v) *regs.sp++ = (v)
|
||||||
#define PUSH_NULL() regs.sp++->setNull()
|
#define PUSH_NULL() regs.sp++->setNull()
|
||||||
#define PUSH_UNDEFINED() regs.sp++->setUndefined()
|
#define PUSH_UNDEFINED() regs.sp++->setUndefined()
|
||||||
#define PUSH_BOOLEAN(b) regs.sp++->setBoolean(b)
|
#define PUSH_BOOLEAN(b) regs.sp++->setBoolean(b)
|
||||||
|
@ -964,13 +964,13 @@ TryNoteIter::settle()
|
||||||
#define PUSH_OBJECT(obj) do { regs.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
|
#define PUSH_OBJECT(obj) do { regs.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
|
||||||
#define PUSH_OBJECT_OR_NULL(obj) do { regs.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
|
#define PUSH_OBJECT_OR_NULL(obj) do { regs.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
|
||||||
#define PUSH_HOLE() regs.sp++->setMagic(JS_ELEMENTS_HOLE)
|
#define PUSH_HOLE() regs.sp++->setMagic(JS_ELEMENTS_HOLE)
|
||||||
#define POP_COPY_TO(v) v = *--regs.sp
|
#define POP_COPY_TO(v) (v) = *--regs.sp
|
||||||
#define POP_RETURN_VALUE() regs.fp()->setReturnValue(*--regs.sp)
|
#define POP_RETURN_VALUE() regs.fp()->setReturnValue(*--regs.sp)
|
||||||
|
|
||||||
#define FETCH_OBJECT(cx, n, obj) \
|
#define FETCH_OBJECT(cx, n, obj) \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
HandleValue val = regs.stackHandleAt(n); \
|
HandleValue val = regs.stackHandleAt(n); \
|
||||||
obj = ToObjectFromStack(cx, (val)); \
|
obj = ToObjectFromStack((cx), (val)); \
|
||||||
if (!obj) \
|
if (!obj) \
|
||||||
goto error; \
|
goto error; \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
@ -1277,35 +1277,19 @@ Interpret(JSContext *cx, RunState &state)
|
||||||
register int switchMask = 0;
|
register int switchMask = 0;
|
||||||
int switchOp;
|
int switchOp;
|
||||||
|
|
||||||
# define DO_OP() goto do_op
|
#define DO_OP() goto do_op
|
||||||
|
|
||||||
# define BEGIN_CASE(OP) case OP:
|
#define BEGIN_CASE(OP) case OP:
|
||||||
# define END_CASE(OP) END_CASE_LEN(OP##_LENGTH)
|
#define END_CASE(OP) \
|
||||||
# define END_CASE_LEN(n) END_CASE_LENX(n)
|
JS_BEGIN_MACRO \
|
||||||
# define END_CASE_LENX(n) END_CASE_LEN##n
|
len = OP##_LENGTH; \
|
||||||
|
goto advanceAndDoOp; \
|
||||||
|
JS_END_MACRO;
|
||||||
|
|
||||||
/*
|
#define END_VARLEN_CASE goto advanceAndDoOp;
|
||||||
* To share the code for all len == 1 cases we use the specialized label with
|
|
||||||
* code that falls through to advanceAndDoOp: .
|
|
||||||
*/
|
|
||||||
# define END_CASE_LEN1 goto advance_pc_by_one;
|
|
||||||
# define END_CASE_LEN2 len = 2; goto advanceAndDoOp;
|
|
||||||
# define END_CASE_LEN3 len = 3; goto advanceAndDoOp;
|
|
||||||
# define END_CASE_LEN4 len = 4; goto advanceAndDoOp;
|
|
||||||
# define END_CASE_LEN5 len = 5; goto advanceAndDoOp;
|
|
||||||
# define END_CASE_LEN6 len = 6; goto advanceAndDoOp;
|
|
||||||
# define END_CASE_LEN7 len = 7; goto advanceAndDoOp;
|
|
||||||
# define END_CASE_LEN8 len = 8; goto advanceAndDoOp;
|
|
||||||
# define END_CASE_LEN9 len = 9; goto advanceAndDoOp;
|
|
||||||
# define END_CASE_LEN10 len = 10; goto advanceAndDoOp;
|
|
||||||
# define END_CASE_LEN11 len = 11; goto advanceAndDoOp;
|
|
||||||
# define END_CASE_LEN12 len = 12; goto advanceAndDoOp;
|
|
||||||
# define END_VARLEN_CASE goto advanceAndDoOp;
|
|
||||||
# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)
|
|
||||||
# define END_EMPTY_CASES goto advance_pc_by_one;
|
|
||||||
|
|
||||||
#define LOAD_DOUBLE(PCOFF, dbl) \
|
#define LOAD_DOUBLE(PCOFF, dbl) \
|
||||||
(dbl = script->getConst(GET_UINT32_INDEX(regs.pc + (PCOFF))).toDouble())
|
((dbl) = script->getConst(GET_UINT32_INDEX(regs.pc + (PCOFF))).toDouble())
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare to call a user-supplied branch handler, and abort the script
|
* Prepare to call a user-supplied branch handler, and abort the script
|
||||||
|
@ -1431,12 +1415,7 @@ Interpret(JSContext *cx, RunState &state)
|
||||||
if (rt->profilingScripts || cx->runtime()->debugHooks.interruptHook)
|
if (rt->profilingScripts || cx->runtime()->debugHooks.interruptHook)
|
||||||
switchMask = -1; /* Enable interrupts. */
|
switchMask = -1; /* Enable interrupts. */
|
||||||
|
|
||||||
goto advanceAndDoOp;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
advance_pc_by_one:
|
|
||||||
JS_ASSERT(js_CodeSpec[op].length == 1);
|
|
||||||
len = 1;
|
|
||||||
advanceAndDoOp:
|
advanceAndDoOp:
|
||||||
js::gc::MaybeVerifyBarriers(cx);
|
js::gc::MaybeVerifyBarriers(cx);
|
||||||
regs.pc += len;
|
regs.pc += len;
|
||||||
|
@ -1518,51 +1497,55 @@ Interpret(JSContext *cx, RunState &state)
|
||||||
goto do_switch;
|
goto do_switch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No-ops for ease of decompilation. */
|
/* Various 1-byte no-ops. */
|
||||||
ADD_EMPTY_CASE(JSOP_NOP)
|
BEGIN_CASE(JSOP_NOP)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED125)
|
BEGIN_CASE(JSOP_UNUSED125)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED126)
|
BEGIN_CASE(JSOP_UNUSED126)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED132)
|
BEGIN_CASE(JSOP_UNUSED132)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED148)
|
BEGIN_CASE(JSOP_UNUSED148)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED161)
|
BEGIN_CASE(JSOP_UNUSED161)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED162)
|
BEGIN_CASE(JSOP_UNUSED162)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED163)
|
BEGIN_CASE(JSOP_UNUSED163)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED164)
|
BEGIN_CASE(JSOP_UNUSED164)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED165)
|
BEGIN_CASE(JSOP_UNUSED165)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED166)
|
BEGIN_CASE(JSOP_UNUSED166)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED167)
|
BEGIN_CASE(JSOP_UNUSED167)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED168)
|
BEGIN_CASE(JSOP_UNUSED168)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED169)
|
BEGIN_CASE(JSOP_UNUSED169)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED170)
|
BEGIN_CASE(JSOP_UNUSED170)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED171)
|
BEGIN_CASE(JSOP_UNUSED171)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED172)
|
BEGIN_CASE(JSOP_UNUSED172)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED173)
|
BEGIN_CASE(JSOP_UNUSED173)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED174)
|
BEGIN_CASE(JSOP_UNUSED174)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED175)
|
BEGIN_CASE(JSOP_UNUSED175)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED176)
|
BEGIN_CASE(JSOP_UNUSED176)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED177)
|
BEGIN_CASE(JSOP_UNUSED177)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED178)
|
BEGIN_CASE(JSOP_UNUSED178)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED179)
|
BEGIN_CASE(JSOP_UNUSED179)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED180)
|
BEGIN_CASE(JSOP_UNUSED180)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED181)
|
BEGIN_CASE(JSOP_UNUSED181)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED182)
|
BEGIN_CASE(JSOP_UNUSED182)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED183)
|
BEGIN_CASE(JSOP_UNUSED183)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED188)
|
BEGIN_CASE(JSOP_UNUSED188)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED189)
|
BEGIN_CASE(JSOP_UNUSED189)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED190)
|
BEGIN_CASE(JSOP_UNUSED190)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED200)
|
BEGIN_CASE(JSOP_UNUSED200)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED201)
|
BEGIN_CASE(JSOP_UNUSED201)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED208)
|
BEGIN_CASE(JSOP_UNUSED208)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED209)
|
BEGIN_CASE(JSOP_UNUSED209)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED210)
|
BEGIN_CASE(JSOP_UNUSED210)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED219)
|
BEGIN_CASE(JSOP_UNUSED219)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED220)
|
BEGIN_CASE(JSOP_UNUSED220)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED221)
|
BEGIN_CASE(JSOP_UNUSED221)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED222)
|
BEGIN_CASE(JSOP_UNUSED222)
|
||||||
ADD_EMPTY_CASE(JSOP_UNUSED223)
|
BEGIN_CASE(JSOP_UNUSED223)
|
||||||
ADD_EMPTY_CASE(JSOP_CONDSWITCH)
|
BEGIN_CASE(JSOP_CONDSWITCH)
|
||||||
ADD_EMPTY_CASE(JSOP_TRY)
|
BEGIN_CASE(JSOP_TRY)
|
||||||
END_EMPTY_CASES
|
{
|
||||||
|
JS_ASSERT(js_CodeSpec[op].length == 1);
|
||||||
|
len = 1;
|
||||||
|
goto advanceAndDoOp;
|
||||||
|
}
|
||||||
|
|
||||||
BEGIN_CASE(JSOP_LOOPHEAD)
|
BEGIN_CASE(JSOP_LOOPHEAD)
|
||||||
END_CASE(JSOP_LOOPHEAD)
|
END_CASE(JSOP_LOOPHEAD)
|
||||||
|
@ -1605,7 +1588,6 @@ END_CASE(JSOP_LOOPENTRY)
|
||||||
BEGIN_CASE(JSOP_NOTEARG)
|
BEGIN_CASE(JSOP_NOTEARG)
|
||||||
END_CASE(JSOP_NOTEARG)
|
END_CASE(JSOP_NOTEARG)
|
||||||
|
|
||||||
/* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */
|
|
||||||
BEGIN_CASE(JSOP_LINENO)
|
BEGIN_CASE(JSOP_LINENO)
|
||||||
END_CASE(JSOP_LINENO)
|
END_CASE(JSOP_LINENO)
|
||||||
|
|
||||||
|
@ -1772,17 +1754,17 @@ END_CASE(JSOP_AND)
|
||||||
|
|
||||||
#define FETCH_ELEMENT_ID(n, id) \
|
#define FETCH_ELEMENT_ID(n, id) \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
if (!ValueToId<CanGC>(cx, regs.stackHandleAt(n), &id)) \
|
if (!ValueToId<CanGC>(cx, regs.stackHandleAt(n), &(id))) \
|
||||||
goto error; \
|
goto error; \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
|
||||||
#define TRY_BRANCH_AFTER_COND(cond,spdec) \
|
#define TRY_BRANCH_AFTER_COND(cond,spdec) \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
JS_ASSERT(js_CodeSpec[op].length == 1); \
|
JS_ASSERT(js_CodeSpec[op].length == 1); \
|
||||||
unsigned diff_ = (unsigned) GET_UINT8(regs.pc) - (unsigned) JSOP_IFEQ; \
|
unsigned diff_ = (unsigned) GET_UINT8(regs.pc) - (unsigned) JSOP_IFEQ;\
|
||||||
if (diff_ <= 1) { \
|
if (diff_ <= 1) { \
|
||||||
regs.sp -= spdec; \
|
regs.sp -= (spdec); \
|
||||||
if (cond == (diff_ != 0)) { \
|
if ((cond) == (diff_ != 0)) { \
|
||||||
++regs.pc; \
|
++regs.pc; \
|
||||||
len = GET_JUMP_OFFSET(regs.pc); \
|
len = GET_JUMP_OFFSET(regs.pc); \
|
||||||
BRANCH(len); \
|
BRANCH(len); \
|
||||||
|
@ -2004,7 +1986,7 @@ END_CASE(JSOP_NE)
|
||||||
bool equal; \
|
bool equal; \
|
||||||
if (!StrictlyEqual(cx, lref, rref, &equal)) \
|
if (!StrictlyEqual(cx, lref, rref, &equal)) \
|
||||||
goto error; \
|
goto error; \
|
||||||
COND = equal OP true; \
|
(COND) = equal OP true; \
|
||||||
regs.sp--; \
|
regs.sp--; \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
#include "jsinfer.h"
|
#include "jsinfer.h"
|
||||||
|
#include "NamespaceImports.h"
|
||||||
|
|
||||||
#include "gc/Barrier.h"
|
#include "gc/Barrier.h"
|
||||||
#include "gc/Heap.h"
|
#include "gc/Heap.h"
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#include "mozilla/Endian.h"
|
#include "mozilla/Endian.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
|
||||||
#include "jsatom.h"
|
#include "jsatom.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "mozilla/dom/BindingUtils.h"
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
using namespace JS;
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace xpc;
|
using namespace xpc;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "nsGlobalWindow.h"
|
#include "nsGlobalWindow.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
using namespace JS;
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace xpc;
|
using namespace xpc;
|
||||||
|
|
||||||
|
@ -3714,7 +3715,7 @@ nsXPCComponents::AttachComponentsObject(JSContext* aCx,
|
||||||
MOZ_ASSERT(js::IsObjectInContextCompartment(global, aCx));
|
MOZ_ASSERT(js::IsObjectInContextCompartment(global, aCx));
|
||||||
|
|
||||||
RootedId id(aCx, XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS));
|
RootedId id(aCx, XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS));
|
||||||
return JS_DefinePropertyById(aCx, global, id, js::ObjectValue(*components),
|
return JS_DefinePropertyById(aCx, global, id, JS::ObjectValue(*components),
|
||||||
nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY);
|
nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "mozilla/dom/BindingUtils.h"
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
using namespace JS;
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
namespace xpc {
|
namespace xpc {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
|
||||||
|
using namespace JS;
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
namespace xpc {
|
namespace xpc {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
|
||||||
|
using namespace JS;
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
|
|
|
@ -66,17 +66,6 @@ public:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MOZ_ANDROID_SONY_WORKAROUND)
|
|
||||||
private:
|
|
||||||
// Sony ICS devices have extra virtual methods in DataSource.
|
|
||||||
// The dummy methods below fill these vtable positions.
|
|
||||||
virtual void foo1() { abort(); }
|
|
||||||
virtual void foo2() { abort(); }
|
|
||||||
virtual void foo3() { abort(); }
|
|
||||||
virtual void foo4() { abort(); }
|
|
||||||
public:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual status_t reconnectAtOffset(off64_t offset) {
|
virtual status_t reconnectAtOffset(off64_t offset) {
|
||||||
return ERROR_UNSUPPORTED;
|
return ERROR_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,22 +20,4 @@ index 81ef632..713af92 100644
|
||||||
public:
|
public:
|
||||||
enum Flags {
|
enum Flags {
|
||||||
kWantsPrefetching = 1,
|
kWantsPrefetching = 1,
|
||||||
@@ -66,17 +62,6 @@ public:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-#if defined(MOZ_ANDROID_SONY_WORKAROUND)
|
|
||||||
-private:
|
|
||||||
- // Sony ICS devices have extra virtual methods in DataSource.
|
|
||||||
- // The dummy methods below fill these vtable positions.
|
|
||||||
- virtual void foo1() { abort(); }
|
|
||||||
- virtual void foo2() { abort(); }
|
|
||||||
- virtual void foo3() { abort(); }
|
|
||||||
- virtual void foo4() { abort(); }
|
|
||||||
-public:
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
virtual status_t reconnectAtOffset(off64_t offset) {
|
|
||||||
return ERROR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
# Copyright 2012 Mozilla Foundation and Mozilla contributors
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
DEPTH = @DEPTH@
|
|
||||||
topsrcdir = @top_srcdir@
|
|
||||||
srcdir = @srcdir@
|
|
||||||
VPATH = @srcdir@
|
|
||||||
|
|
||||||
include $(DEPTH)/config/autoconf.mk
|
|
||||||
|
|
||||||
MODULE_NAME = omxpluginjb-htc
|
|
||||||
FORCE_SHARED_LIB = 1
|
|
||||||
|
|
||||||
# Don't use STL wrappers; this isn't Gecko code
|
|
||||||
STL_FLAGS =
|
|
||||||
|
|
||||||
# must link statically with the CRT; this isn't Gecko code
|
|
||||||
USE_STATIC_LIBS = 1
|
|
||||||
|
|
||||||
# Need to custom install OMX media plugin
|
|
||||||
NO_INSTALL = 1
|
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
|
||||||
|
|
||||||
ifdef GNU_CXX
|
|
||||||
# Turn off C++ 11 features due to conflicts with Android OS headers and char16_t definition
|
|
||||||
CXXFLAGS += -std=gnu++98
|
|
||||||
endif
|
|
||||||
|
|
||||||
INCLUDES += \
|
|
||||||
-I$(srcdir)/../../../content/media/plugins \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
EXTRA_DSO_LDOPTS += \
|
|
||||||
-L$(DEPTH)/media/omx-plugin/lib/ics/libutils \
|
|
||||||
-lutils \
|
|
||||||
-L$(DEPTH)/media/omx-plugin/lib/ics/libstagefright \
|
|
||||||
-lstagefright \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
INCLUDES += \
|
|
||||||
-I$(srcdir)/../include/ics \
|
|
||||||
-I$(srcdir)/../include/ics/media/stagefright/openmax \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
libs:: $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX)
|
|
||||||
$(INSTALL) $< $(DEPTH)/dist/bin
|
|
||||||
|
|
||||||
libs:: $(PROGRAMS)
|
|
|
@ -1,9 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
||||||
/* 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/. */
|
|
||||||
#define MOZ_STAGEFRIGHT_OFF_T off64_t
|
|
||||||
#define MOZ_ANDROID_ICS
|
|
||||||
#define MOZ_ANDROID_HTC_WORKAROUND
|
|
||||||
#include "../OmxPlugin.cpp"
|
|
|
@ -1,15 +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/.
|
|
||||||
|
|
||||||
MODULE = 'omxpluginjb-htc'
|
|
||||||
NO_DIST_INSTALL = True
|
|
||||||
|
|
||||||
CPP_SOURCES += [
|
|
||||||
'OmxPluginJB-HTC.cpp',
|
|
||||||
]
|
|
||||||
|
|
||||||
LIBRARY_NAME = 'omxpluginjb-htc'
|
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
# Copyright 2012 Mozilla Foundation and Mozilla contributors
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
DEPTH = @DEPTH@
|
|
||||||
topsrcdir = @top_srcdir@
|
|
||||||
srcdir = @srcdir@
|
|
||||||
VPATH = @srcdir@
|
|
||||||
|
|
||||||
include $(DEPTH)/config/autoconf.mk
|
|
||||||
|
|
||||||
MODULE_NAME = omxpluginsony
|
|
||||||
FORCE_SHARED_LIB = 1
|
|
||||||
|
|
||||||
# Don't use STL wrappers; this isn't Gecko code
|
|
||||||
STL_FLAGS =
|
|
||||||
|
|
||||||
# must link statically with the CRT; this isn't Gecko code
|
|
||||||
USE_STATIC_LIBS = 1
|
|
||||||
|
|
||||||
# Need to custom install OMX media plugin
|
|
||||||
NO_INSTALL = 1
|
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
|
||||||
|
|
||||||
ifdef GNU_CXX
|
|
||||||
# Turn off C++ 11 features due to conflicts with Android OS headers and char16_t definition
|
|
||||||
CXXFLAGS += -std=gnu++98
|
|
||||||
endif
|
|
||||||
|
|
||||||
INCLUDES += \
|
|
||||||
-I$(srcdir)/../../../content/media/plugins \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
EXTRA_DSO_LDOPTS += \
|
|
||||||
-L$(DEPTH)/media/omx-plugin/lib/ics/libutils \
|
|
||||||
-lutils \
|
|
||||||
-L$(DEPTH)/media/omx-plugin/lib/ics/libstagefright \
|
|
||||||
-lstagefright \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
INCLUDES += \
|
|
||||||
-I$(srcdir)/../include/ics \
|
|
||||||
-I$(srcdir)/../include/ics/media/stagefright/openmax \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
libs:: $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX)
|
|
||||||
$(INSTALL) $< $(DEPTH)/dist/bin
|
|
||||||
|
|
||||||
libs:: $(PROGRAMS)
|
|
|
@ -1,10 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
||||||
/* 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/. */
|
|
||||||
#define MOZ_STAGEFRIGHT_OFF_T off64_t
|
|
||||||
#define MOZ_ANDROID_GB
|
|
||||||
#define MOZ_ANDROID_HC
|
|
||||||
#include <ui/egl/android_natives.h>
|
|
||||||
#include "../OmxPlugin.cpp"
|
|
|
@ -1,9 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
||||||
/* 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/. */
|
|
||||||
#define MOZ_STAGEFRIGHT_OFF_T off64_t
|
|
||||||
#define MOZ_ANDROID_ICS
|
|
||||||
#define MOZ_ANDROID_SONY_WORKAROUND
|
|
||||||
#include "../OmxPlugin.cpp"
|
|
|
@ -1,15 +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/.
|
|
||||||
|
|
||||||
MODULE = 'omxpluginsony'
|
|
||||||
NO_DIST_INSTALL = True
|
|
||||||
|
|
||||||
CPP_SOURCES += [
|
|
||||||
'OmxPluginSony.cpp',
|
|
||||||
]
|
|
||||||
|
|
||||||
LIBRARY_NAME = 'omxpluginsony'
|
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
using mozilla::DoublesAreIdentical;
|
using mozilla::DoublesAreIdentical;
|
||||||
|
using mozilla::IsFinite;
|
||||||
|
using mozilla::IsInfinite;
|
||||||
|
using mozilla::IsNaN;
|
||||||
|
using mozilla::IsNegative;
|
||||||
|
using mozilla::IsNegativeZero;
|
||||||
using mozilla::NegativeInfinity;
|
using mozilla::NegativeInfinity;
|
||||||
using mozilla::PositiveInfinity;
|
using mozilla::PositiveInfinity;
|
||||||
using mozilla::SpecificNaN;
|
using mozilla::SpecificNaN;
|
||||||
|
@ -97,8 +102,54 @@ TestDoublesAreIdentical()
|
||||||
ShouldNotBeIdentical(UnspecifiedNaN(), NegativeInfinity());
|
ShouldNotBeIdentical(UnspecifiedNaN(), NegativeInfinity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
TestPredicates()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsNaN(UnspecifiedNaN()));
|
||||||
|
MOZ_ASSERT(IsNaN(SpecificNaN(1, 17)));;
|
||||||
|
MOZ_ASSERT(IsNaN(SpecificNaN(0, 0xfffffffffff0fULL)));
|
||||||
|
MOZ_ASSERT(!IsNaN(0));
|
||||||
|
MOZ_ASSERT(!IsNaN(-0.0));
|
||||||
|
MOZ_ASSERT(!IsNaN(1.0));
|
||||||
|
MOZ_ASSERT(!IsNaN(PositiveInfinity()));
|
||||||
|
MOZ_ASSERT(!IsNaN(NegativeInfinity()));
|
||||||
|
|
||||||
|
MOZ_ASSERT(IsInfinite(PositiveInfinity()));
|
||||||
|
MOZ_ASSERT(IsInfinite(NegativeInfinity()));
|
||||||
|
MOZ_ASSERT(!IsInfinite(UnspecifiedNaN()));
|
||||||
|
MOZ_ASSERT(!IsInfinite(0));
|
||||||
|
MOZ_ASSERT(!IsInfinite(-0.0));
|
||||||
|
MOZ_ASSERT(!IsInfinite(1.0));
|
||||||
|
|
||||||
|
MOZ_ASSERT(!IsFinite(PositiveInfinity()));
|
||||||
|
MOZ_ASSERT(!IsFinite(NegativeInfinity()));
|
||||||
|
MOZ_ASSERT(!IsFinite(UnspecifiedNaN()));
|
||||||
|
MOZ_ASSERT(IsFinite(0));
|
||||||
|
MOZ_ASSERT(IsFinite(-0.0));
|
||||||
|
MOZ_ASSERT(IsFinite(1.0));
|
||||||
|
|
||||||
|
MOZ_ASSERT(!IsNegative(PositiveInfinity()));
|
||||||
|
MOZ_ASSERT(IsNegative(NegativeInfinity()));
|
||||||
|
MOZ_ASSERT(IsNegative(-0.0));
|
||||||
|
MOZ_ASSERT(!IsNegative(0.0));
|
||||||
|
MOZ_ASSERT(IsNegative(-1.0));
|
||||||
|
MOZ_ASSERT(!IsNegative(1.0));
|
||||||
|
|
||||||
|
MOZ_ASSERT(!IsNegativeZero(PositiveInfinity()));
|
||||||
|
MOZ_ASSERT(!IsNegativeZero(NegativeInfinity()));
|
||||||
|
MOZ_ASSERT(!IsNegativeZero(SpecificNaN(1, 17)));;
|
||||||
|
MOZ_ASSERT(!IsNegativeZero(SpecificNaN(1, 0xfffffffffff0fULL)));
|
||||||
|
MOZ_ASSERT(!IsNegativeZero(SpecificNaN(0, 17)));;
|
||||||
|
MOZ_ASSERT(!IsNegativeZero(SpecificNaN(0, 0xfffffffffff0fULL)));
|
||||||
|
MOZ_ASSERT(IsNegativeZero(-0.0));
|
||||||
|
MOZ_ASSERT(!IsNegativeZero(0.0));
|
||||||
|
MOZ_ASSERT(!IsNegativeZero(-1.0));
|
||||||
|
MOZ_ASSERT(!IsNegativeZero(1.0));
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
TestDoublesAreIdentical();
|
TestDoublesAreIdentical();
|
||||||
|
TestPredicates();
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,6 @@
|
||||||
@BINPATH@/@DLL_PREFIX@omxplugingb@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@omxplugingb@DLL_SUFFIX@
|
||||||
@BINPATH@/@DLL_PREFIX@omxplugingb235@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@omxplugingb235@DLL_SUFFIX@
|
||||||
@BINPATH@/@DLL_PREFIX@omxpluginhc@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@omxpluginhc@DLL_SUFFIX@
|
||||||
@BINPATH@/@DLL_PREFIX@omxpluginjb-htc@DLL_SUFFIX@
|
|
||||||
@BINPATH@/@DLL_PREFIX@omxpluginsony@DLL_SUFFIX@
|
|
||||||
@BINPATH@/@DLL_PREFIX@omxpluginfroyo@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@omxpluginfroyo@DLL_SUFFIX@
|
||||||
@BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@
|
||||||
|
|
||||||
|
|
|
@ -118,17 +118,21 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||||
CPP_UNIT_TESTS='CPP_UNIT_TESTS',
|
CPP_UNIT_TESTS='CPP_UNIT_TESTS',
|
||||||
CSRCS='CSRCS',
|
CSRCS='CSRCS',
|
||||||
DEFINES='DEFINES',
|
DEFINES='DEFINES',
|
||||||
|
EXPORT_LIBRARY='EXPORT_LIBRARY',
|
||||||
EXTRA_COMPONENTS='EXTRA_COMPONENTS',
|
EXTRA_COMPONENTS='EXTRA_COMPONENTS',
|
||||||
EXTRA_JS_MODULES='EXTRA_JS_MODULES',
|
EXTRA_JS_MODULES='EXTRA_JS_MODULES',
|
||||||
EXTRA_PP_COMPONENTS='EXTRA_PP_COMPONENTS',
|
EXTRA_PP_COMPONENTS='EXTRA_PP_COMPONENTS',
|
||||||
EXTRA_PP_JS_MODULES='EXTRA_PP_JS_MODULES',
|
EXTRA_PP_JS_MODULES='EXTRA_PP_JS_MODULES',
|
||||||
FAIL_ON_WARNINGS='FAIL_ON_WARNINGS',
|
FAIL_ON_WARNINGS='FAIL_ON_WARNINGS',
|
||||||
|
FORCE_SHARED_LIB='FORCE_SHARED_LIB',
|
||||||
|
FORCE_STATIC_LIB='FORCE_STATIC_LIB',
|
||||||
GTEST_CMMSRCS='GTEST_CMM_SOURCES',
|
GTEST_CMMSRCS='GTEST_CMM_SOURCES',
|
||||||
GTEST_CPPSRCS='GTEST_CPP_SOURCES',
|
GTEST_CPPSRCS='GTEST_CPP_SOURCES',
|
||||||
GTEST_CSRCS='GTEST_C_SOURCES',
|
GTEST_CSRCS='GTEST_C_SOURCES',
|
||||||
HOST_CPPSRCS='HOST_CPPSRCS',
|
HOST_CPPSRCS='HOST_CPPSRCS',
|
||||||
HOST_CSRCS='HOST_CSRCS',
|
HOST_CSRCS='HOST_CSRCS',
|
||||||
HOST_LIBRARY_NAME='HOST_LIBRARY_NAME',
|
HOST_LIBRARY_NAME='HOST_LIBRARY_NAME',
|
||||||
|
IS_COMPONENT='IS_COMPONENT',
|
||||||
JS_MODULES_PATH='JS_MODULES_PATH',
|
JS_MODULES_PATH='JS_MODULES_PATH',
|
||||||
LIBRARY_NAME='LIBRARY_NAME',
|
LIBRARY_NAME='LIBRARY_NAME',
|
||||||
LIBS='LIBS',
|
LIBS='LIBS',
|
||||||
|
|
|
@ -98,6 +98,10 @@ VARIABLES = {
|
||||||
delimiters.
|
delimiters.
|
||||||
"""),
|
"""),
|
||||||
|
|
||||||
|
'EXPORT_LIBRARY': (bool, bool, False,
|
||||||
|
"""Install the library to the static libraries folder.
|
||||||
|
"""),
|
||||||
|
|
||||||
'EXTRA_COMPONENTS': (StrictOrderingOnAppendList, list, [],
|
'EXTRA_COMPONENTS': (StrictOrderingOnAppendList, list, [],
|
||||||
"""Additional component files to distribute.
|
"""Additional component files to distribute.
|
||||||
|
|
||||||
|
@ -138,6 +142,14 @@ VARIABLES = {
|
||||||
"""Whether to treat warnings as errors.
|
"""Whether to treat warnings as errors.
|
||||||
"""),
|
"""),
|
||||||
|
|
||||||
|
'FORCE_SHARED_LIB': (bool, bool, False,
|
||||||
|
"""Whether the library in this directory is a shared library.
|
||||||
|
"""),
|
||||||
|
|
||||||
|
'FORCE_STATIC_LIB': (bool, bool, False,
|
||||||
|
"""Whether the library in this directory is a static library.
|
||||||
|
"""),
|
||||||
|
|
||||||
'GTEST_C_SOURCES': (StrictOrderingOnAppendList, list, [],
|
'GTEST_C_SOURCES': (StrictOrderingOnAppendList, list, [],
|
||||||
"""C code source files for GTest unit tests.
|
"""C code source files for GTest unit tests.
|
||||||
|
|
||||||
|
@ -171,6 +183,10 @@ VARIABLES = {
|
||||||
This variable contains a list of C source files to compile.
|
This variable contains a list of C source files to compile.
|
||||||
"""),
|
"""),
|
||||||
|
|
||||||
|
'IS_COMPONENT': (bool, bool, False,
|
||||||
|
"""Whether the library contains a binary XPCOM component manifest.
|
||||||
|
"""),
|
||||||
|
|
||||||
'PARALLEL_DIRS': (list, list, [],
|
'PARALLEL_DIRS': (list, list, [],
|
||||||
"""A parallel version of DIRS.
|
"""A parallel version of DIRS.
|
||||||
|
|
||||||
|
@ -212,7 +228,7 @@ VARIABLES = {
|
||||||
'LIBXUL_LIBRARY': (bool, bool, False,
|
'LIBXUL_LIBRARY': (bool, bool, False,
|
||||||
"""Whether the library in this directory is linked into libxul.
|
"""Whether the library in this directory is linked into libxul.
|
||||||
|
|
||||||
Implies MOZILLA_INTERNAL_API.
|
Implies MOZILLA_INTERNAL_API and FORCE_STATIC_LIB.
|
||||||
"""),
|
"""),
|
||||||
|
|
||||||
'MSVC_ENABLE_PGO': (bool, bool, False,
|
'MSVC_ENABLE_PGO': (bool, bool, False,
|
||||||
|
|
|
@ -45,3 +45,8 @@ LIBXUL_LIBRARY = True
|
||||||
MSVC_ENABLE_PGO = True
|
MSVC_ENABLE_PGO = True
|
||||||
|
|
||||||
NO_DIST_INSTALL = True
|
NO_DIST_INSTALL = True
|
||||||
|
|
||||||
|
FORCE_SHARED_LIB = True
|
||||||
|
FORCE_STATIC_LIB = True
|
||||||
|
EXPORT_LIBRARY = True
|
||||||
|
IS_COMPONENT = True
|
||||||
|
|
|
@ -132,17 +132,21 @@ class TestEmitterBasic(unittest.TestCase):
|
||||||
CSRCS=['fans.c', 'tans.c'],
|
CSRCS=['fans.c', 'tans.c'],
|
||||||
CPP_UNIT_TESTS=['foo.cpp'],
|
CPP_UNIT_TESTS=['foo.cpp'],
|
||||||
DEFINES=['-Dfans', '-Dtans'],
|
DEFINES=['-Dfans', '-Dtans'],
|
||||||
|
EXPORT_LIBRARY=True,
|
||||||
EXTRA_COMPONENTS=['fans.js', 'tans.js'],
|
EXTRA_COMPONENTS=['fans.js', 'tans.js'],
|
||||||
EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'],
|
EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'],
|
||||||
EXTRA_JS_MODULES=['bar.jsm', 'foo.jsm'],
|
EXTRA_JS_MODULES=['bar.jsm', 'foo.jsm'],
|
||||||
EXTRA_PP_JS_MODULES=['bar.pp.jsm', 'foo.pp.jsm'],
|
EXTRA_PP_JS_MODULES=['bar.pp.jsm', 'foo.pp.jsm'],
|
||||||
FAIL_ON_WARNINGS=True,
|
FAIL_ON_WARNINGS=True,
|
||||||
|
FORCE_SHARED_LIB=True,
|
||||||
|
FORCE_STATIC_LIB=True,
|
||||||
GTEST_CSRCS=['test1.c', 'test2.c'],
|
GTEST_CSRCS=['test1.c', 'test2.c'],
|
||||||
GTEST_CMMSRCS=['test1.mm', 'test2.mm'],
|
GTEST_CMMSRCS=['test1.mm', 'test2.mm'],
|
||||||
GTEST_CPPSRCS=['test1.cpp', 'test2.cpp'],
|
GTEST_CPPSRCS=['test1.cpp', 'test2.cpp'],
|
||||||
HOST_CPPSRCS=['fans.cpp', 'tans.cpp'],
|
HOST_CPPSRCS=['fans.cpp', 'tans.cpp'],
|
||||||
HOST_CSRCS=['fans.c', 'tans.c'],
|
HOST_CSRCS=['fans.c', 'tans.c'],
|
||||||
HOST_LIBRARY_NAME='host_fans',
|
HOST_LIBRARY_NAME='host_fans',
|
||||||
|
IS_COMPONENT=True,
|
||||||
LIBRARY_NAME='lib_name',
|
LIBRARY_NAME='lib_name',
|
||||||
LIBS=['fans.lib', 'tans.lib'],
|
LIBS=['fans.lib', 'tans.lib'],
|
||||||
LIBXUL_LIBRARY=True,
|
LIBXUL_LIBRARY=True,
|
||||||
|
|
|
@ -184,15 +184,15 @@ function _do_quit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function _format_exception_stack(stack) {
|
function _format_exception_stack(stack) {
|
||||||
// frame is of the form "fname(args)@file:line"
|
// frame is of the form "fname@file:line"
|
||||||
let frame_regexp = new RegExp("(.*)\\(.*\\)@(.*):(\\d*)", "g");
|
let frame_regexp = new RegExp("(.*)@(.*):(\\d*)", "g");
|
||||||
return stack.split("\n").reduce(function(stack_msg, frame) {
|
return stack.split("\n").reduce(function(stack_msg, frame) {
|
||||||
if (frame) {
|
if (frame) {
|
||||||
let parts = frame_regexp.exec(frame);
|
let parts = frame_regexp.exec(frame);
|
||||||
if (parts) {
|
if (parts) {
|
||||||
return stack_msg + "JS frame :: " + parts[2] + " :: " +
|
let [ _, func, file, line ] = parts;
|
||||||
(parts[1] ? parts[1] : "anonymous") +
|
return stack_msg + "JS frame :: " + file + " :: " +
|
||||||
" :: line " + parts[3] + "\n";
|
(func || "anonymous") + " :: line " + line + "\n";
|
||||||
}
|
}
|
||||||
else { /* Could be a -e (command line string) style location. */
|
else { /* Could be a -e (command line string) style location. */
|
||||||
return stack_msg + "JS frame :: " + frame + "\n";
|
return stack_msg + "JS frame :: " + frame + "\n";
|
||||||
|
|
|
@ -345,7 +345,7 @@ INNER_ROBOCOP_PACKAGE=echo 'Testing is disabled - No Robocop for you'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef MOZ_OMX_PLUGIN
|
ifdef MOZ_OMX_PLUGIN
|
||||||
DIST_FILES += libomxplugin.so libomxplugingb.so libomxplugingb235.so libomxpluginhc.so libomxpluginsony.so libomxpluginfroyo.so libomxpluginjb-htc.so
|
DIST_FILES += libomxplugin.so libomxplugingb.so libomxplugingb235.so libomxpluginhc.so libomxpluginfroyo.so
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SO_LIBRARIES := $(filter %.so,$(DIST_FILES))
|
SO_LIBRARIES := $(filter %.so,$(DIST_FILES))
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче