Merge last PGO-green changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Ed Morley 2012-08-01 10:48:01 +01:00
commit e5de263e59
113 changed files with 2113 additions and 637 deletions

View File

@ -131,6 +131,7 @@ function startTest2() {
"onStateChange",
"onLocationChange",
"onSecurityChange",
"onSecurityChange",
"onStateChange"
];
gFrontNotifications = gAllNotifications;
@ -155,6 +156,7 @@ function startTest4() {
"onStateChange",
"onLocationChange",
"onSecurityChange",
"onSecurityChange",
"onStateChange"
];
gFrontNotifications = [];

View File

@ -47,8 +47,6 @@ public class RunCmdThread extends Thread
public void run() {
try {
int nIterations = 0;
SvrSocket.setSoTimeout(5000);
while (bListening)
{
@ -61,16 +59,6 @@ public class RunCmdThread extends Thread
}
catch (SocketTimeoutException toe)
{
if (++nIterations > 60)
{
nIterations = 0;
String sRet = SendPing("www.mozilla.org");
if (sRet.contains("3 received"))
handler.post(new doCancelNotification());
else
handler.post(new doSendNotification("SUTAgent - Network Connectivity Error", sRet));
sRet = null;
}
continue;
}
catch (IOException e)

View File

@ -0,0 +1,55 @@
#!/bin/python
import os
import simplejson
import sys
import subprocess
import urllib
import glob
def check_run(args):
r = subprocess.call(args)
assert r == 0
old_files = glob.glob('*.manifest') + ['tooltool.py', 'setup.sh']
for f in old_files:
try:
os.unlink(f)
except:
pass
urllib.urlretrieve('https://raw.github.com/jhford/tooltool/master/tooltool.py',
'tooltool.py')
urllib.urlretrieve('https://hg.mozilla.org/mozilla-central/raw-file/tip/build/unix/build-clang/setup.sh',
'setup.sh')
check_run(['python', 'tooltool.py', '-m', 'linux32.manifest', 'add',
'clang-linux32.tar.bz2', 'setup.sh'])
check_run(['python', 'tooltool.py', '-m', 'linux64.manifest', 'add',
'clang-linux64.tar.bz2', 'setup.sh'])
check_run(['python', 'tooltool.py', '-m', 'darwin.manifest', 'add',
'clang-darwin.tar.bz2', 'setup.sh'])
def key_sort(item):
item = item[0]
if item == 'size':
return 0
if item == 'digest':
return 1
if item == 'algorithm':
return 3
return 4
rev = os.path.basename(os.getcwd()).split('-')[1]
for platform in ['darwin', 'linux32', 'linux64']:
old_name = 'clang-' + platform + '.tar.bz2'
manifest = platform + '.manifest'
data = eval(file(manifest).read())
new_name = data[1]['digest']
data[1]['filename'] = 'clang.tar.bz2'
data = [{'clang_version' : 'r%s' % rev }] + data
out = file(manifest,'w')
simplejson.dump(data, out, indent=0, item_sort_key=key_sort)
out.write('\n')
os.rename(old_name, new_name)

View File

@ -2603,8 +2603,8 @@ GetRequestBody(ArrayBuffer* aArrayBuffer, nsIInputStream** aResult,
aContentType.SetIsVoid(true);
aCharset.Truncate();
PRInt32 length = aArrayBuffer->mLength;
char* data = reinterpret_cast<char*>(aArrayBuffer->mData);
PRInt32 length = aArrayBuffer->Length();
char* data = reinterpret_cast<char*>(aArrayBuffer->Data());
nsCOMPtr<nsIInputStream> stream;
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), data, length,

View File

@ -892,7 +892,7 @@ public:
WebGLfloat z, WebGLfloat w);
void Uniform1iv(WebGLUniformLocation* location, dom::Int32Array& arr) {
Uniform1iv_base(location, arr.mLength, arr.mData);
Uniform1iv_base(location, arr.Length(), arr.Data());
}
void Uniform1iv(WebGLUniformLocation* location,
const dom::Sequence<WebGLint>& arr) {
@ -902,7 +902,7 @@ public:
const WebGLint* data);
void Uniform2iv(WebGLUniformLocation* location, dom::Int32Array& arr) {
Uniform2iv_base(location, arr.mLength, arr.mData);
Uniform2iv_base(location, arr.Length(), arr.Data());
}
void Uniform2iv(WebGLUniformLocation* location,
const dom::Sequence<WebGLint>& arr) {
@ -912,7 +912,7 @@ public:
const WebGLint* data);
void Uniform3iv(WebGLUniformLocation* location, dom::Int32Array& arr) {
Uniform3iv_base(location, arr.mLength, arr.mData);
Uniform3iv_base(location, arr.Length(), arr.Data());
}
void Uniform3iv(WebGLUniformLocation* location,
const dom::Sequence<WebGLint>& arr) {
@ -922,7 +922,7 @@ public:
const WebGLint* data);
void Uniform4iv(WebGLUniformLocation* location, dom::Int32Array& arr) {
Uniform4iv_base(location, arr.mLength, arr.mData);
Uniform4iv_base(location, arr.Length(), arr.Data());
}
void Uniform4iv(WebGLUniformLocation* location,
const dom::Sequence<WebGLint>& arr) {
@ -932,7 +932,7 @@ public:
const WebGLint* data);
void Uniform1fv(WebGLUniformLocation* location, dom::Float32Array& arr) {
Uniform1fv_base(location, arr.mLength, arr.mData);
Uniform1fv_base(location, arr.Length(), arr.Data());
}
void Uniform1fv(WebGLUniformLocation* location,
const dom::Sequence<WebGLfloat>& arr) {
@ -942,7 +942,7 @@ public:
const WebGLfloat* data);
void Uniform2fv(WebGLUniformLocation* location, dom::Float32Array& arr) {
Uniform2fv_base(location, arr.mLength, arr.mData);
Uniform2fv_base(location, arr.Length(), arr.Data());
}
void Uniform2fv(WebGLUniformLocation* location,
const dom::Sequence<WebGLfloat>& arr) {
@ -952,7 +952,7 @@ public:
const WebGLfloat* data);
void Uniform3fv(WebGLUniformLocation* location, dom::Float32Array& arr) {
Uniform3fv_base(location, arr.mLength, arr.mData);
Uniform3fv_base(location, arr.Length(), arr.Data());
}
void Uniform3fv(WebGLUniformLocation* location,
const dom::Sequence<WebGLfloat>& arr) {
@ -962,7 +962,7 @@ public:
const WebGLfloat* data);
void Uniform4fv(WebGLUniformLocation* location, dom::Float32Array& arr) {
Uniform4fv_base(location, arr.mLength, arr.mData);
Uniform4fv_base(location, arr.Length(), arr.Data());
}
void Uniform4fv(WebGLUniformLocation* location,
const dom::Sequence<WebGLfloat>& arr) {
@ -974,7 +974,7 @@ public:
void UniformMatrix2fv(WebGLUniformLocation* location,
WebGLboolean transpose,
dom::Float32Array &value) {
UniformMatrix2fv_base(location, transpose, value.mLength, value.mData);
UniformMatrix2fv_base(location, transpose, value.Length(), value.Data());
}
void UniformMatrix2fv(WebGLUniformLocation* location,
WebGLboolean transpose,
@ -989,7 +989,7 @@ public:
void UniformMatrix3fv(WebGLUniformLocation* location,
WebGLboolean transpose,
dom::Float32Array &value) {
UniformMatrix3fv_base(location, transpose, value.mLength, value.mData);
UniformMatrix3fv_base(location, transpose, value.Length(), value.Data());
}
void UniformMatrix3fv(WebGLUniformLocation* location,
WebGLboolean transpose,
@ -1004,7 +1004,7 @@ public:
void UniformMatrix4fv(WebGLUniformLocation* location,
WebGLboolean transpose,
dom::Float32Array &value) {
UniformMatrix4fv_base(location, transpose, value.mLength, value.mData);
UniformMatrix4fv_base(location, transpose, value.Length(), value.Data());
}
void UniformMatrix4fv(WebGLUniformLocation* location,
WebGLboolean transpose,
@ -1027,7 +1027,7 @@ public:
WebGLfloat x2, WebGLfloat x3);
void VertexAttrib1fv(WebGLuint idx, dom::Float32Array &arr) {
VertexAttrib1fv_base(idx, arr.mLength, arr.mData);
VertexAttrib1fv_base(idx, arr.Length(), arr.Data());
}
void VertexAttrib1fv(WebGLuint idx, const dom::Sequence<WebGLfloat>& arr) {
VertexAttrib1fv_base(idx, arr.Length(), arr.Elements());
@ -1036,7 +1036,7 @@ public:
const WebGLfloat* ptr);
void VertexAttrib2fv(WebGLuint idx, dom::Float32Array &arr) {
VertexAttrib2fv_base(idx, arr.mLength, arr.mData);
VertexAttrib2fv_base(idx, arr.Length(), arr.Data());
}
void VertexAttrib2fv(WebGLuint idx, const dom::Sequence<WebGLfloat>& arr) {
VertexAttrib2fv_base(idx, arr.Length(), arr.Elements());
@ -1045,7 +1045,7 @@ public:
const WebGLfloat* ptr);
void VertexAttrib3fv(WebGLuint idx, dom::Float32Array &arr) {
VertexAttrib3fv_base(idx, arr.mLength, arr.mData);
VertexAttrib3fv_base(idx, arr.Length(), arr.Data());
}
void VertexAttrib3fv(WebGLuint idx, const dom::Sequence<WebGLfloat>& arr) {
VertexAttrib3fv_base(idx, arr.Length(), arr.Elements());
@ -1054,7 +1054,7 @@ public:
const WebGLfloat* ptr);
void VertexAttrib4fv(WebGLuint idx, dom::Float32Array &arr) {
VertexAttrib4fv_base(idx, arr.mLength, arr.mData);
VertexAttrib4fv_base(idx, arr.Length(), arr.Data());
}
void VertexAttrib4fv(WebGLuint idx, const dom::Sequence<WebGLfloat>& arr) {
VertexAttrib4fv_base(idx, arr.Length(), arr.Elements());

View File

@ -546,16 +546,16 @@ WebGLContext::BufferData(WebGLenum target, ArrayBuffer *data, WebGLenum usage)
MakeContextCurrent();
GLenum error = CheckedBufferData(target, data->mLength, data->mData, usage);
GLenum error = CheckedBufferData(target, data->Length(), data->Data(), usage);
if (error) {
GenerateWarning("bufferData generated error %s", ErrorName(error));
return;
}
boundBuffer->SetByteLength(data->mLength);
boundBuffer->SetByteLength(data->Length());
boundBuffer->InvalidateCachedMaxElements();
if (!boundBuffer->CopyDataIfElementArray(data->mData))
if (!boundBuffer->CopyDataIfElementArray(data->Data()))
return ErrorOutOfMemory("bufferData: out of memory");
}
@ -583,15 +583,15 @@ WebGLContext::BufferData(WebGLenum target, ArrayBufferView& data, WebGLenum usag
MakeContextCurrent();
GLenum error = CheckedBufferData(target, data.mLength, data.mData, usage);
GLenum error = CheckedBufferData(target, data.Length(), data.Data(), usage);
if (error) {
GenerateWarning("bufferData generated error %s", ErrorName(error));
return;
}
boundBuffer->SetByteLength(data.mLength);
boundBuffer->SetByteLength(data.Length());
boundBuffer->InvalidateCachedMaxElements();
if (!boundBuffer->CopyDataIfElementArray(data.mData))
if (!boundBuffer->CopyDataIfElementArray(data.Data()))
return ErrorOutOfMemory("bufferData: out of memory");
}
@ -654,7 +654,7 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
if (!boundBuffer)
return ErrorInvalidOperation("bufferData: no buffer bound!");
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data->mLength;
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data->Length();
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
@ -664,10 +664,10 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
MakeContextCurrent();
boundBuffer->CopySubDataIfElementArray(byteOffset, data->mLength, data->mData);
boundBuffer->CopySubDataIfElementArray(byteOffset, data->Length(), data->Data());
boundBuffer->InvalidateCachedMaxElements();
gl->fBufferSubData(target, byteOffset, data->mLength, data->mData);
gl->fBufferSubData(target, byteOffset, data->Length(), data->Data());
}
void
@ -693,7 +693,7 @@ WebGLContext::BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
if (!boundBuffer)
return ErrorInvalidOperation("bufferSubData: no buffer bound!");
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data.mLength;
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data.Length();
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
@ -703,10 +703,10 @@ WebGLContext::BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
MakeContextCurrent();
boundBuffer->CopySubDataIfElementArray(byteOffset, data.mLength, data.mData);
boundBuffer->CopySubDataIfElementArray(byteOffset, data.Length(), data.Data());
boundBuffer->InvalidateCachedMaxElements();
gl->fBufferSubData(target, byteOffset, data.mLength, data.mData);
gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
}
NS_IMETHODIMP
@ -3876,9 +3876,9 @@ WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width,
WebGLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
WebGLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
void* data = pixels->mData;
uint32_t dataByteLen = JS_GetTypedArrayByteLength(pixels->mObj, NULL);
int dataType = JS_GetTypedArrayType(pixels->mObj, NULL);
void* data = pixels->Data();
uint32_t dataByteLen = JS_GetTypedArrayByteLength(pixels->Obj(), NULL);
int dataType = JS_GetTypedArrayType(pixels->Obj(), NULL);
uint32_t channels = 0;
@ -5146,12 +5146,12 @@ WebGLContext::CompressedTexImage2D(WebGLenum target, WebGLint level, WebGLenum i
return;
}
uint32_t byteLength = view.mLength;
uint32_t byteLength = view.Length();
if (!ValidateCompressedTextureSize(level, internalformat, width, height, byteLength, "compressedTexImage2D")) {
return;
}
gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.mData);
gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.Data());
tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE);
}
@ -5207,7 +5207,7 @@ WebGLContext::CompressedTexSubImage2D(WebGLenum target, WebGLint level, WebGLint
return;
}
uint32_t byteLength = view.mLength;
uint32_t byteLength = view.Length();
if (!ValidateCompressedTextureSize(level, format, width, height, byteLength, "compressedTexSubImage2D")) {
return;
}
@ -5252,7 +5252,7 @@ WebGLContext::CompressedTexSubImage2D(WebGLenum target, WebGLint level, WebGLint
}
}
gl->fCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, byteLength, view.mData);
gl->fCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, byteLength, view.Data());
return;
}
@ -5742,9 +5742,9 @@ WebGLContext::TexImage2D(JSContext* cx, WebGLenum target, WebGLint level,
return;
return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type,
pixels ? pixels->mData : 0,
pixels ? pixels->mLength : 0,
pixels ? (int)JS_GetTypedArrayType(pixels->mObj, cx) : -1,
pixels ? pixels->Data() : 0,
pixels ? pixels->Length() : 0,
pixels ? (int)JS_GetTypedArrayType(pixels->Obj(), cx) : -1,
WebGLTexelConversions::Auto, false);
}
@ -5783,7 +5783,7 @@ WebGLContext::TexImage2D(JSContext* cx, WebGLenum target, WebGLint level,
Uint8ClampedArray arr(cx, pixels->GetDataObject());
return TexImage2D_base(target, level, internalformat, pixels->GetWidth(),
pixels->GetHeight(), 4*pixels->GetWidth(), 0,
format, type, arr.mData, arr.mLength, -1,
format, type, arr.Data(), arr.Length(), -1,
WebGLTexelConversions::RGBA8, false);
}
@ -5948,8 +5948,8 @@ WebGLContext::TexSubImage2D(JSContext* cx, WebGLenum target, WebGLint level,
return TexSubImage2D_base(target, level, xoffset, yoffset,
width, height, 0, format, type,
pixels->mData, pixels->mLength,
JS_GetTypedArrayType(pixels->mObj, cx),
pixels->Data(), pixels->Length(),
JS_GetTypedArrayType(pixels->Obj(), cx),
WebGLTexelConversions::Auto, false);
}
@ -5994,7 +5994,7 @@ WebGLContext::TexSubImage2D(JSContext* cx, WebGLenum target, WebGLint level,
return TexSubImage2D_base(target, level, xoffset, yoffset,
pixels->GetWidth(), pixels->GetHeight(),
4*pixels->GetWidth(), format, type,
arr.mData, arr.mLength,
arr.Data(), arr.Length(),
-1,
WebGLTexelConversions::RGBA8, false);
}

View File

@ -4352,7 +4352,7 @@ nsCanvasRenderingContext2DAzure::PutImageData(JSContext* cx,
error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
imageData->GetWidth(), imageData->GetHeight(),
arr.mData, arr.mLength, false, 0, 0, 0, 0);
arr.Data(), arr.Length(), false, 0, 0, 0, 0);
}
void
@ -4372,7 +4372,7 @@ nsCanvasRenderingContext2DAzure::PutImageData(JSContext* cx,
error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
imageData->GetWidth(), imageData->GetHeight(),
arr.mData, arr.mLength, true,
arr.Data(), arr.Length(), true,
JS_DoubleToInt32(dirtyX),
JS_DoubleToInt32(dirtyY),
JS_DoubleToInt32(dirtyWidth),

View File

@ -189,7 +189,7 @@ nsHTMLAudioElement::MozCurrentSampleOffset(PRUint64 *aRetVal)
if (position < 0) {
*aRetVal = 0;
} else {
*aRetVal = mAudioStream->GetPositionInFrames() * mChannels;
*aRetVal = position * mChannels;
}
return NS_OK;
}

View File

@ -1653,11 +1653,10 @@ nsresult nsOggReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
}
else {
// Page is for a stream we don't know about (possibly a chained
// ogg), return an error.
//
// XXX Invalid cast of PageSyncResult to nsresult -- this has numeric
// value 1 and will pass an NS_SUCCEEDED() check (bug 778105)
return (nsresult)PAGE_SYNC_ERROR;
// ogg), return OK to abort the finding any further ranges. This
// prevents us searching through the rest of the media when we
// may not be able to extract timestamps from it.
return NS_OK;
}
}

View File

@ -516,6 +516,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
#include "BluetoothAdapter.h"
#include "BluetoothDevice.h"
#include "BluetoothDeviceEvent.h"
#include "BluetoothPropertyEvent.h"
#endif
#include "nsIDOMNavigatorSystemMessages.h"
@ -1670,6 +1671,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(BluetoothDeviceEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(BluetoothPropertyEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
#endif
NS_DEFINE_CLASSINFO_DATA(CameraManager, nsDOMGenericSH,
@ -4467,6 +4470,11 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothDeviceEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(BluetoothPropertyEvent, nsIDOMBluetoothPropertyEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothPropertyEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
DOM_CLASSINFO_MAP_END
#endif
DOM_CLASSINFO_MAP_BEGIN(CameraManager, nsIDOMCameraManager)

View File

@ -524,6 +524,7 @@ DOMCI_CLASS(BluetoothManager)
DOMCI_CLASS(BluetoothAdapter)
DOMCI_CLASS(BluetoothDevice)
DOMCI_CLASS(BluetoothDeviceEvent)
DOMCI_CLASS(BluetoothPropertyEvent)
#endif
DOMCI_CLASS(CameraManager)

View File

@ -110,6 +110,9 @@ static PRLogModuleInfo* gJSDiagnostics;
// Maximum amount of time that should elapse between incremental GC slices
#define NS_INTERSLICE_GC_DELAY 100 // ms
// If we haven't painted in 100ms, we allow for a longer GC budget
#define NS_INTERSLICE_GC_BUDGET 40 // ms
// The amount of time we wait between a request to CC (after GC ran)
// and doing the actual CC.
#define NS_CC_DELAY 6000 // ms
@ -2909,11 +2912,14 @@ void
nsJSContext::GarbageCollectNow(js::gcreason::Reason aReason,
IsIncremental aIncremental,
IsCompartment aCompartment,
IsShrinking aShrinking)
IsShrinking aShrinking,
int64_t aSliceMillis)
{
NS_TIME_FUNCTION_MIN(1.0);
SAMPLE_LABEL("GC", "GarbageCollectNow");
MOZ_ASSERT_IF(aSliceMillis, aIncremental == IncrementalGC);
KillGCTimer();
KillShrinkGCBuffersTimer();
@ -2933,7 +2939,7 @@ nsJSContext::GarbageCollectNow(js::gcreason::Reason aReason,
if (sCCLockedOut && aIncremental == IncrementalGC) {
// We're in the middle of incremental GC. Do another slice.
js::PrepareForIncrementalGC(nsJSRuntime::sRuntime);
js::IncrementalGC(nsJSRuntime::sRuntime, aReason);
js::IncrementalGC(nsJSRuntime::sRuntime, aReason, aSliceMillis);
return;
}
@ -2954,7 +2960,7 @@ nsJSContext::GarbageCollectNow(js::gcreason::Reason aReason,
}
if (js::IsGCScheduled(nsJSRuntime::sRuntime)) {
if (aIncremental == IncrementalGC) {
js::IncrementalGC(nsJSRuntime::sRuntime, aReason);
js::IncrementalGC(nsJSRuntime::sRuntime, aReason, aSliceMillis);
} else {
js::GCForReason(nsJSRuntime::sRuntime, aReason);
}
@ -2967,7 +2973,7 @@ nsJSContext::GarbageCollectNow(js::gcreason::Reason aReason,
}
js::PrepareForFullGC(nsJSRuntime::sRuntime);
if (aIncremental == IncrementalGC) {
js::IncrementalGC(nsJSRuntime::sRuntime, aReason);
js::IncrementalGC(nsJSRuntime::sRuntime, aReason, aSliceMillis);
} else {
js::GCForReason(nsJSRuntime::sRuntime, aReason);
}
@ -3215,15 +3221,23 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
sNeedsFullCC = false;
}
// static
void
InterSliceGCTimerFired(nsITimer *aTimer, void *aClosure)
{
NS_RELEASE(sInterSliceGCTimer);
nsJSContext::GarbageCollectNow(js::gcreason::INTER_SLICE_GC,
nsJSContext::IncrementalGC,
nsJSContext::CompartmentGC,
nsJSContext::NonShrinkingGC,
NS_INTERSLICE_GC_BUDGET);
}
// static
void
GCTimerFired(nsITimer *aTimer, void *aClosure)
{
if (aTimer == sGCTimer) {
NS_RELEASE(sGCTimer);
} else {
NS_RELEASE(sInterSliceGCTimer);
}
NS_RELEASE(sGCTimer);
uintptr_t reason = reinterpret_cast<uintptr_t>(aClosure);
nsJSContext::GarbageCollectNow(static_cast<js::gcreason::Reason>(reason),
@ -3546,9 +3560,8 @@ DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescrip
if (aProgress == js::GC_SLICE_END) {
nsJSContext::KillInterSliceGCTimer();
CallCreateInstance("@mozilla.org/timer;1", &sInterSliceGCTimer);
js::gcreason::Reason reason = js::gcreason::INTER_SLICE_GC;
sInterSliceGCTimer->InitWithFuncCallback(GCTimerFired,
reinterpret_cast<void *>(reason),
sInterSliceGCTimer->InitWithFuncCallback(InterSliceGCTimerFired,
NULL,
NS_INTERSLICE_GC_DELAY,
nsITimer::TYPE_ONE_SHOT);
}

View File

@ -164,7 +164,8 @@ public:
static void GarbageCollectNow(js::gcreason::Reason reason,
IsIncremental aIncremental = NonIncrementalGC,
IsCompartment aCompartment = NonCompartmentGC,
IsShrinking aShrinking = NonShrinkingGC);
IsShrinking aShrinking = NonShrinkingGC,
int64_t aSliceMillis = 0);
static void ShrinkGCBuffersNow();
// If aExtraForgetSkippableCalls is -1, forgetSkippable won't be
// called even if the previous collection was GC.

View File

@ -1972,19 +1972,13 @@ for (uint32_t i = 0; i < length; ++i) {
"arraybuffer views because making sure all the "
"objects are properly rooted is hard")
name = type.name
if type.isArrayBuffer():
jsname = "ArrayBufferObject"
elif type.isArrayBufferView():
jsname = "ArrayBufferViewObject"
else:
jsname = type.name
# By default, we use a Maybe<> to hold our typed array. And in the optional
# non-nullable case we want to pass Optional<TypedArray> to consumers, not
# Optional<NonNull<TypedArray> >, so jump though some hoops to do that.
holderType = "Maybe<%s>" % name
constructLoc = "${holderName}"
constructMethod = "construct"
constructInternal = "ref"
if type.nullable():
if isOptional:
declType = "const Optional<" + name + "*>"
@ -1997,15 +1991,16 @@ for (uint32_t i = 0; i < length; ++i) {
holderType = None
constructLoc = "(const_cast<Optional<" + name + ">& >(${declName}))"
constructMethod = "Construct"
constructInternal = "Value"
else:
declType = "NonNull<" + name + ">"
template = (
"if (!JS_Is%s(&${val}.toObject(), cx)) {\n"
"%s.%s(cx, &${val}.toObject());\n"
"if (!%s.%s().inited()) {\n"
"%s" # No newline here because onFailure() handles that
"}\n"
"%s.%s(cx, &${val}.toObject());\n" %
(jsname, CGIndenter(onFailure(failureCode, descriptorProvider.workers)).define(),
constructLoc, constructMethod))
"}\n" %
(constructLoc, constructMethod, constructLoc, constructInternal,
CGIndenter(onFailure(failureCode, descriptorProvider.workers)).define()))
nullableTarget = ""
if type.nullable():
if isOptional:

View File

@ -18,31 +18,50 @@ namespace dom {
* a subclass of the base class that supports creation of a relevant typed array
* or array buffer object.
*/
template<typename T, typename U,
U* GetData(JSObject*, JSContext*),
uint32_t GetLength(JSObject*, JSContext*)>
template<typename T,
JSObject* UnboxArray(JSContext*, JSObject*, uint32_t*, T**)>
struct TypedArray_base {
TypedArray_base(JSContext* cx, JSObject* obj) :
mData(static_cast<T*>(GetData(obj, cx))),
mLength(GetLength(obj, cx)),
mObj(obj)
{}
TypedArray_base(JSContext* cx, JSObject* obj)
{
mObj = UnboxArray(cx, obj, &mLength, &mData);
}
T* const mData;
const uint32_t mLength;
JSObject* const mObj;
private:
T* mData;
uint32_t mLength;
JSObject* mObj;
public:
inline bool inited() const {
return !!mObj;
}
inline T *Data() const {
MOZ_ASSERT(inited());
return mData;
}
inline uint32_t Length() const {
MOZ_ASSERT(inited());
return mLength;
}
inline JSObject *Obj() const {
MOZ_ASSERT(inited());
return mObj;
}
};
template<typename T, typename U,
U* GetData(JSObject*, JSContext*),
uint32_t GetLength(JSObject*, JSContext*),
template<typename T,
T* GetData(JSObject*, JSContext*),
JSObject* UnboxArray(JSContext*, JSObject*, uint32_t*, T**),
JSObject* CreateNew(JSContext*, uint32_t)>
struct TypedArray : public TypedArray_base<T,U,GetData,GetLength> {
struct TypedArray : public TypedArray_base<T,UnboxArray> {
TypedArray(JSContext* cx, JSObject* obj) :
TypedArray_base<T,U,GetData,GetLength>(cx, obj)
TypedArray_base<T,UnboxArray>(cx, obj)
{}
static inline JSObject*
Create(JSContext* cx, nsWrapperCache* creator, uint32_t length,
T* data = NULL) {
@ -65,38 +84,37 @@ struct TypedArray : public TypedArray_base<T,U,GetData,GetLength> {
}
};
typedef TypedArray<int8_t, int8_t, JS_GetInt8ArrayData, JS_GetTypedArrayLength,
typedef TypedArray<int8_t, JS_GetInt8ArrayData, JS_GetObjectAsInt8Array,
JS_NewInt8Array>
Int8Array;
typedef TypedArray<uint8_t, uint8_t, JS_GetUint8ArrayData,
JS_GetTypedArrayLength, JS_NewUint8Array>
typedef TypedArray<uint8_t, JS_GetUint8ArrayData,
JS_GetObjectAsUint8Array, JS_NewUint8Array>
Uint8Array;
typedef TypedArray<uint8_t, uint8_t, JS_GetUint8ClampedArrayData,
JS_GetTypedArrayLength, JS_NewUint8ClampedArray>
typedef TypedArray<uint8_t, JS_GetUint8ClampedArrayData,
JS_GetObjectAsUint8ClampedArray, JS_NewUint8ClampedArray>
Uint8ClampedArray;
typedef TypedArray<int16_t, int16_t, JS_GetInt16ArrayData,
JS_GetTypedArrayLength, JS_NewInt16Array>
typedef TypedArray<int16_t, JS_GetInt16ArrayData,
JS_GetObjectAsInt16Array, JS_NewInt16Array>
Int16Array;
typedef TypedArray<uint16_t, uint16_t, JS_GetUint16ArrayData,
JS_GetTypedArrayLength, JS_NewUint16Array>
typedef TypedArray<uint16_t, JS_GetUint16ArrayData,
JS_GetObjectAsUint16Array, JS_NewUint16Array>
Uint16Array;
typedef TypedArray<int32_t, int32_t, JS_GetInt32ArrayData,
JS_GetTypedArrayLength, JS_NewInt32Array>
typedef TypedArray<int32_t, JS_GetInt32ArrayData,
JS_GetObjectAsInt32Array, JS_NewInt32Array>
Int32Array;
typedef TypedArray<uint32_t, uint32_t, JS_GetUint32ArrayData,
JS_GetTypedArrayLength, JS_NewUint32Array>
typedef TypedArray<uint32_t, JS_GetUint32ArrayData,
JS_GetObjectAsUint32Array, JS_NewUint32Array>
Uint32Array;
typedef TypedArray<float, float, JS_GetFloat32ArrayData, JS_GetTypedArrayLength,
JS_NewFloat32Array>
typedef TypedArray<float, JS_GetFloat32ArrayData,
JS_GetObjectAsFloat32Array, JS_NewFloat32Array>
Float32Array;
typedef TypedArray<double, double, JS_GetFloat64ArrayData,
JS_GetTypedArrayLength, JS_NewFloat64Array>
typedef TypedArray<double, JS_GetFloat64ArrayData,
JS_GetObjectAsFloat64Array, JS_NewFloat64Array>
Float64Array;
typedef TypedArray_base<uint8_t, void, JS_GetArrayBufferViewData,
JS_GetArrayBufferViewByteLength>
typedef TypedArray_base<uint8_t, JS_GetObjectAsArrayBufferView>
ArrayBufferView;
typedef TypedArray<uint8_t, uint8_t, JS_GetArrayBufferData,
JS_GetArrayBufferByteLength, JS_NewArrayBuffer>
typedef TypedArray<uint8_t, JS_GetArrayBufferData,
JS_GetObjectAsArrayBuffer, JS_NewArrayBuffer>
ArrayBuffer;
} // namespace dom

View File

@ -8,15 +8,18 @@
#include "BluetoothAdapter.h"
#include "BluetoothDevice.h"
#include "BluetoothDeviceEvent.h"
#include "BluetoothPropertyEvent.h"
#include "BluetoothService.h"
#include "BluetoothTypes.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothUtils.h"
#include "nsDOMClassInfo.h"
#include "nsDOMEvent.h"
#include "nsThreadUtils.h"
#include "nsXPCOMCIDInternal.h"
#include "nsIDOMDOMRequest.h"
#include "nsContentUtils.h"
#include "mozilla/LazyIdleThread.h"
#include "mozilla/Util.h"
@ -29,8 +32,15 @@ DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsDeviceAddresses)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(devicefound)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(devicedisappeared)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(propertychanged)
@ -38,6 +48,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
tmp->Unroot();
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(devicefound)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(devicedisappeared)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(propertychanged)
@ -51,36 +62,15 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
class GetPropertiesTask : public BluetoothReplyRunnable
BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aOwner, const nsAString& aPath)
: BluetoothPropertyContainer(BluetoothObjectType::TYPE_ADAPTER)
, mJsUuids(nullptr)
, mJsDeviceAddresses(nullptr)
, mIsRooted(false)
{
public:
GetPropertiesTask(BluetoothAdapter* aAdapter, nsIDOMDOMRequest* aReq) :
BluetoothReplyRunnable(aReq),
mAdapterPtr(aAdapter)
{
}
bool
ParseSuccessfulReply(jsval* aValue)
{
const InfallibleTArray<BluetoothNamedValue>& values =
mReply->get_BluetoothReplySuccess().value().get_ArrayOfBluetoothNamedValue();
for (uint32_t i = 0; i < values.Length(); ++i) {
mAdapterPtr->SetPropertyByValue(values[i]);
}
*aValue = JSVAL_VOID;
return true;
}
void
ReleaseMembers()
{
BluetoothReplyRunnable::ReleaseMembers();
mAdapterPtr = nullptr;
}
private:
nsRefPtr<BluetoothAdapter> mAdapterPtr;
};
BindToOwner(aOwner);
mPath = aPath;
}
BluetoothAdapter::~BluetoothAdapter()
{
@ -91,6 +81,27 @@ BluetoothAdapter::~BluetoothAdapter()
NS_WARNING("Failed to unregister object with observer!");
}
}
Unroot();
}
void
BluetoothAdapter::Unroot()
{
if (!mIsRooted) {
return;
}
NS_DROP_JS_OBJECTS(this, BluetoothAdapter);
mIsRooted = false;
}
void
BluetoothAdapter::Root()
{
if (mIsRooted) {
return;
}
NS_HOLD_JS_OBJECTS(this, BluetoothAdapter);
mIsRooted = true;
}
void
@ -102,10 +113,14 @@ BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
mName = value.get_nsString();
} else if (name.EqualsLiteral("Address")) {
mAddress = value.get_nsString();
} else if (name.EqualsLiteral("Path")) {
mPath = value.get_nsString();
} else if (name.EqualsLiteral("Enabled")) {
mEnabled = value.get_bool();
} else if (name.EqualsLiteral("Discoverable")) {
mDiscoverable = value.get_bool();
} else if (name.EqualsLiteral("Discovering")) {
mDiscovering = value.get_bool();
} else if (name.EqualsLiteral("Pairable")) {
mPairable = value.get_bool();
} else if (name.EqualsLiteral("Powered")) {
@ -118,6 +133,36 @@ BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
mClass = value.get_uint32_t();
} else if (name.EqualsLiteral("UUIDs")) {
mUuids = value.get_ArrayOfnsString();
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
if (sc) {
rv =
StringArrayToJSArray(sc->GetNativeContext(),
sc->GetNativeGlobal(), mUuids, &mJsUuids);
if (NS_FAILED(rv)) {
NS_WARNING("Cannot set JS UUIDs object!");
return;
}
Root();
} else {
NS_WARNING("Could not get context!");
}
} else if (name.EqualsLiteral("Devices")) {
mDeviceAddresses = value.get_ArrayOfnsString();
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
if (sc) {
rv =
StringArrayToJSArray(sc->GetNativeContext(),
sc->GetNativeGlobal(), mUuids, &mJsDeviceAddresses);
if (NS_FAILED(rv)) {
NS_WARNING("Cannot set JS Devices Addresses object!");
return;
}
Root();
} else {
NS_WARNING("Could not get context!");
}
} else {
#ifdef DEBUG
nsCString warningMsg;
@ -136,11 +181,15 @@ BluetoothAdapter::Create(nsPIDOMWindow* aOwner, const nsAString& aPath)
NS_ASSERTION(!aPath.IsEmpty(), "Adapter created with empty path!");
BluetoothService* bs = BluetoothService::Get();
MOZ_ASSERT(bs);
if (!bs) {
NS_WARNING("BluetoothService not available!");
return nullptr;
}
nsRefPtr<BluetoothAdapter> adapter = new BluetoothAdapter(aPath);
adapter->BindToOwner(aOwner);
if (NS_FAILED(bs->RegisterBluetoothSignalHandler(aPath, adapter))) {
nsRefPtr<BluetoothAdapter> adapter = new BluetoothAdapter(aOwner, aPath);
nsString path;
path = adapter->GetPath();
if (NS_FAILED(bs->RegisterBluetoothSignalHandler(path, adapter))) {
NS_WARNING("Failed to register object with observer!");
return nullptr;
}
@ -151,9 +200,21 @@ void
BluetoothAdapter::Notify(const BluetoothSignal& aData)
{
if (aData.name().EqualsLiteral("DeviceFound")) {
nsRefPtr<BluetoothDevice> d = BluetoothDevice::Create(GetOwner(), aData);
nsRefPtr<BluetoothDevice> d = BluetoothDevice::Create(GetOwner(), mPath, aData.value());
nsRefPtr<BluetoothDeviceEvent> e = BluetoothDeviceEvent::Create(d);
e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("devicefound"));
} else if (aData.name().EqualsLiteral("PropertyChanged")) {
// Get BluetoothNamedValue, make sure array length is 1
InfallibleTArray<BluetoothNamedValue> arr = aData.value().get_ArrayOfBluetoothNamedValue();
if (arr.Length() != 1) {
// This really should not happen
NS_ERROR("Got more than one property in a change message!");
return;
}
BluetoothNamedValue v = arr[0];
SetPropertyByValue(v);
nsRefPtr<BluetoothPropertyEvent> e = BluetoothPropertyEvent::Create(v.name());
e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("propertychanged"));
} else {
#ifdef DEBUG
nsCString warningMsg;
@ -168,10 +229,12 @@ nsresult
BluetoothAdapter::StartStopDiscovery(bool aStart, nsIDOMDOMRequest** aRequest)
{
BluetoothService* bs = BluetoothService::Get();
MOZ_ASSERT(bs);
if (!bs) {
NS_WARNING("BluetoothService not available!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
if (!rs) {
NS_WARNING("No DOMRequest Service!");
return NS_ERROR_FAILURE;
@ -268,10 +331,66 @@ BluetoothAdapter::GetDiscoverableTimeout(PRUint32* aDiscoverableTimeout)
NS_IMETHODIMP
BluetoothAdapter::GetDevices(JSContext* aCx, jsval* aDevices)
{
NS_WARNING("GetDevices not yet implemented.");
if (mJsDeviceAddresses) {
aDevices->setObject(*mJsDeviceAddresses);
}
else {
NS_WARNING("UUIDs not yet set!\n");
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
BluetoothAdapter::GetUuids(JSContext* aCx, jsval* aValue)
{
if (mJsUuids) {
aValue->setObject(*mJsUuids);
}
else {
NS_WARNING("UUIDs not yet set!\n");
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
BluetoothAdapter::SetName(const nsAString& aName,
nsIDOMDOMRequest** aRequest)
{
if (mName.Equals(aName)) {
return NS_OK;
}
nsString name(aName);
BluetoothValue value(name);
BluetoothNamedValue property(NS_LITERAL_STRING("Name"), value);
return SetProperty(GetOwner(), property, aRequest);
}
NS_IMETHODIMP
BluetoothAdapter::SetDiscoverable(const bool aDiscoverable,
nsIDOMDOMRequest** aRequest)
{
if (aDiscoverable == mDiscoverable) {
return NS_OK;
}
BluetoothValue value(aDiscoverable);
BluetoothNamedValue property(NS_LITERAL_STRING("Discoverable"), value);
return SetProperty(GetOwner(), property, aRequest);
}
NS_IMETHODIMP
BluetoothAdapter::SetDiscoverableTimeout(const PRUint32 aDiscoverableTimeout,
nsIDOMDOMRequest** aRequest)
{
if (aDiscoverableTimeout == mDiscoverableTimeout) {
return NS_OK;
}
BluetoothValue value(aDiscoverableTimeout);
BluetoothNamedValue property(NS_LITERAL_STRING("DiscoverableTimeout"), value);
return SetProperty(GetOwner(), property, aRequest);
}
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, propertychanged)
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicefound)
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicedisappeared)

View File

@ -8,6 +8,7 @@
#define mozilla_dom_bluetooth_bluetoothadapter_h__
#include "BluetoothCommon.h"
#include "BluetoothPropertyContainer.h"
#include "nsCOMPtr.h"
#include "nsDOMEventTargetHelper.h"
#include "nsIDOMBluetoothAdapter.h"
@ -23,6 +24,7 @@ class BluetoothNamedValue;
class BluetoothAdapter : public nsDOMEventTargetHelper
, public nsIDOMBluetoothAdapter
, public BluetoothSignalObserver
, public BluetoothPropertyContainer
{
public:
NS_DECL_ISUPPORTS_INHERITED
@ -30,8 +32,9 @@ public:
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
static already_AddRefed<BluetoothAdapter>
Create(nsPIDOMWindow* aOwner, const nsAString& name);
@ -50,23 +53,18 @@ public:
return ToIDOMEventTarget();
}
nsresult GetProperties();
void SetPropertyByValue(const BluetoothNamedValue& aValue);
void Unroot();
virtual void SetPropertyByValue(const BluetoothNamedValue& aValue);
private:
BluetoothAdapter(const nsAString& aPath) : mPath(aPath)
{
}
BluetoothAdapter(nsPIDOMWindow* aOwner, const nsAString& aPath);
~BluetoothAdapter();
nsresult SetProperty(const BluetoothNamedValue& aValue,
nsIDOMDOMRequest** aRequest);
void Root();
nsresult StartStopDiscovery(bool aStart, nsIDOMDOMRequest** aRequest);
nsString mAddress;
nsString mName;
nsString mPath;
bool mEnabled;
bool mDiscoverable;
bool mDiscovering;
@ -77,7 +75,10 @@ private:
PRUint32 mClass;
nsTArray<nsString> mDeviceAddresses;
nsTArray<nsString> mUuids;
JSObject* mJsUuids;
JSObject* mJsDeviceAddresses;
bool mIsRooted;
NS_DECL_EVENT_HANDLER(propertychanged)
NS_DECL_EVENT_HANDLER(devicefound)
NS_DECL_EVENT_HANDLER(devicedisappeared)

View File

@ -25,6 +25,15 @@ BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSignal;
typedef mozilla::Observer<BluetoothSignal> BluetoothSignalObserver;
// Enums for object types, currently used for shared function lookups
// (get/setproperty, etc...). Possibly discernable via dbus paths, but this
// method is future-proofed for platform independence.
enum BluetoothObjectType {
TYPE_MANAGER = 0,
TYPE_ADAPTER = 1,
TYPE_DEVICE = 2
};
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_bluetoothcommon_h__

View File

@ -6,9 +6,15 @@
#include "base/basictypes.h"
#include "BluetoothDevice.h"
#include "BluetoothPropertyEvent.h"
#include "BluetoothTypes.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#include "nsIDOMDOMRequest.h"
#include "nsDOMClassInfo.h"
#include "nsContentUtils.h"
USING_BLUETOOTH_NAMESPACE
@ -16,13 +22,20 @@ DOMCI_DATA(BluetoothDevice, BluetoothDevice)
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothDevice,
nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothDevice,
nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(propertychanged)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDevice,
nsDOMEventTargetHelper)
tmp->Unroot();
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(propertychanged)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -34,15 +47,52 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(BluetoothDevice, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(BluetoothDevice, nsDOMEventTargetHelper)
BluetoothDevice::BluetoothDevice(const BluetoothSignal& aSignal)
BluetoothDevice::BluetoothDevice(nsPIDOMWindow* aOwner,
const nsAString& aAdapterPath,
const BluetoothValue& aValue) :
BluetoothPropertyContainer(BluetoothObjectType::TYPE_DEVICE),
mJsUuids(nullptr),
mAdapterPath(aAdapterPath),
mIsRooted(false)
{
BindToOwner(aOwner);
const InfallibleTArray<BluetoothNamedValue>& values =
aSignal.value().get_ArrayOfBluetoothNamedValue();
aValue.get_ArrayOfBluetoothNamedValue();
for (uint32_t i = 0; i < values.Length(); ++i) {
SetPropertyByValue(values[i]);
}
}
BluetoothDevice::~BluetoothDevice()
{
BluetoothService* bs = BluetoothService::Get();
// bs can be null on shutdown, where destruction might happen.
if (bs) {
if (NS_FAILED(bs->UnregisterBluetoothSignalHandler(mPath, this))) {
NS_WARNING("Failed to unregister object with observer!");
}
}
Unroot();
}
void
BluetoothDevice::Root()
{
if (!mIsRooted) {
NS_HOLD_JS_OBJECTS(this, BluetoothDevice);
mIsRooted = true;
}
}
void
BluetoothDevice::Unroot()
{
if (mIsRooted) {
NS_DROP_JS_OBJECTS(this, BluetoothDevice);
mIsRooted = false;
}
}
void
BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
{
@ -52,6 +102,13 @@ BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
mName = value.get_nsString();
} else if (name.EqualsLiteral("Address")) {
mAddress = value.get_nsString();
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
NS_WARNING("BluetoothService not available!");
return;
}
// We can't actually set up our path until we know our address
bs->GetDevicePath(mAdapterPath, mAddress, mPath);
} else if (name.EqualsLiteral("Class")) {
mClass = value.get_uint32_t();
} else if (name.EqualsLiteral("Connected")) {
@ -60,8 +117,22 @@ BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
mPaired = value.get_bool();
} else if (name.EqualsLiteral("UUIDs")) {
mUuids = value.get_ArrayOfnsString();
} else {
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
if (sc) {
rv =
StringArrayToJSArray(sc->GetNativeContext(),
sc->GetNativeGlobal(), mUuids, &mJsUuids);
if (NS_FAILED(rv)) {
NS_WARNING("Cannot set JS UUIDs object!");
return;
}
Root();
} else {
NS_WARNING("Could not get context!");
}
#ifdef DEBUG
} else {
nsCString warningMsg;
warningMsg.AssignLiteral("Not handling device property: ");
warningMsg.Append(NS_ConvertUTF16toUTF8(name));
@ -72,13 +143,46 @@ BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
// static
already_AddRefed<BluetoothDevice>
BluetoothDevice::Create(nsPIDOMWindow* aOwner, const BluetoothSignal& aSignal)
BluetoothDevice::Create(nsPIDOMWindow* aOwner,
const nsAString& aAdapterPath,
const BluetoothValue& aValue)
{
nsRefPtr<BluetoothDevice> device = new BluetoothDevice(aSignal);
device->BindToOwner(device);
// Make sure we at least have a service
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
NS_WARNING("BluetoothService not available!");
return nullptr;
}
nsRefPtr<BluetoothDevice> device = new BluetoothDevice(aOwner, aAdapterPath,
aValue);
if (NS_FAILED(bs->RegisterBluetoothSignalHandler(device->mPath, device))) {
NS_WARNING("Failed to register object with observer!");
return nullptr;
}
return device.forget();
}
void
BluetoothDevice::Notify(const BluetoothSignal& aData)
{
if (aData.name().EqualsLiteral("PropertyChanged")) {
// Get BluetoothNamedValue, make sure array length is 1
BluetoothNamedValue v = aData.value().get_ArrayOfBluetoothNamedValue()[0];
nsString name = v.name();
SetPropertyByValue(v);
nsRefPtr<BluetoothPropertyEvent> e = BluetoothPropertyEvent::Create(name);
e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("propertychanged"));
} else {
#ifdef DEBUG
nsCString warningMsg;
warningMsg.AssignLiteral("Not handling device signal: ");
warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
NS_WARNING(warningMsg.get());
#endif
}
}
NS_IMETHODIMP
BluetoothDevice::GetAddress(nsAString& aAddress)
{
@ -114,4 +218,16 @@ BluetoothDevice::GetConnected(bool* aConnected)
return NS_OK;
}
NS_IMETHODIMP
BluetoothDevice::GetUuids(JSContext* aCx, jsval* aUuids)
{
if (mJsUuids) {
aUuids->setObject(*mJsUuids);
} else {
NS_WARNING("UUIDs not yet set!\n");
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMPL_EVENT_HANDLER(BluetoothDevice, propertychanged)

View File

@ -8,17 +8,23 @@
#define mozilla_dom_bluetooth_bluetoothdevice_h__
#include "BluetoothCommon.h"
#include "BluetoothPropertyContainer.h"
#include "nsDOMEventTargetHelper.h"
#include "nsIDOMBluetoothDevice.h"
#include "nsString.h"
class nsIDOMDOMRequest;
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothNamedValue;
class BluetoothValue;
class BluetoothSignal;
class BluetoothDevice : public nsDOMEventTargetHelper
, public nsIDOMBluetoothDevice
, public BluetoothSignalObserver
, public BluetoothPropertyContainer
{
public:
NS_DECL_ISUPPORTS_INHERITED
@ -26,11 +32,14 @@ public:
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothDevice,
nsDOMEventTargetHelper)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(BluetoothDevice,
nsDOMEventTargetHelper)
static already_AddRefed<BluetoothDevice>
Create(nsPIDOMWindow* aOwner, const BluetoothSignal& aSignal);
Create(nsPIDOMWindow* aOwner, const nsAString& aAdapterPath,
const BluetoothValue& aValue);
void Notify(const BluetoothSignal& aParam);
nsIDOMEventTarget*
ToIDOMEventTarget() const
@ -44,17 +53,25 @@ public:
{
return ToIDOMEventTarget();
}
private:
BluetoothDevice(const BluetoothSignal& aSignal);
~BluetoothDevice() {}
void SetPropertyByValue(const BluetoothNamedValue& aValue);
void Unroot();
private:
BluetoothDevice(nsPIDOMWindow* aOwner, const nsAString& aAdapterPath,
const BluetoothValue& aValue);
~BluetoothDevice();
void Root();
JSObject* mJsUuids;
nsString mAdapterPath;
nsString mAddress;
nsString mName;
PRUint32 mClass;
bool mConnected;
bool mPaired;
bool mIsRooted;
nsTArray<nsString> mUuids;
NS_DECL_EVENT_HANDLER(propertychanged)

View File

@ -8,6 +8,7 @@
#include "BluetoothDeviceEvent.h"
#include "BluetoothTypes.h"
#include "BluetoothDevice.h"
#include "nsIDOMDOMRequest.h"
#include "nsDOMClassInfo.h"

View File

@ -144,10 +144,11 @@ private:
};
BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow) :
BluetoothPropertyContainer(BluetoothObjectType::TYPE_MANAGER),
mEnabled(false)
{
BindToOwner(aWindow);
mName.AssignLiteral("/");
mPath.AssignLiteral("/");
}
BluetoothManager::~BluetoothManager()
@ -155,20 +156,34 @@ BluetoothManager::~BluetoothManager()
BluetoothService* bs = BluetoothService::Get();
// We can be null on shutdown, where this might happen
if (bs) {
if (NS_FAILED(bs->UnregisterBluetoothSignalHandler(mName, this))) {
if (NS_FAILED(bs->UnregisterBluetoothSignalHandler(mPath, this))) {
NS_WARNING("Failed to unregister object with observer!");
}
}
}
void
BluetoothManager::SetPropertyByValue(const BluetoothNamedValue& aValue)
{
#ifdef DEBUG
const nsString& name = aValue.name();
nsCString warningMsg;
warningMsg.AssignLiteral("Not handling manager property: ");
warningMsg.Append(NS_ConvertUTF16toUTF8(name));
NS_WARNING(warningMsg.get());
#endif
}
NS_IMETHODIMP
BluetoothManager::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
{
BluetoothService* bs = BluetoothService::Get();
MOZ_ASSERT(bs);
if (!bs) {
NS_WARNING("BluetoothService not available!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
if (!rs) {
NS_WARNING("No DOMRequest Service!");
return NS_ERROR_FAILURE;
@ -208,7 +223,10 @@ NS_IMETHODIMP
BluetoothManager::GetDefaultAdapter(nsIDOMDOMRequest** aAdapter)
{
BluetoothService* bs = BluetoothService::Get();
MOZ_ASSERT(bs);
if (!bs) {
NS_WARNING("BluetoothService not available!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
@ -239,7 +257,10 @@ BluetoothManager::Create(nsPIDOMWindow* aWindow) {
nsRefPtr<BluetoothManager> manager = new BluetoothManager(aWindow);
BluetoothService* bs = BluetoothService::Get();
MOZ_ASSERT(bs);
if (!bs) {
NS_WARNING("BluetoothService not available!");
return nullptr;
}
if (NS_FAILED(bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING("/"), manager))) {
NS_ERROR("Failed to register object with observer!");

View File

@ -8,6 +8,7 @@
#define mozilla_dom_bluetooth_bluetoothmanager_h__
#include "BluetoothCommon.h"
#include "BluetoothPropertyContainer.h"
#include "nsDOMEventTargetHelper.h"
#include "nsIDOMBluetoothManager.h"
#include "mozilla/Observer.h"
@ -15,9 +16,12 @@
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothNamedValue;
class BluetoothManager : public nsDOMEventTargetHelper
, public nsIDOMBluetoothManager
, public BluetoothSignalObserver
, public BluetoothPropertyContainer
{
public:
NS_DECL_ISUPPORTS_INHERITED
@ -34,12 +38,11 @@ public:
static already_AddRefed<BluetoothManager>
Create(nsPIDOMWindow* aWindow);
void Notify(const BluetoothSignal& aData);
virtual void SetPropertyByValue(const BluetoothNamedValue& aValue);
private:
BluetoothManager() {}
BluetoothManager(nsPIDOMWindow* aWindow);
~BluetoothManager();
bool mEnabled;
nsString mName;
NS_DECL_EVENT_HANDLER(enabled)
};

View File

@ -0,0 +1,76 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
#include "BluetoothPropertyContainer.h"
#include "BluetoothService.h"
#include "BluetoothTypes.h"
#include "nsIDOMDOMRequest.h"
USING_BLUETOOTH_NAMESPACE
nsresult
BluetoothPropertyContainer::GetProperties()
{
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
NS_WARNING("Bluetooth service not available!");
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothReplyRunnable> task = new GetPropertiesTask(this, NULL);
return bs->GetProperties(mObjectType, mPath, task);
}
nsresult
BluetoothPropertyContainer::SetProperty(nsIDOMWindow* aOwner,
const BluetoothNamedValue& aProperty,
nsIDOMDOMRequest** aRequest)
{
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
NS_WARNING("Bluetooth service not available!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
if (!rs) {
NS_WARNING("No DOMRequest Service!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMDOMRequest> req;
nsresult rv = rs->CreateRequest(aOwner, getter_AddRefs(req));
if (NS_FAILED(rv)) {
NS_WARNING("Can't create DOMRequest!");
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothReplyRunnable> task = new BluetoothVoidReplyRunnable(req);
rv = bs->SetProperty(mObjectType, mPath, aProperty, task);
NS_ENSURE_SUCCESS(rv, rv);
req.forget(aRequest);
return NS_OK;
}
bool
BluetoothPropertyContainer::GetPropertiesTask::ParseSuccessfulReply(jsval* aValue)
{
*aValue = JSVAL_VOID;
BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
NS_WARNING("Not a BluetoothNamedValue array!");
return false;
}
const InfallibleTArray<BluetoothNamedValue>& values =
mReply->get_BluetoothReplySuccess().value().get_ArrayOfBluetoothNamedValue();
for (uint32_t i = 0; i < values.Length(); ++i) {
mPropObjPtr->SetPropertyByValue(values[i]);
}
return true;
}

View File

@ -0,0 +1,75 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_bluetoothpropertyobject_h__
#define mozilla_dom_bluetooth_bluetoothpropertyobject_h__
#include "BluetoothCommon.h"
#include "BluetoothReplyRunnable.h"
class nsIDOMDOMRequest;
class nsIDOMWindow;
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothNamedValue;
class BluetoothPropertyContainer
{
public:
nsresult GetProperties();
nsresult SetProperty(nsIDOMWindow* aOwner,
const BluetoothNamedValue& aProperty,
nsIDOMDOMRequest** aRequest);
virtual void SetPropertyByValue(const BluetoothNamedValue& aValue) = 0;
nsString GetPath()
{
return mPath;
}
// Compatibility with nsRefPtr to make sure we don't hold a weakptr to
// ourselves
virtual nsrefcnt AddRef() = 0;
virtual nsrefcnt Release() = 0;
protected:
BluetoothPropertyContainer(BluetoothObjectType aType) :
mObjectType(aType)
{}
~BluetoothPropertyContainer()
{}
class GetPropertiesTask : public BluetoothReplyRunnable
{
public:
GetPropertiesTask(BluetoothPropertyContainer* aPropObj, nsIDOMDOMRequest* aReq) :
BluetoothReplyRunnable(aReq),
mPropObjPtr(aPropObj)
{
MOZ_ASSERT(aReq && aPropObj);
}
virtual bool ParseSuccessfulReply(jsval* aValue);
void
ReleaseMembers()
{
BluetoothReplyRunnable::ReleaseMembers();
mPropObjPtr = nullptr;
}
private:
BluetoothPropertyContainer* mPropObjPtr;
};
nsString mPath;
BluetoothObjectType mObjectType;
};
END_BLUETOOTH_NAMESPACE
#endif

View File

@ -0,0 +1,53 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
#include "BluetoothPropertyEvent.h"
#include "BluetoothTypes.h"
#include "nsDOMClassInfo.h"
USING_BLUETOOTH_NAMESPACE
// static
already_AddRefed<BluetoothPropertyEvent>
BluetoothPropertyEvent::Create(const nsAString& aPropertyName)
{
NS_ASSERTION(!aPropertyName.IsEmpty(), "Empty Property String!");
nsRefPtr<BluetoothPropertyEvent> event = new BluetoothPropertyEvent();
event->mPropertyName = aPropertyName;
return event.forget();
}
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothPropertyEvent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothPropertyEvent,
nsDOMEvent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothPropertyEvent,
nsDOMEvent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothPropertyEvent)
NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothPropertyEvent)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothPropertyEvent)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
NS_IMPL_ADDREF_INHERITED(BluetoothPropertyEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(BluetoothPropertyEvent, nsDOMEvent)
DOMCI_DATA(BluetoothPropertyEvent, BluetoothPropertyEvent)
NS_IMETHODIMP
BluetoothPropertyEvent::GetProperty(nsAString& aPropertyName)
{
aPropertyName = mPropertyName;
return NS_OK;
}

View File

@ -0,0 +1,66 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_propertyevent_h__
#define mozilla_dom_bluetooth_propertyevent_h__
#include "BluetoothCommon.h"
#include "nsIDOMBluetoothPropertyEvent.h"
#include "nsIDOMEventTarget.h"
#include "nsDOMEvent.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothPropertyEvent : public nsDOMEvent
, public nsIDOMBluetoothPropertyEvent
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_TO_NSDOMEVENT
NS_DECL_NSIDOMBLUETOOTHPROPERTYEVENT
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothPropertyEvent, nsDOMEvent)
static already_AddRefed<BluetoothPropertyEvent>
Create(const nsAString& aPropertyName);
nsresult
Dispatch(nsIDOMEventTarget* aTarget, const nsAString& aEventType)
{
NS_ASSERTION(aTarget, "Null pointer!");
NS_ASSERTION(!aEventType.IsEmpty(), "Empty event type!");
nsresult rv = InitEvent(aEventType, false, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = SetTrusted(true);
NS_ENSURE_SUCCESS(rv, rv);
nsIDOMEvent* thisEvent =
static_cast<nsDOMEvent*>(const_cast<BluetoothPropertyEvent*>(this));
bool dummy;
rv = aTarget->DispatchEvent(thisEvent, &dummy);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
private:
BluetoothPropertyEvent()
: nsDOMEvent(nullptr, nullptr)
{ }
~BluetoothPropertyEvent()
{ }
nsString mPropertyName;
};
END_BLUETOOTH_NAMESPACE
#endif

View File

@ -7,8 +7,6 @@
#include "base/basictypes.h"
#include "BluetoothTypes.h"
#include "BluetoothReplyRunnable.h"
#include "nsIDOMDOMRequest.h"
#include "jsapi.h"
USING_BLUETOOTH_NAMESPACE

View File

@ -9,10 +9,9 @@
#include "BluetoothCommon.h"
#include "nsThreadUtils.h"
#include "nsIDOMDOMRequest.h"
#include "jsapi.h"
class nsIDOMDOMRequest;
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothReply;

View File

@ -143,6 +143,50 @@ public:
*/
virtual nsresult StopInternal() = 0;
/**
* Fetches the propertes for the specified object
*
* @param aType Type of the object (see BluetoothObjectType in BluetoothCommon.h)
* @param aPath Path of the object
* @param aRunnable Runnable to return to after receiving callback
*
* @return NS_OK on function run, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
GetProperties(BluetoothObjectType aType,
const nsAString& aPath,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Set a property for the specified object
*
* @param aPath Path to the object
* @param aPropName Name of the property
* @param aValue Boolean value
* @param aRunnable Runnable to run on async reply
*
* @return NS_OK if property is set correctly, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
SetProperty(BluetoothObjectType aType,
const nsAString& aPath,
const BluetoothNamedValue& aValue,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Get the path of a device
*
* @param aAdapterPath Path to the Adapter that's communicating with the device
* @param aDeviceAddress Device address (XX:XX:XX:XX:XX:XX format)
* @param aDevicePath Return value of path
*
* @return True if path set correctly, false otherwise
*/
virtual bool
GetDevicePath(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
nsAString& aDevicePath) = 0;
protected:
BluetoothService()
{

View File

@ -0,0 +1,61 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BluetoothUtils.h"
#include "jsapi.h"
#include "nsTArray.h"
#include "nsString.h"
#include "mozilla/Scoped.h"
nsresult
mozilla::dom::bluetooth::StringArrayToJSArray(JSContext* aCx, JSObject* aGlobal,
const nsTArray<nsString>& aSourceArray,
JSObject** aResultArray)
{
NS_ASSERTION(aCx, "Null context!");
NS_ASSERTION(aGlobal, "Null global!");
JSAutoRequest ar(aCx);
JSAutoEnterCompartment ac;
if (!ac.enter(aCx, aGlobal)) {
NS_WARNING("Failed to enter compartment!");
return NS_ERROR_FAILURE;
}
JSObject* arrayObj;
if (aSourceArray.IsEmpty()) {
arrayObj = JS_NewArrayObject(aCx, 0, nullptr);
} else {
uint32_t valLength = aSourceArray.Length();
mozilla::ScopedDeleteArray<jsval> valArray(new jsval[valLength]);
JS::AutoArrayRooter tvr(aCx, valLength, valArray);
for (PRUint32 index = 0; index < valLength; index++) {
JSString* s = JS_NewUCStringCopyN(aCx, aSourceArray[index].BeginReading(),
aSourceArray[index].Length());
if(!s) {
NS_WARNING("Memory allocation error!");
return NS_ERROR_OUT_OF_MEMORY;
}
valArray[index] = STRING_TO_JSVAL(s);
}
arrayObj = JS_NewArrayObject(aCx, valLength, valArray);
}
if (!arrayObj) {
return NS_ERROR_OUT_OF_MEMORY;
}
// XXX This is not what Jonas wants. He wants it to be live.
// Followup at bug 717414
if (!JS_FreezeObject(aCx, arrayObj)) {
return NS_ERROR_FAILURE;
}
*aResultArray = arrayObj;
return NS_OK;
}

View File

@ -0,0 +1,24 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_bluetoothutils_h__
#define mozilla_dom_bluetooth_bluetoothutils_h__
#include "BluetoothCommon.h"
class JSContext;
class JSObject;
BEGIN_BLUETOOTH_NAMESPACE
nsresult
StringArrayToJSArray(JSContext* aCx, JSObject* aGlobal,
const nsTArray<nsString>& aSourceArray,
JSObject** aResultArray);
END_BLUETOOTH_NAMESPACE
#endif

View File

@ -33,7 +33,10 @@ CPPSRCS += \
BluetoothAdapter.cpp \
BluetoothDevice.cpp \
BluetoothDeviceEvent.cpp \
BluetoothPropertyEvent.cpp \
BluetoothReplyRunnable.cpp \
BluetoothPropertyContainer.cpp \
BluetoothUtils.cpp \
$(NULL)
XPIDLSRCS = \
@ -42,6 +45,7 @@ XPIDLSRCS = \
nsIDOMBluetoothAdapter.idl \
nsIDOMBluetoothDevice.idl \
nsIDOMBluetoothDeviceEvent.idl \
nsIDOMBluetoothPropertyEvent.idl \
$(NULL)
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))

View File

@ -57,6 +57,7 @@ USING_BLUETOOTH_NAMESPACE
#define LOG(args...) if (BTDEBUG) printf(args);
#endif
#define DBUS_MANAGER_IFACE BLUEZ_DBUS_BASE_IFC ".Manager"
#define DBUS_ADAPTER_IFACE BLUEZ_DBUS_BASE_IFC ".Adapter"
#define DBUS_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".Device"
#define BLUEZ_DBUS_BASE_PATH "/org/bluez"
@ -68,7 +69,7 @@ typedef struct {
int type;
} Properties;
static Properties remote_device_properties[] = {
static Properties sDeviceProperties[] = {
{"Address", DBUS_TYPE_STRING},
{"Name", DBUS_TYPE_STRING},
{"Icon", DBUS_TYPE_STRING},
@ -88,7 +89,7 @@ static Properties remote_device_properties[] = {
{"Broadcaster", DBUS_TYPE_BOOLEAN}
};
static Properties adapter_properties[] = {
static Properties sAdapterProperties[] = {
{"Address", DBUS_TYPE_STRING},
{"Name", DBUS_TYPE_STRING},
{"Class", DBUS_TYPE_UINT32},
@ -102,7 +103,18 @@ static Properties adapter_properties[] = {
{"UUIDs", DBUS_TYPE_ARRAY},
};
static const char* BLUETOOTH_DBUS_SIGNALS[] =
static Properties sManagerProperties[] = {
{"Adapters", DBUS_TYPE_ARRAY},
};
static const char* sBluetoothDBusIfaces[] =
{
DBUS_MANAGER_IFACE,
DBUS_ADAPTER_IFACE,
DBUS_DEVICE_IFACE
};
static const char* sBluetoothDBusSignals[] =
{
"type='signal',interface='org.freedesktop.DBus'",
"type='signal',interface='org.bluez.Adapter'",
@ -128,12 +140,14 @@ public:
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
MOZ_ASSERT(bs);
if (!bs) {
NS_WARNING("BluetoothService not available!");
return NS_ERROR_FAILURE;
}
return bs->DistributeSignal(mSignal);
}
};
bool
IsDBusMessageError(DBusMessage* aMsg, nsAString& aError)
{
@ -176,24 +190,14 @@ DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
NS_WARNING("Failed to dispatch to main thread!");
}
}
void
GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
UnpackObjectPathMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
{
MOZ_ASSERT(!NS_IsMainThread());
DBusError err;
dbus_error_init(&err);
nsRefPtr<BluetoothReplyRunnable> replyRunnable =
dont_AddRef(static_cast< BluetoothReplyRunnable* >(aBluetoothReplyRunnable));
NS_ASSERTION(replyRunnable, "Callback reply runnable is null!");
nsString replyError;
nsString replyPath;
nsTArray<BluetoothNamedValue> replyValues;
BluetoothValue v;
if (!IsDBusMessageError(aMsg, replyError)) {
if (!IsDBusMessageError(aMsg, aErrorStr)) {
NS_ASSERTION(dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN,
"Got dbus callback that's not a METHOD_RETURN!");
const char* object_path;
@ -201,22 +205,22 @@ GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
&object_path, DBUS_TYPE_INVALID) ||
!object_path) {
if (dbus_error_is_set(&err)) {
replyError = NS_ConvertUTF8toUTF16(err.message);
aErrorStr = NS_ConvertUTF8toUTF16(err.message);
LOG_AND_FREE_DBUS_ERROR(&err);
}
} else {
v = NS_ConvertUTF8toUTF16(object_path);
aValue = NS_ConvertUTF8toUTF16(object_path);
}
}
DispatchBluetoothReply(replyRunnable, v, replyError);
}
typedef void (*UnpackFunc)(DBusMessage*, BluetoothValue&, nsAString&);
void
GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
UnpackFunc aFunc)
{
MOZ_ASSERT(!NS_IsMainThread());
DBusError err;
dbus_error_init(&err);
nsRefPtr<BluetoothReplyRunnable> replyRunnable =
dont_AddRef(static_cast< BluetoothReplyRunnable* >(aBluetoothReplyRunnable));
@ -224,20 +228,41 @@ GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
nsString replyError;
BluetoothValue v;
if (!IsDBusMessageError(aMsg, replyError) &&
aFunc(aMsg, v, replyError);
DispatchBluetoothReply(replyRunnable, v, replyError);
}
void
GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackObjectPathMessage);
}
void
UnpackVoidMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
{
DBusError err;
dbus_error_init(&err);
if (!IsDBusMessageError(aMsg, aErrorStr) &&
dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN &&
!dbus_message_get_args(aMsg, &err, DBUS_TYPE_INVALID)) {
if (dbus_error_is_set(&err)) {
replyError = NS_ConvertUTF8toUTF16(err.message);
aErrorStr = NS_ConvertUTF8toUTF16(err.message);
LOG_AND_FREE_DBUS_ERROR(&err);
}
}
DispatchBluetoothReply(replyRunnable, v, replyError);
}
void
GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackVoidMessage);
}
bool
GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
int aPropertiesTypeLen, int* aPropIndex,
int aPropertyTypeLen, int* aPropIndex,
InfallibleTArray<BluetoothNamedValue>& aProperties)
{
DBusMessageIter prop_val, array_val_iter;
@ -256,13 +281,13 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
return false;
}
for (i = 0; i < aPropertiesTypeLen; i++) {
for (i = 0; i < aPropertyTypeLen; i++) {
if (!strncmp(property, aPropertyTypes[i].name, strlen(property))) {
break;
}
}
if (i == aPropertiesTypeLen) {
if (i == aPropertyTypeLen) {
return false;
}
@ -310,6 +335,9 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
} while (dbus_message_iter_next(&array_val_iter));
propertyValue = arr;
} else {
// This happens when the array is 0-length. Apparently we get a
// DBUS_TYPE_INVALID type.
propertyValue = InfallibleTArray<nsString>();
NS_WARNING("Received array type that's not a string array!");
}
break;
@ -321,10 +349,11 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
}
void
ParseProperties(DBusMessageIter* aIter,
ParseProperties(DBusMessageIter* aIter,
BluetoothValue& aValue,
nsAString& aErrorStr,
Properties* aPropertyTypes,
const int aPropertiesTypeLen,
InfallibleTArray<BluetoothNamedValue>& aProperties)
const int aPropertyTypeLen)
{
DBusMessageIter dict_entry, dict;
int prop_index = -1;
@ -333,28 +362,100 @@ ParseProperties(DBusMessageIter* aIter,
"Trying to parse a property from something that's not an array!");
dbus_message_iter_recurse(aIter, &dict);
InfallibleTArray<BluetoothNamedValue> props;
do {
NS_ASSERTION(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY,
"Trying to parse a property from something that's not an dict!");
dbus_message_iter_recurse(&dict, &dict_entry);
if (!GetProperty(dict_entry, aPropertyTypes, aPropertiesTypeLen, &prop_index,
aProperties)) {
if (!GetProperty(dict_entry, aPropertyTypes, aPropertyTypeLen, &prop_index,
props)) {
aErrorStr.AssignLiteral("Can't Create Property!");
NS_WARNING("Can't create property!");
return;
}
} while (dbus_message_iter_next(&dict));
aValue = props;
}
void UnpackPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr, Properties* aPropertyTypes,
const int aPropertyTypeLen)
{
if (!IsDBusMessageError(aMsg, aErrorStr) &&
dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
DBusMessageIter iter;
if (!dbus_message_iter_init(aMsg, &iter)) {
aErrorStr.AssignLiteral("Cannot create dbus message iter!");
} else {
ParseProperties(&iter, aValue, aErrorStr, aPropertyTypes,
aPropertyTypeLen);
}
}
}
void UnpackAdapterPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
{
UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
sAdapterProperties,
ArrayLength(sAdapterProperties));
}
void UnpackDevicePropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
{
UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
sDeviceProperties,
ArrayLength(sDeviceProperties));
}
void UnpackManagerPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
{
UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
sManagerProperties,
ArrayLength(sManagerProperties));
}
void
ParsePropertyChange(DBusMessage* aMsg, Properties* aPropertyTypes,
const int aPropertiesTypeLen,
InfallibleTArray<BluetoothNamedValue>& aProperties)
GetManagerPropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackManagerPropertiesMessage);
}
void
GetAdapterPropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackAdapterPropertiesMessage);
}
void
GetDevicePropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackDevicePropertiesMessage);
}
static DBusCallback sBluetoothDBusPropCallbacks[] =
{
GetManagerPropertiesCallback,
GetAdapterPropertiesCallback,
GetDevicePropertiesCallback
};
MOZ_STATIC_ASSERT(sizeof(sBluetoothDBusPropCallbacks) == sizeof(sBluetoothDBusIfaces),
"DBus Property callback array and DBus interface array must be same size");
void
ParsePropertyChange(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr, Properties* aPropertyTypes,
const int aPropertyTypeLen)
{
DBusMessageIter iter;
DBusError err;
int prop_index = -1;
InfallibleTArray<BluetoothNamedValue> props;
dbus_error_init(&err);
if (!dbus_message_iter_init(aMsg, &iter)) {
@ -362,10 +463,13 @@ ParsePropertyChange(DBusMessage* aMsg, Properties* aPropertyTypes,
return;
}
if (!GetProperty(iter, aPropertyTypes, aPropertiesTypeLen,
&prop_index, aProperties)) {
if (!GetProperty(iter, aPropertyTypes, aPropertyTypeLen,
&prop_index, props)) {
NS_WARNING("Can't get property!");
aErrorStr.AssignLiteral("Can't get property!");
return;
}
aValue = props;
}
// Called by dbus during WaitForAndDispatchEventNative()
@ -392,11 +496,8 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
nsString signalName;
dbus_error_init(&err);
signalPath = NS_ConvertUTF8toUTF16(dbus_message_get_path(aMsg));
LOG("%s: Received signal %s:%s from %s\n", __FUNCTION__,
dbus_message_get_interface(aMsg), dbus_message_get_member(aMsg),
dbus_message_get_path(aMsg));
signalName = NS_ConvertUTF8toUTF16(dbus_message_get_member(aMsg));
nsString errorStr;
BluetoothValue v;
if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceFound")) {
@ -408,21 +509,28 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
InfallibleTArray<BluetoothNamedValue> value;
const char* addr;
dbus_message_iter_get_basic(&iter, &addr);
value.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Address"),
NS_ConvertUTF8toUTF16(addr)));
if (dbus_message_iter_next(&iter)) {
ParseProperties(&iter,
remote_device_properties,
ArrayLength(remote_device_properties),
value);
NS_ASSERTION(value.Length() != 0, "Properties returned empty!");
v = value;
v,
errorStr,
sDeviceProperties,
ArrayLength(sDeviceProperties));
if (v.type() == BluetoothValue::TArrayOfBluetoothNamedValue)
{
// The DBus DeviceFound message actually passes back a key value object
// with the address as the key and the rest of the device properties as
// a dict value. After we parse out the properties, we need to go back
// and add the address to the ipdl dict we've created to make sure we
// have all of the information to correctly build the device.
v.get_ArrayOfBluetoothNamedValue()
.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Address"),
NS_ConvertUTF8toUTF16(addr)));
}
} else {
NS_WARNING("DBus iterator not as long as expected!");
errorStr.AssignLiteral("DBus device found message structure not as expected!");
}
} else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceDisappeared")) {
const char* str;
@ -430,6 +538,7 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
DBUS_TYPE_STRING, &str,
DBUS_TYPE_INVALID)) {
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
errorStr.AssignLiteral("Cannot parse device address!");
}
v = NS_ConvertUTF8toUTF16(str);
} else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceCreated")) {
@ -438,16 +547,39 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
DBUS_TYPE_OBJECT_PATH, &str,
DBUS_TYPE_INVALID)) {
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
errorStr.AssignLiteral("Cannot parse device path!");
}
v = NS_ConvertUTF8toUTF16(str);
} else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "PropertyChanged")) {
InfallibleTArray<BluetoothNamedValue> value;
ParsePropertyChange(aMsg,
(Properties*)&adapter_properties,
ArrayLength(adapter_properties),
value);
NS_ASSERTION(value.Length() != 0, "Properties returned empty!");
v = value;
v,
errorStr,
sAdapterProperties,
ArrayLength(sAdapterProperties));
} else if (dbus_message_is_signal(aMsg, DBUS_DEVICE_IFACE, "PropertyChanged")) {
ParsePropertyChange(aMsg,
v,
errorStr,
sDeviceProperties,
ArrayLength(sDeviceProperties));
} else if (dbus_message_is_signal(aMsg, DBUS_MANAGER_IFACE, "PropertyChanged")) {
ParsePropertyChange(aMsg,
v,
errorStr,
sManagerProperties,
ArrayLength(sManagerProperties));
} else {
#ifdef DEBUG
nsCAutoString signalStr;
signalStr += dbus_message_get_member(aMsg);
signalStr += " Signal not handled!";
NS_WARNING(signalStr.get());
#endif
}
if (!errorStr.IsEmpty()) {
NS_WARNING(NS_ConvertUTF16toUTF8(errorStr).get());
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
BluetoothSignal signal(signalName, signalPath, v);
@ -577,3 +709,131 @@ BluetoothDBusService::StartDiscoveryInternal(const nsAString& aAdapterPath,
{
return SendDiscoveryMessage(aAdapterPath, "StartDiscovery", aRunnable);
}
nsresult
BluetoothDBusService::GetProperties(BluetoothObjectType aType,
const nsAString& aPath,
BluetoothReplyRunnable* aRunnable)
{
NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusIfaces));
MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusPropCallbacks));
const char* interface = sBluetoothDBusIfaces[aType];
DBusCallback callback = sBluetoothDBusPropCallbacks[aType];
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
if (!dbus_func_args_async(mConnection,
1000,
callback,
(void*)aRunnable,
NS_ConvertUTF16toUTF8(aPath).get(),
interface,
"GetProperties",
DBUS_TYPE_INVALID)) {
NS_WARNING("Could not start async function!");
return NS_ERROR_FAILURE;
}
runnable.forget();
return NS_OK;
}
nsresult
BluetoothDBusService::SetProperty(BluetoothObjectType aType,
const nsAString& aPath,
const BluetoothNamedValue& aValue,
BluetoothReplyRunnable* aRunnable)
{
NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusIfaces));
const char* interface = sBluetoothDBusIfaces[aType];
/* Compose the command */
DBusMessage* msg = dbus_message_new_method_call("org.bluez",
NS_ConvertUTF16toUTF8(aPath).get(),
interface,
"SetProperty");
if (!msg) {
NS_WARNING("Could not allocate D-Bus message object!");
return NS_ERROR_FAILURE;
}
const char* propName = NS_ConvertUTF16toUTF8(aValue.name()).get();
if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &propName, DBUS_TYPE_INVALID)) {
NS_WARNING("Couldn't append arguments to dbus message!");
return NS_ERROR_FAILURE;
}
int type;
int tmp_int;
void* val;
nsCString str;
if (aValue.value().type() == BluetoothValue::Tuint32_t) {
tmp_int = aValue.value().get_uint32_t();
val = &tmp_int;
type = DBUS_TYPE_UINT32;
} else if (aValue.value().type() == BluetoothValue::TnsString) {
str = NS_ConvertUTF16toUTF8(aValue.value().get_nsString());
val = (void*)str.get();
type = DBUS_TYPE_STRING;
} else if (aValue.value().type() == BluetoothValue::Tbool) {
tmp_int = aValue.value().get_bool() ? 1 : 0;
val = &(tmp_int);
type = DBUS_TYPE_BOOLEAN;
} else {
NS_WARNING("Property type not handled!");
dbus_message_unref(msg);
return NS_ERROR_FAILURE;
}
DBusMessageIter value_iter, iter;
dbus_message_iter_init_append(msg, &iter);
char var_type[2] = {(char)type, '\0'};
if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, var_type, &value_iter) ||
!dbus_message_iter_append_basic(&value_iter, type, val) ||
!dbus_message_iter_close_container(&iter, &value_iter)) {
NS_WARNING("Could not append argument to method call!");
dbus_message_unref(msg);
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
// msg is unref'd as part of dbus_func_send_async
if (!dbus_func_send_async(mConnection,
msg,
1000,
GetVoidCallback,
(void*)aRunnable)) {
NS_WARNING("Could not start async function!");
return NS_ERROR_FAILURE;
}
runnable.forget();
return NS_OK;
}
nsString
GetObjectPathFromAddress(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress)
{
// The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1,
// and the adapter path would be the first part of the object path, accoring
// to the example above, it's /org/bluez/2906/hci0.
nsString devicePath(aAdapterPath);
devicePath.AppendLiteral("/dev_");
devicePath.Append(aDeviceAddress);
devicePath.ReplaceChar(':', '_');
return devicePath;
}
bool
BluetoothDBusService::GetDevicePath(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
nsAString& aDevicePath)
{
aDevicePath = GetObjectPathFromAddress(aAdapterPath, aDeviceAddress);
return true;
}

View File

@ -16,67 +16,46 @@ class DBusMessage;
BEGIN_BLUETOOTH_NAMESPACE
/**
* BluetoothService functions are used to dispatch messages to Bluetooth DOM
* objects on the main thread, as well as provide platform independent access
* to BT functionality. Tasks for polling for outside messages will usually
* happen on the IO Thread (see ipc/dbus for instance), and these messages will
* be encased in runnables that will then be distributed via observers managed
* here.
* BluetoothDBusService is the implementation of BluetoothService for DBus on
* linux/android/B2G. Function comments are in BluetoothService.h
*/
class BluetoothDBusService : public BluetoothService
, private mozilla::ipc::RawDBusConnection
{
public:
/**
* Set up variables and start the platform specific connection. Must
* be called from outside main thread.
*
* @return NS_OK if connection starts successfully, NS_ERROR_FAILURE
* otherwise
*/
virtual nsresult StartInternal();
/**
* Stop the platform specific connection. Must be called from outside main
* thread.
*
* @return NS_OK if connection starts successfully, NS_ERROR_FAILURE
* otherwise
*/
virtual nsresult StopInternal();
/**
* Returns the path of the default adapter, implemented via a platform
* specific method.
*
* @return Default adapter path/name on success, NULL otherwise
*/
virtual nsresult GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable);
/**
* Start device discovery (platform specific implementation)
*
* @param aAdapterPath Adapter to start discovery on
*
* @return NS_OK if discovery stopped correctly, NS_ERROR_FAILURE otherwise
*/
virtual nsresult StartDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable);
/**
* Stop device discovery (platform specific implementation)
*
* @param aAdapterPath Adapter to stop discovery on
*
* @return NS_OK if discovery stopped correctly, NS_ERROR_FAILURE otherwise
*/
virtual nsresult StopDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable);
virtual nsresult
GetProperties(BluetoothObjectType aType,
const nsAString& aPath,
BluetoothReplyRunnable* aRunnable);
virtual nsresult
SetProperty(BluetoothObjectType aType,
const nsAString& aPath,
const BluetoothNamedValue& aValue,
BluetoothReplyRunnable* aRunnable);
virtual bool
GetDevicePath(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
nsAString& aDevicePath);
private:
nsresult SendGetPropertyMessage(const nsAString& aPath,
const char* aInterface,
void (*aCB)(DBusMessage *, void *),
BluetoothReplyRunnable* aRunnable);
nsresult SendDiscoveryMessage(const nsAString& aAdapterPath,
const char* aMessageName,
BluetoothReplyRunnable* aRunnable);
nsresult SendSetPropertyMessage(const nsString& aPath, const char* aInterface,
const BluetoothNamedValue& aValue,
BluetoothReplyRunnable* aRunnable);
};
END_BLUETOOTH_NAMESPACE

View File

@ -170,7 +170,7 @@ EventFilter(DBusConnection *aConn, DBusMessage *aMsg,
nsresult
StartBluetoothConnection()
{
if(sDBusConnection) {
if (sDBusConnection) {
NS_WARNING("DBusConnection already established, skipping");
return NS_OK;
}
@ -193,7 +193,7 @@ StartBluetoothConnection()
nsresult
StopBluetoothConnection()
{
if(!sDBusConnection) {
if (!sDBusConnection) {
NS_WARNING("DBusConnection does not exist, nothing to stop, skipping.");
return NS_OK;
}

View File

@ -9,7 +9,7 @@
interface nsIDOMDOMRequest;
interface nsIDOMBluetoothDevice;
[scriptable, builtinclass, uuid(48df7f05-2bbc-4ac8-aa88-9fecd4c24028)]
[scriptable, builtinclass, uuid(86e9fe78-ce64-476e-a357-333f7d3c8980)]
interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
{
readonly attribute DOMString address;
@ -20,11 +20,17 @@ interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
[implicit_jscontext]
readonly attribute jsval devices;
[implicit_jscontext]
readonly attribute jsval uuids;
readonly attribute DOMString name;
readonly attribute bool discoverable;
// Unit: sec
readonly attribute unsigned long discoverableTimeout;
nsIDOMDOMRequest setName(in DOMString name);
nsIDOMDOMRequest setDiscoverable(in bool discoverable);
nsIDOMDOMRequest setDiscoverableTimeout(in unsigned long timeout);
nsIDOMDOMRequest startDiscovery();
nsIDOMDOMRequest stopDiscovery();
// Fired when discoverying and any device is discovered.

View File

@ -6,13 +6,13 @@
#include "nsIDOMEventTarget.idl"
[scriptable, builtinclass, uuid(2c446123-b5dd-4631-80f6-eda91befd8c9)]
[scriptable, builtinclass, uuid(24c64513-9587-46c6-b718-bb9b9a754b0d)]
interface nsIDOMBluetoothDevice : nsIDOMEventTarget
{
readonly attribute DOMString address;
readonly attribute DOMString name;
[binaryname(DeviceClass)] readonly attribute unsigned long class;
[implicit_jscontext] readonly attribute jsval uuids;
readonly attribute bool connected;
readonly attribute bool paired;
attribute nsIDOMEventListener onpropertychanged;

View File

@ -0,0 +1,13 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIDOMEvent.idl"
[scriptable, builtinclass, uuid(2604ce78-abaa-4af4-b456-daa4c6386a11)]
interface nsIDOMBluetoothPropertyEvent : nsIDOMEvent
{
readonly attribute DOMString property;
};

View File

@ -193,7 +193,9 @@ BrowserElementParent::OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,
NS_ENSURE_TRUE(popupFrameElement, false);
nsCAutoString spec;
aURI->GetSpec(spec);
if (aURI) {
aURI->GetSpec(spec);
}
bool dispatchSucceeded =
DispatchOpenWindowEvent(openerFrameElement, popupFrameElement,
NS_ConvertUTF8toUTF16(spec),

View File

@ -53,6 +53,8 @@ public:
* set aPopupTabParent's frame element to event.detail.frameElement.
* Otherwise, we return false.
*
* @param aURL the URL the new window should load. The empty string is
* allowed.
* @param aOpenerTabParent the TabParent whose TabChild called window.open.
* @param aPopupTabParent the TabParent inside which the opened window will
* live.
@ -75,6 +77,8 @@ public:
*
* (These parameter types are silly, but they match what our caller has in
* hand. Feel free to add an override, if they are inconvenient to you.)
*
* @param aURI the URI the new window should load. May be null.
*/
static bool
OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,

View File

@ -7,12 +7,13 @@
#include "CameraControl.h"
#include "nsAutoPtr.h"
#include "mozilla/Attributes.h"
namespace mozilla {
typedef nsresult (*ParseItemAndAddFunc)(JSContext* aCx, JSObject* aArray, PRUint32 aIndex, const char* aStart, char** aEnd);
class nsCameraCapabilities : public nsICameraCapabilities
class nsCameraCapabilities MOZ_FINAL : public nsICameraCapabilities
{
public:
NS_DECL_ISUPPORTS

View File

@ -25,8 +25,8 @@ NS_INTERFACE_MAP_BEGIN(nsCameraControl)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraControl)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsCameraControl)
NS_IMPL_RELEASE(nsCameraControl)
NS_IMPL_THREADSAFE_ADDREF(nsCameraControl)
NS_IMPL_THREADSAFE_RELEASE(nsCameraControl)
// Helpers for string properties.
nsresult

View File

@ -9,7 +9,7 @@
using namespace mozilla;
NS_IMPL_ISUPPORTS1(CameraPreview, CameraPreview)
NS_IMPL_THREADSAFE_ISUPPORTS1(CameraPreview, CameraPreview)
class CameraPreviewListener : public MediaStreamListener
{

View File

@ -12,8 +12,9 @@
#include "nsIThread.h"
#include "nsThreadUtils.h"
#include "nsIDOMCameraManager.h"
#include "mozilla/Attributes.h"
class nsDOMCameraManager : public nsIDOMCameraManager
class nsDOMCameraManager MOZ_FINAL : public nsIDOMCameraManager
{
public:
NS_DECL_ISUPPORTS

View File

@ -72,7 +72,7 @@ GonkCameraPreview::ReceiveFrame(PRUint8 *aData, PRUint32 aLength)
uint8_t* y = aData;
uint32_t yN = mWidth * mHeight;
NS_ASSERTION(yN & 0x3 == 0, "Invalid image dimensions!");
NS_ASSERTION((yN & 0x3) == 0, "Invalid image dimensions!");
uint32_t uvN = yN / 4;
uint32_t* src = (uint32_t*)( y + yN );
@ -81,7 +81,7 @@ GonkCameraPreview::ReceiveFrame(PRUint8 *aData, PRUint32 aLength)
uint32_t* v = u + uvN / 4;
// we're handling pairs of 32-bit words, so divide by 8
NS_ASSERTION(uvN & 0x7 == 0, "Invalid image dimensions!");
NS_ASSERTION((uvN & 0x7) == 0, "Invalid image dimensions!");
uvN /= 8;
while (uvN--) {
@ -136,11 +136,11 @@ GonkCameraPreview::ReceiveFrame(PRUint8 *aData, PRUint32 aLength)
data.mYSize = gfxIntSize(mWidth, mHeight);
data.mYStride = mWidth * lumaBpp;
NS_ASSERTION(data.mYStride & 0x7 == 0, "Invalid image dimensions!");
NS_ASSERTION((data.mYStride & 0x7) == 0, "Invalid image dimensions!");
data.mYStride /= 8;
data.mCbCrStride = mWidth * chromaBpp;
NS_ASSERTION(data.mCbCrStride & 0x7 == 0, "Invalid image dimensions!");
NS_ASSERTION((data.mCbCrStride & 0x7) == 0, "Invalid image dimensions!");
data.mCbCrStride /= 8;
data.mCbChannel = aData + mHeight * data.mYStride;

View File

@ -385,7 +385,9 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
/* aChromeFlags = */ 0, mIsBrowserElement, mAppId));
nsCAutoString spec;
aURI->GetSpec(spec);
if (aURI) {
aURI->GetSpec(spec);
}
NS_ConvertUTF8toUTF16 url(spec);
nsString name(aName);

View File

@ -18,6 +18,7 @@
#include "gtk2compat.h"
#include "gtk2xtbin.h"
#include "mozilla/X11Util.h"
class nsPluginNativeWindowGtk2 : public nsPluginNativeWindow {
public:
@ -307,6 +308,6 @@ socket_unrealize_cb(GtkWidget *widget, gpointer data)
if (children) XFree(children);
XSync(display, False);
mozilla::FinishX(display);
gdk_error_trap_pop();
}

View File

@ -133,7 +133,7 @@ PluginInstanceParent::ActorDestroy(ActorDestroyReason why)
const NPRect rect = {0, 0, 0, 0};
RecvNPN_InvalidateRect(rect);
#ifdef MOZ_X11
XSync(DefaultXDisplay(), False);
FinishX(DefaultXDisplay());
#endif
}
}
@ -634,7 +634,7 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
// referencing it, so we XSync here to let them finish before
// the plugin starts scribbling on it again, or worse,
// destroys it.
XSync(DefaultXDisplay(), False);
FinishX(DefaultXDisplay());
#endif
if (mFrontSurface && gfxSharedImageSurface::IsSharedImage(mFrontSurface))
@ -1260,7 +1260,7 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
// process does not need to wait; the child is the process that needs
// to wait. A possibly-slightly-better alternative would be to send
// an X event to the child that the child would wait for.
XSync(DefaultXDisplay(), False);
FinishX(DefaultXDisplay());
return CallPaint(npremoteevent, &handled) ? handled : 0;

View File

@ -162,7 +162,7 @@ public:
void
Send(ArrayBuffer& aBody, ErrorResult& aRv) {
return Send(aBody.mObj, aRv);
return Send(aBody.Obj(), aRv);
}
void

View File

@ -163,8 +163,6 @@ private:
*/
void *mData;
SurfaceFormat mFormat;
RefPtr<SourceSurfaceCGContext> mSnapshot;
};

View File

@ -1415,7 +1415,7 @@ public:
if (mBackingSurface && mUpdateSurface == mBackingSurface) {
#ifdef MOZ_X11
if (mBackingSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
XSync(DefaultXDisplay(), False);
FinishX(DefaultXDisplay());
}
#endif

View File

@ -40,7 +40,7 @@ namespace mozilla {
namespace gl {
static bool gIsATI = false;
static bool gIsChromium = false;
static bool gClientIsMesa = false;
static int gGLXMajorVersion = 0, gGLXMinorVersion = 0;
// Check that we have at least version aMajor.aMinor .
@ -170,11 +170,7 @@ GLXLibrary::EnsureInitialized()
}
Display *display = DefaultXDisplay();
int screen = DefaultScreen(display);
const char *serverVendor = NULL;
const char *serverVersionStr = NULL;
const char *extensionsStr = NULL;
if (!xQueryVersion(display, &gGLXMajorVersion, &gGLXMinorVersion)) {
gGLXMajorVersion = 0;
@ -182,14 +178,13 @@ GLXLibrary::EnsureInitialized()
return false;
}
serverVendor = xQueryServerString(display, screen, GLX_VENDOR);
serverVersionStr = xQueryServerString(display, screen, GLX_VERSION);
if (!GLXVersionCheck(1, 1))
// Not possible to query for extensions.
return false;
extensionsStr = xQueryExtensionsString(display, screen);
const char *clientVendor = xGetClientString(display, GLX_VENDOR);
const char *serverVendor = xQueryServerString(display, screen, GLX_VENDOR);
const char *extensionsStr = xQueryExtensionsString(display, screen);
GLLibraryLoader::SymLoadStruct *sym13;
if (!GLXVersionCheck(1, 3)) {
@ -243,10 +238,7 @@ GLXLibrary::EnsureInitialized()
}
gIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
gIsChromium = (serverVendor &&
DoesStringMatch(serverVendor, "Chromium")) ||
(serverVersionStr &&
DoesStringMatch(serverVersionStr, "Chromium"));
gClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa");
mInitialized = true;
return true;
@ -270,36 +262,77 @@ GLXPixmap
GLXLibrary::CreatePixmap(gfxASurface* aSurface)
{
if (!SupportsTextureFromPixmap(aSurface)) {
return 0;
return None;
}
gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(aSurface);
const XRenderPictFormat *format = xs->XRenderFormat();
if (!format || format->type != PictTypeDirect) {
return None;
}
bool withAlpha =
aSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA;
int attribs[] = { GLX_DOUBLEBUFFER, False,
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
(withAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT
: GLX_BIND_TO_TEXTURE_RGB_EXT), True,
None };
int numFormats;
Display *display = DefaultXDisplay();
int numConfigs = 0;
Display *display = xs->XDisplay();
int xscreen = DefaultScreen(display);
ScopedXFree<GLXFBConfig> cfg(xChooseFBConfig(display,
xscreen,
attribs,
&numFormats));
if (!cfg) {
return 0;
}
NS_ABORT_IF_FALSE(numFormats > 0,
"glXChooseFBConfig() failed to match our requested format and violated its spec (!)");
ScopedXFree<GLXFBConfig> cfgs(xChooseFBConfig(display,
xscreen,
attribs,
&numConfigs));
gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(aSurface);
int matchIndex = -1;
const XRenderDirectFormat& direct = format->direct;
unsigned long redMask =
static_cast<unsigned long>(direct.redMask) << direct.red;
unsigned long greenMask =
static_cast<unsigned long>(direct.greenMask) << direct.green;
unsigned long blueMask =
static_cast<unsigned long>(direct.blueMask) << direct.blue;
ScopedXFree<XVisualInfo> vinfo;
for (int i = 0; i < numConfigs; i++) {
int size;
// The visual depth won't necessarily match as it may not include the
// alpha buffer, so check buffer size.
if (sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i],
GLX_BUFFER_SIZE, &size) != Success ||
size != format->depth) {
continue;
}
vinfo = sGLXLibrary.xGetVisualFromFBConfig(display, cfgs[i]);
if (!vinfo ||
vinfo->c_class != TrueColor ||
vinfo->red_mask != redMask ||
vinfo->green_mask != greenMask ||
vinfo->blue_mask != blueMask ) {
continue;
}
matchIndex = i;
}
if (matchIndex == -1) {
NS_WARNING("[GLX] Couldn't find a FBConfig matching Pixmap format");
return None;
}
int pixmapAttribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
GLX_TEXTURE_FORMAT_EXT,
(withAlpha ? GLX_TEXTURE_FORMAT_RGBA_EXT
: GLX_TEXTURE_FORMAT_RGB_EXT),
None};
GLXPixmap glxpixmap = xCreatePixmap(display,
cfg[0],
cfgs[matchIndex],
xs->XDrawable(),
pixmapAttribs);
@ -326,7 +359,14 @@ GLXLibrary::BindTexImage(GLXPixmap aPixmap)
Display *display = DefaultXDisplay();
// Make sure all X drawing to the surface has finished before binding to a texture.
xWaitX();
if (gClientIsMesa) {
// Using XSync instead of Mesa's glXWaitX, because its glxWaitX is a
// noop when direct rendering unless the current drawable is a
// single-buffer window.
FinishX(display);
} else {
xWaitX();
}
xBindTexImage(display, aPixmap, GLX_FRONT_LEFT_EXT, NULL);
}
@ -365,7 +405,7 @@ void
GLXLibrary::AfterGLXCall()
{
if (mDebug) {
XSync(DefaultXDisplay(), False);
FinishX(DefaultXDisplay());
if (sErrorEvent.mError.error_code) {
char buffer[2048];
XGetErrorText(DefaultXDisplay(), sErrorEvent.mError.error_code, buffer, sizeof(buffer));

View File

@ -924,7 +924,8 @@ BasicLayerManager::CreateReadbackLayer()
}
BasicShadowLayerManager::BasicShadowLayerManager(nsIWidget* aWidget) :
BasicLayerManager(aWidget), mTargetRotation(ROTATION_0)
BasicLayerManager(aWidget), mTargetRotation(ROTATION_0),
mRepeatTransaction(false)
{
MOZ_COUNT_CTOR(BasicShadowLayerManager);
}

View File

@ -13,6 +13,7 @@
#include "GestureEventListener.h"
#include "nsIThreadManager.h"
#include "nsThreadUtils.h"
#include "Layers.h"
namespace mozilla {
namespace layers {
@ -697,7 +698,7 @@ void AsyncPanZoomController::RequestContentRepaint() {
bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
const FrameMetrics& aFrame,
const gfx3DMatrix& aCurrentTransform,
Layer* aLayer,
gfx3DMatrix* aNewTransform) {
// The eventual return value of this function. The compositor needs to know
// whether or not to advance by a frame as soon as it can. For example, if a
@ -706,9 +707,11 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
// responsibility to schedule a composite.
bool requestAnimationFrame = false;
const gfx3DMatrix& currentTransform = aLayer->GetTransform();
// Scales on the root layer, on what's currently painted.
float rootScaleX = aCurrentTransform.GetXScale(),
rootScaleY = aCurrentTransform.GetYScale();
float rootScaleX = currentTransform.GetXScale(),
rootScaleY = currentTransform.GetYScale();
nsIntPoint metricsScrollOffset(0, 0);
nsIntPoint scrollOffset;
@ -740,7 +743,14 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
(scrollOffset.y / rootScaleY - metricsScrollOffset.y) * localScaleY);
ViewTransform treeTransform(-scrollCompensation, localScaleX, localScaleY);
*aNewTransform = gfx3DMatrix(treeTransform) * aCurrentTransform;
*aNewTransform = gfx3DMatrix(treeTransform) * currentTransform;
// The transform already takes the resolution scale into account. Since we
// will apply the resolution scale again when computing the effective
// transform, we must apply the inverse resolution scale here.
aNewTransform->Scale(1.0f/aLayer->GetXScale(),
1.0f/aLayer->GetYScale(),
1);
mLastSampleTime = aSampleTime;

View File

@ -110,7 +110,7 @@ public:
* sampled at; this is used for interpolating animations. Calling this sets a
* new transform in |aNewTransform| which should be applied directly to the
* shadow layer of the frame (do not multiply it in as the code already does
* this internally with |aCurrentTransform|.
* this internally with |aLayer|'s transform).
*
* Return value indicates whether or not any currently running animation
* should continue. That is, if true, the compositor should schedule another
@ -118,7 +118,7 @@ public:
*/
bool SampleContentTransformForFrame(const TimeStamp& aSampleTime,
const FrameMetrics& aFrame,
const gfx3DMatrix& aCurrentTransform,
Layer* aLayer,
gfx3DMatrix* aNewTransform);
/**

View File

@ -692,7 +692,7 @@ CompositorParent::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame,
*aWantNextFrame |=
controller->SampleContentTransformForFrame(aCurrentFrame,
container->GetFrameMetrics(),
aLayer->GetTransform(),
aLayer,
&newTransform);
shadow->SetShadowTransform(newTransform);

View File

@ -187,7 +187,7 @@ ShadowLayerManager::PlatformSyncBeforeReplyUpdate()
// the child, even though they will be read operations.
// Otherwise, the child might start scribbling on new back buffers
// that are still participating in requests as old front buffers.
XSync(DefaultXDisplay(), False);
FinishX(DefaultXDisplay());
}
}

View File

@ -37,6 +37,16 @@ XVisualIDToInfo(Display* aDisplay, VisualID aVisualID,
return false;
}
void
FinishX(Display* aDisplay)
{
unsigned long lastRequest = NextRequest(aDisplay) - 1;
if (lastRequest == LastKnownRequestProcessed(aDisplay))
return;
XSync(aDisplay, False);
}
ScopedXErrorHandler::ErrorEvent* ScopedXErrorHandler::sXErrorPtr;
int
@ -67,13 +77,8 @@ ScopedXErrorHandler::~ScopedXErrorHandler()
bool
ScopedXErrorHandler::SyncAndGetError(Display *dpy, XErrorEvent *ev)
{
XSync(dpy, False);
return GetError(ev);
}
FinishX(dpy);
bool
ScopedXErrorHandler::GetError(XErrorEvent *ev)
{
bool retval = mXError.mError.error_code != 0;
if (ev)
*ev = mXError.mError;

View File

@ -52,6 +52,19 @@ bool
XVisualIDToInfo(Display* aDisplay, VisualID aVisualID,
Visual** aVisual, unsigned int* aDepth);
/**
* Ensure that all X requests have been processed.
*
* This is similar to XSync, but doesn't need a round trip if the previous
* request was synchronous or if events have been received since the last
* request. Subsequent FinishX calls will be noops if there have been no
* intermediate requests.
*/
void
FinishX(Display* aDisplay);
/**
* Invoke XFree() on a pointer to memory allocated by Xlib (if the
* pointer is nonnull) when this class goes out of scope.
@ -124,13 +137,6 @@ public:
* the first one will be returned.
*/
bool SyncAndGetError(Display *dpy, XErrorEvent *ev = nullptr);
/** Like SyncAndGetError, but does not sync. Faster, but only reliably catches errors in synchronous calls.
*
* \param ev this optional parameter, if set, will be filled with the XErrorEvent object. If multiple errors occurred,
* the first one will be returned.
*/
bool GetError(XErrorEvent *ev = nullptr);
};
} // namespace mozilla

View File

@ -82,7 +82,6 @@ enum {
static const char* DBUS_SIGNALS[] =
{
"type='signal',interface='org.freedesktop.DBus'",
"type='signal',interface='org.bluez.Adapter'",
"type='signal',interface='org.bluez.Manager'",
"type='signal',interface='org.bluez.Device'",

View File

@ -12,8 +12,6 @@ struct DBusMessage;
namespace mozilla {
namespace ipc {
class nsCString;
/**
* Starts the DBus thread, which handles returning signals to objects
* that call asynchronous functions. This should be called from the

View File

@ -23,10 +23,10 @@ using namespace js::frontend;
class AutoAttachToRuntime {
JSRuntime *rt;
public:
ScriptSource *ss;
AutoAttachToRuntime(JSRuntime *rt)
: rt(rt), ss(NULL) {}
public:
AutoAttachToRuntime(JSRuntime *rt, ScriptSource *ss)
: rt(rt), ss(ss) {}
~AutoAttachToRuntime() {
// This makes the source visible to the GC. If compilation fails, and no
// script refers to it, it will be collected.
@ -79,14 +79,14 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *call
if (!CheckLength(cx, length))
return NULL;
AutoAttachToRuntime attacher(cx->runtime);
ScriptSource *ss = cx->new_<ScriptSource>();
if (!ss)
return NULL;
AutoAttachToRuntime attacher(cx->runtime, ss);
SourceCompressionToken sct(cx);
ScriptSource *ss = NULL;
if (!cx->hasRunOption(JSOPTION_ONLY_CNG_SOURCE) || options.compileAndGo) {
ss = ScriptSource::createFromSource(cx, chars, length, false, &sct);
if (!ss)
if (!ss->setSource(cx, chars, length, false, &sct))
return NULL;
attacher.ss = ss;
}
Parser parser(cx, options, chars, length, /* foldConstants = */ true);
@ -244,13 +244,14 @@ frontend::CompileFunctionBody(JSContext *cx, HandleFunction fun, CompileOptions
Bindings *bindings, const jschar *chars, size_t length)
{
if (!CheckLength(cx, length))
return false;
AutoAttachToRuntime attacher(cx->runtime);
SourceCompressionToken sct(cx);
ScriptSource *ss = ScriptSource::createFromSource(cx, chars, length, true, &sct);
return NULL;
ScriptSource *ss = cx->new_<ScriptSource>();
if (!ss)
return NULL;
attacher.ss = ss;
AutoAttachToRuntime attacher(cx->runtime, ss);
SourceCompressionToken sct(cx);
if (!ss->setSource(cx, chars, length, true, &sct))
return NULL;
options.setCompileAndGo(false);
Parser parser(cx, options, chars, length, /* foldConstants = */ true);

View File

@ -1209,7 +1209,7 @@ TryConvertToGname(BytecodeEmitter *bce, ParseNode *pn, JSOp *op)
static bool
BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
JS_ASSERT(pn->isKind(PNK_NAME));
JS_ASSERT(pn->isKind(PNK_NAME) || pn->isKind(PNK_INTRINSICNAME));
/* Don't attempt if 'pn' is already bound or deoptimized or a nop. */
JSOp op = pn->getOp();
@ -1746,6 +1746,9 @@ EmitNameOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool callContext)
case JSOP_NAME:
op = JSOP_CALLNAME;
break;
case JSOP_INTRINSICNAME:
op = JSOP_CALLINTRINSIC;
break;
case JSOP_GETGNAME:
op = JSOP_CALLGNAME;
break;
@ -5332,12 +5335,54 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
* value required for calls (which non-strict mode functions
* will box into the global object).
*/
uint32_t argc = pn->pn_count - 1;
bool emitArgs = true;
ParseNode *pn2 = pn->pn_head;
switch (pn2->getKind()) {
case PNK_NAME:
if (!EmitNameOp(cx, bce, pn2, callop))
return false;
break;
case PNK_INTRINSICNAME:
if (pn2->atom() == cx->runtime->atomState._CallFunctionAtom)
{
/*
* Special-casing of %_CallFunction to emit bytecode that directly
* invokes the callee with the correct |this| object and arguments.
* The call %_CallFunction(receiver, ...args, fun) thus becomes:
* - emit lookup for fun
* - emit lookup for receiver
* - emit lookups for ...args
*
* argc is set to the amount of actually emitted args and the
* emitting of args below is disabled by setting emitArgs to false.
*/
if (pn->pn_count < 3) {
bce->reportError(pn, JSMSG_MORE_ARGS_NEEDED, "%_CallFunction", "1", "s");
return false;
}
ParseNode *funNode = pn2->pn_next;
while (funNode->pn_next)
funNode = funNode->pn_next;
if (!EmitTree(cx, bce, funNode))
return false;
ParseNode *receiver = pn2->pn_next;
if (!EmitTree(cx, bce, receiver))
return false;
bool oldInForInit = bce->inForInit;
bce->inForInit = false;
for (ParseNode *argpn = receiver->pn_next; argpn != funNode; argpn = argpn->pn_next) {
if (!EmitTree(cx, bce, argpn))
return false;
}
bce->inForInit = oldInForInit;
argc -= 2;
emitArgs = false;
break;
}
if (!EmitNameOp(cx, bce, pn2, callop))
return false;
break;
case PNK_DOT:
if (!EmitPropOp(cx, pn2, pn2->getOp(), bce, callop))
return false;
@ -5364,25 +5409,23 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
if (!callop && Emit1(cx, bce, JSOP_UNDEFINED) < 0)
return false;
/* Remember start of callable-object bytecode for decompilation hint. */
ptrdiff_t off = top;
/*
* Emit code for each argument in order, then emit the JSOP_*CALL or
* JSOP_NEW bytecode with a two-byte immediate telling how many args
* were pushed on the operand stack.
*/
bool oldInForInit = bce->inForInit;
bce->inForInit = false;
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
if (!EmitTree(cx, bce, pn3))
return false;
if (emitArgs) {
/*
* Emit code for each argument in order, then emit the JSOP_*CALL or
* JSOP_NEW bytecode with a two-byte immediate telling how many args
* were pushed on the operand stack.
*/
bool oldInForInit = bce->inForInit;
bce->inForInit = false;
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
if (!EmitTree(cx, bce, pn3))
return false;
}
bce->inForInit = oldInForInit;
}
bce->inForInit = oldInForInit;
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - off) < 0)
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - top) < 0)
return false;
uint32_t argc = pn->pn_count - 1;
if (Emit3(cx, bce, pn->getOp(), ARGC_HI(argc), ARGC_LO(argc)) < 0)
return false;
CheckTypeSet(cx, bce, pn->getOp());

View File

@ -35,7 +35,7 @@ UpvarCookie::set(JSContext *cx, unsigned newLevel, uint16_t newSlot)
inline PropertyName *
ParseNode::atom() const
{
JS_ASSERT(isKind(PNK_FUNCTION) || isKind(PNK_NAME));
JS_ASSERT(isKind(PNK_FUNCTION) || isKind(PNK_NAME) || isKind(PNK_INTRINSICNAME));
JSAtom *atom = isKind(PNK_FUNCTION) ? pn_funbox->function()->atom : pn_atom;
return atom->asPropertyName();
}

View File

@ -98,6 +98,7 @@ enum ParseNodeKind {
PNK_LP,
PNK_RP,
PNK_NAME,
PNK_INTRINSICNAME,
PNK_NUMBER,
PNK_STRING,
PNK_REGEXP,

View File

@ -117,7 +117,8 @@ Parser::Parser(JSContext *cx, const CompileOptions &options,
sct(NULL),
keepAtoms(cx->runtime),
foldConstants(foldConstants),
compileAndGo(options.compileAndGo)
compileAndGo(options.compileAndGo),
allowIntrinsicsCalls(options.allowIntrinsicsCalls)
{
cx->activeCompilations++;
}
@ -6497,6 +6498,30 @@ Parser::identifierName(bool afterDoubleDot)
return node;
}
ParseNode *
Parser::intrinsicName()
{
JS_ASSERT(tokenStream.isCurrentTokenType(TOK_MOD));
if (tokenStream.getToken() != TOK_NAME) {
reportError(NULL, JSMSG_SYNTAX_ERROR);
return NULL;
}
PropertyName *name = tokenStream.currentToken().name();
if (!(name == context->runtime->atomState._CallFunctionAtom ||
context->global()->hasIntrinsicFunction(context, name)))
{
reportError(NULL, JSMSG_INTRINSIC_NOT_DEFINED, JS_EncodeString(context, name));
return NULL;
}
ParseNode *node = NameNode::create(PNK_INTRINSICNAME, name, this, this->tc);
if (!node)
return NULL;
JS_ASSERT(tokenStream.currentToken().t_op == JSOP_NAME);
node->setOp(JSOP_INTRINSICNAME);
return node;
}
#if JS_HAS_XML_SUPPORT
ParseNode *
Parser::starOrAtPropertyIdentifier(TokenKind tt)
@ -7054,6 +7079,12 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
case TOK_NULL:
return new_<NullLiteral>(tokenStream.currentToken().pos);
case TOK_MOD:
if (allowIntrinsicsCalls)
return intrinsicName();
else
goto syntaxerror;
case TOK_ERROR:
/* The scanner or one of its subroutines reported the error. */
return NULL;

View File

@ -54,6 +54,12 @@ struct Parser : private AutoGCRooter
/* Script can optimize name references based on scope chain. */
const bool compileAndGo:1;
/*
* Self-hosted scripts can use the special syntax %funName(..args) to call
* internal functions.
*/
const bool allowIntrinsicsCalls:1;
public:
Parser(JSContext *cx, const CompileOptions &options,
const jschar *chars, size_t length, bool foldConstants);
@ -230,6 +236,7 @@ struct Parser : private AutoGCRooter
bool checkForFunctionNode(PropertyName *name, ParseNode *node);
ParseNode *identifierName(bool afterDoubleDot);
ParseNode *intrinsicName();
#if JS_HAS_XML_SUPPORT
// True if E4X syntax is allowed in the current syntactic context. Note this

View File

@ -25,8 +25,8 @@
namespace js {
namespace gcstats {
/* Except for the first and last, slices of less than 12ms are not reported. */
static const int64_t SLICE_MIN_REPORT_TIME = 12 * PRMJ_USEC_PER_MSEC;
/* Except for the first and last, slices of less than 42ms are not reported. */
static const int64_t SLICE_MIN_REPORT_TIME = 42 * PRMJ_USEC_PER_MSEC;
class StatisticsSerializer
{

View File

@ -352,3 +352,4 @@ MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 298, 0, JSEXN_ERR, "the 'arguments' p
MSG_DEF(JSMSG_REST_WITH_DEFAULT, 299, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 300, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default")
MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 301, 0, JSEXN_SYNTAXERR, "yield in default expression")
MSG_DEF(JSMSG_INTRINSIC_NOT_DEFINED, 302, 1, JSEXN_REFERENCEERR, "no intrinsic function {0}")

View File

@ -570,6 +570,8 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
case JSOP_RETRVAL:
case JSOP_GETGNAME:
case JSOP_CALLGNAME:
case JSOP_INTRINSICNAME:
case JSOP_CALLINTRINSIC:
case JSOP_SETGNAME:
case JSOP_REGEXP:
case JSOP_OBJECT:

View File

@ -5058,6 +5058,48 @@ ReadCompleteFile(JSContext *cx, FILE *fp, FileContents &buffer)
return true;
}
class AutoFile
{
FILE *fp_;
public:
AutoFile()
: fp_(NULL)
{}
~AutoFile()
{
if (fp_ && fp_ != stdin)
fclose(fp_);
}
FILE *fp() const { return fp_; }
bool open(JSContext *cx, const char *filename);
bool readAll(JSContext *cx, FileContents &buffer)
{
JS_ASSERT(fp_);
return ReadCompleteFile(cx, fp_, buffer);
}
};
/*
* Open a source file for reading. Supports "-" and NULL to mean stdin. The
* return value must be fclosed unless it is stdin.
*/
bool
AutoFile::open(JSContext *cx, const char *filename)
{
if (!filename || strcmp(filename, "-") == 0) {
fp_ = stdin;
} else {
fp_ = fopen(filename, "r");
if (!fp_) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN,
filename, "No such file or directory");
return false;
}
}
return true;
}
JS::CompileOptions::CompileOptions(JSContext *cx)
: principals(NULL),
originPrincipals(NULL),
@ -5067,7 +5109,8 @@ JS::CompileOptions::CompileOptions(JSContext *cx)
filename(NULL),
lineno(1),
compileAndGo(cx->hasRunOption(JSOPTION_COMPILE_N_GO)),
noScriptRval(cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL))
noScriptRval(cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL)),
allowIntrinsicsCalls(false)
{
}
@ -5122,21 +5165,11 @@ JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options, FILE *fp)
JSScript *
JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options, const char *filename)
{
FILE *fp;
if (!filename || strcmp(filename, "-") == 0) {
fp = stdin;
} else {
fp = fopen(filename, "r");
if (!fp) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN,
filename, "No such file or directory");
return NULL;
}
}
JSScript *script = Compile(cx, obj, options, fp);
if (fp != stdin)
fclose(fp);
AutoFile file;
if (!file.open(cx, filename))
return NULL;
options = options.setFileAndLine(filename, 1);
JSScript *script = Compile(cx, obj, options, file.fp());
return script;
}
@ -5624,6 +5657,21 @@ JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options,
return ok;
}
extern JS_PUBLIC_API(bool)
JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options,
const char *filename, jsval *rval)
{
FileContents buffer(cx);
{
AutoFile file;
if (!file.open(cx, filename) || !file.readAll(cx, buffer))
return NULL;
}
options = options.setFileAndLine(filename, 1);
return Evaluate(cx, obj, options, buffer.begin(), buffer.length(), rval);
}
JS_PUBLIC_API(JSBool)
JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj_,
JSPrincipals *principals,
@ -5955,10 +6003,16 @@ JS_InternJSString(JSContext *cx, JSString *str)
JS_PUBLIC_API(JSString *)
JS_InternString(JSContext *cx, const char *s)
{
return JS_InternStringN(cx, s, strlen(s));
}
JS_PUBLIC_API(JSString *)
JS_InternStringN(JSContext *cx, const char *s, size_t length)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
JSAtom *atom = js_Atomize(cx, s, strlen(s), InternAtom);
JSAtom *atom = js_Atomize(cx, s, length, InternAtom);
JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
return atom;
}

View File

@ -4090,7 +4090,7 @@ struct JSClass {
* with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
* prevously allowed, but is now an ES5 violation and thus unsupported.
*/
#define JSCLASS_GLOBAL_SLOT_COUNT (JSProto_LIMIT * 3 + 23)
#define JSCLASS_GLOBAL_SLOT_COUNT (JSProto_LIMIT * 3 + 24)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \
@ -4962,6 +4962,7 @@ struct CompileOptions {
unsigned lineno;
bool compileAndGo;
bool noScriptRval;
bool allowIntrinsicsCalls;
CompileOptions(JSContext *cx);
CompileOptions &setPrincipals(JSPrincipals *p) { principals = p; return *this; }
@ -4973,6 +4974,7 @@ struct CompileOptions {
}
CompileOptions &setCompileAndGo(bool cng) { compileAndGo = cng; return *this; }
CompileOptions &setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
CompileOptions &setAllowIntrinsicsCalls(bool aic) { allowIntrinsicsCalls = aic; return *this; }
};
extern JS_PUBLIC_API(JSScript *)
@ -5136,6 +5138,10 @@ extern JS_PUBLIC_API(bool)
Evaluate(JSContext *cx, JSHandleObject obj, CompileOptions options,
const char *bytes, size_t length, jsval *rval);
extern JS_PUBLIC_API(bool)
Evaluate(JSContext *cx, JSHandleObject obj, CompileOptions options,
const char *filename, jsval *rval);
} /* namespace JS */
JS_BEGIN_EXTERN_C
@ -5265,6 +5271,9 @@ JS_NewStringCopyZ(JSContext *cx, const char *s);
extern JS_PUBLIC_API(JSString *)
JS_InternJSString(JSContext *cx, JSString *str);
extern JS_PUBLIC_API(JSString *)
JS_InternStringN(JSContext *cx, const char *s, size_t length);
extern JS_PUBLIC_API(JSString *)
JS_InternString(JSContext *cx, const char *s);

View File

@ -149,3 +149,4 @@ DEFINE_ATOM(unescape, "unescape")
DEFINE_ATOM(uneval, "uneval")
DEFINE_ATOM(unwatch, "unwatch")
DEFINE_ATOM(watch, "watch")
DEFINE_ATOM(_CallFunction, "_CallFunction")

View File

@ -1161,14 +1161,15 @@ JSRuntime::setGCMaxMallocBytes(size_t value)
void
JSRuntime::updateMallocCounter(JSContext *cx, size_t nbytes)
{
/* We tolerate any thread races when updating gcMallocBytes. */
ptrdiff_t oldCount = gcMallocBytes;
ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
gcMallocBytes = newCount;
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
onTooMuchMalloc();
else if (cx && cx->compartment)
if (cx && cx->compartment) {
cx->compartment->updateMallocCounter(nbytes);
} else {
ptrdiff_t oldCount = gcMallocBytes;
ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
gcMallocBytes = newCount;
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
onTooMuchMalloc();
}
}
JS_FRIEND_API(void)

View File

@ -70,7 +70,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
sourceMapMap(NULL),
debugScriptMap(NULL)
{
setGCMaxMallocBytes(rt->gcMaxMallocBytes * 0.9);
setGCMaxMallocBytes(rt->gcMaxMallocBytes);
}
JSCompartment::~JSCompartment()

View File

@ -162,9 +162,9 @@ js::ShrinkingGC(JSRuntime *rt, gcreason::Reason reason)
}
JS_FRIEND_API(void)
js::IncrementalGC(JSRuntime *rt, gcreason::Reason reason)
js::IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis)
{
GCSlice(rt, GC_NORMAL, reason);
GCSlice(rt, GC_NORMAL, reason, millis);
}
JS_FRIEND_API(void)

View File

@ -707,7 +707,7 @@ extern JS_FRIEND_API(void)
ShrinkingGC(JSRuntime *rt, gcreason::Reason reason);
extern JS_FRIEND_API(void)
IncrementalGC(JSRuntime *rt, gcreason::Reason reason);
IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis = 0);
extern JS_FRIEND_API(void)
FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason);
@ -1093,6 +1093,35 @@ JS_IsFloat32Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsFloat64Array(JSObject *obj, JSContext *cx);
/*
* Unwrap Typed arrays all at once. Return NULL without throwing if the object
* cannot be viewed as the correct typed array, or the typed array object on
* success, filling both outparameters.
*/
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt8Array(JSContext *cx, JSObject *obj, uint32_t *length, int8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint8Array(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint8ClampedArray(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt16Array(JSContext *cx, JSObject *obj, uint32_t *length, int16_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint16Array(JSContext *cx, JSObject *obj, uint32_t *length, uint16_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt32Array(JSContext *cx, JSObject *obj, uint32_t *length, int32_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint32Array(JSContext *cx, JSObject *obj, uint32_t *length, uint32_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsFloat32Array(JSContext *cx, JSObject *obj, uint32_t *length, float **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsFloat64Array(JSContext *cx, JSObject *obj, uint32_t *length, double **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBufferView(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBuffer(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
/*
* Get the type of elements in a typed array.
*

View File

@ -606,8 +606,11 @@ js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lamb
}
}
bool haveSource = fun->isInterpreted();
if (haveSource && !fun->script()->scriptSource() && !fun->script()->loadSource(cx, &haveSource))
return NULL;
if (haveSource && !fun->script()->scriptSource()->hasSourceData() &&
!fun->script()->loadSource(cx, &haveSource))
{
return NULL;
}
if (haveSource) {
RootedScript script(cx, fun->script());
RootedString src(cx, fun->script()->sourceData(cx));

View File

@ -2631,8 +2631,8 @@ MaybeGC(JSContext *cx)
GCSlice(rt, GC_NORMAL, gcreason::MAYBEGC);
return;
}
double factor = rt->gcHighFrequencyGC ? 0.75 : 0.9;
double factor = rt->gcHighFrequencyGC ? 0.75 : 0.9;
JSCompartment *comp = cx->compartment;
if (comp->gcBytes > 1024 * 1024 &&
comp->gcBytes >= factor * comp->gcTriggerBytes &&
@ -4251,11 +4251,16 @@ GC(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason)
}
void
GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason)
GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason, int64_t millis)
{
int sliceBudget = rt->gcHighFrequencyGC && rt->gcDynamicMarkSlice
? rt->gcSliceBudget * IGC_MARK_SLICE_MULTIPLIER
: rt->gcSliceBudget;
int64_t sliceBudget;
if (millis)
sliceBudget = SliceBudget::TimeBudget(millis);
else if (rt->gcHighFrequencyGC && rt->gcDynamicMarkSlice)
sliceBudget = rt->gcSliceBudget * IGC_MARK_SLICE_MULTIPLIER;
else
sliceBudget = rt->gcSliceBudget;
Collect(rt, true, sliceBudget, gckind, reason);
}
@ -4265,7 +4270,6 @@ GCFinalSlice(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason)
Collect(rt, true, SliceBudget::Unlimited, gckind, reason);
}
void
GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount)
{

View File

@ -525,7 +525,7 @@ extern void
GC(JSRuntime *rt, JSGCInvocationKind gckind, js::gcreason::Reason reason);
extern void
GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, js::gcreason::Reason reason);
GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, js::gcreason::Reason reason, int64_t millis = 0);
extern void
GCFinalSlice(JSRuntime *rt, JSGCInvocationKind gckind, js::gcreason::Reason reason);

View File

@ -3394,11 +3394,13 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
}
case JSOP_NAME:
case JSOP_CALLNAME: {
case JSOP_INTRINSICNAME:
case JSOP_CALLNAME:
case JSOP_CALLINTRINSIC: {
TypeSet *seen = bytecodeTypes(pc);
addTypeBarrier(cx, pc, seen, Type::UnknownType());
seen->addSubset(cx, &pushed[0]);
if (op == JSOP_CALLNAME)
if (op == JSOP_CALLNAME || op == JSOP_CALLINTRINSIC)
pushed[0].addPropagateThis(cx, script, pc, Type::UnknownType());
break;
}

View File

@ -1418,8 +1418,6 @@ ADD_EMPTY_CASE(JSOP_NOP)
ADD_EMPTY_CASE(JSOP_UNUSED1)
ADD_EMPTY_CASE(JSOP_UNUSED2)
ADD_EMPTY_CASE(JSOP_UNUSED3)
ADD_EMPTY_CASE(JSOP_UNUSED8)
ADD_EMPTY_CASE(JSOP_UNUSED9)
ADD_EMPTY_CASE(JSOP_UNUSED10)
ADD_EMPTY_CASE(JSOP_UNUSED11)
ADD_EMPTY_CASE(JSOP_UNUSED12)
@ -2524,6 +2522,19 @@ BEGIN_CASE(JSOP_CALLNAME)
}
END_CASE(JSOP_NAME)
BEGIN_CASE(JSOP_INTRINSICNAME)
BEGIN_CASE(JSOP_CALLINTRINSIC)
{
RootedValue &rval = rootValue0;
if (!IntrinsicNameOperation(cx, script, regs.pc, rval.address()))
goto error;
PUSH_COPY(rval);
TypeScript::Monitor(cx, script, regs.pc, rval);
}
END_CASE(JSOP_INTRINSICNAME)
BEGIN_CASE(JSOP_UINT16)
PUSH_INT32((int32_t) GET_UINT16(regs.pc));
END_CASE(JSOP_UINT16)

View File

@ -21,6 +21,7 @@
#include "jsfuninlines.h"
#include "jsinferinlines.h"
#include "jsopcodeinlines.h"
#include "jspropertycacheinlines.h"
#include "jstypedarrayinlines.h"
@ -359,6 +360,17 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Val
return true;
}
inline bool
IntrinsicNameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value *vp)
{
JSOp op = JSOp(*pc);
RootedPropertyName name(cx);
name = GetNameFromBytecode(cx, script, pc, op);
JSFunction *fun = cx->global()->getIntrinsicFunction(cx, name);
vp->setObject(*fun);
return true;
}
inline bool
NameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value *vp)
{

View File

@ -350,9 +350,17 @@ OPDEF(JSOP_DECALIASEDVAR, 140,"decaliasedvar",NULL, 10, 0, 1, 15, JOF_SCOPEC
OPDEF(JSOP_ALIASEDVARINC, 141,"aliasedvarinc",NULL, 10, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
OPDEF(JSOP_ALIASEDVARDEC, 142,"aliasedvardec",NULL, 10, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
/*
* Intrinsic names have the syntax %name and can only be used when the
* CompileOptions flag "allowIntrinsicsCalls" is set.
*
* They are used to access intrinsic functions the runtime doesn't give
* client JS code access to from self-hosted code.
*/
OPDEF(JSOP_INTRINSICNAME, 143, "intrinsicname", NULL, 5, 0, 1, 19, JOF_ATOM|JOF_NAME|JOF_TYPESET)
OPDEF(JSOP_CALLINTRINSIC, 144, "callintrinsic", NULL, 5, 0, 1, 19, JOF_ATOM|JOF_NAME|JOF_TYPESET)
/* Unused. */
OPDEF(JSOP_UNUSED8, 143,"unused8", NULL, 1, 0, 0, 0, JOF_BYTE)
OPDEF(JSOP_UNUSED9, 144,"unused9", NULL, 1, 0, 0, 0, JOF_BYTE)
OPDEF(JSOP_UNUSED10, 145,"unused10", NULL, 1, 0, 0, 0, JOF_BYTE)
OPDEF(JSOP_UNUSED11, 146,"unused11", NULL, 1, 0, 0, 0, JOF_BYTE)
OPDEF(JSOP_UNUSED12, 147,"unused12", NULL, 1, 0, 0, 0, JOF_BYTE)

View File

@ -4,6 +4,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jsopcodeinlines_h__
#define jsopcodeinlines_h__
#include "jsautooplen.h"
#include "frontend/BytecodeEmitter.h"
@ -118,3 +121,5 @@ public:
};
}
#endif /* jsopcodeinlines_h__ */

View File

@ -358,8 +358,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
ParentFilename,
IsGenerator,
IsGeneratorExp,
HaveSource,
OwnSource,
HasSourceData,
ExplicitUseStrict
};
@ -519,10 +519,10 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
? (1 << ParentFilename)
: (1 << OwnFilename);
}
if (script->scriptSource()) {
scriptBits |= (1 << HaveSource);
if (!enclosingScript || enclosingScript->scriptSource() != script->scriptSource())
scriptBits |= (1 << OwnSource);
if (!enclosingScript || enclosingScript->scriptSource() != script->scriptSource()) {
scriptBits |= (1 << OwnSource);
if (script->scriptSource()->hasSourceData())
scriptBits |= (1 << HasSourceData);
}
if (script->isGenerator)
scriptBits |= (1 << IsGenerator);
@ -573,8 +573,19 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
CompileOptions options(cx);
options.setVersion(version_)
.setNoScriptRval(!!(scriptBits & (1 << NoScriptRval)));
ScriptSource *ss;
if (scriptBits & (1 << OwnSource)) {
ss = cx->new_<ScriptSource>();
if (!ss)
return NULL;
} else {
JS_ASSERT(enclosingScript);
ss = enclosingScript->scriptSource();
}
script = JSScript::Create(cx, enclosingScope, !!(scriptBits & (1 << SavedCallerFun)),
options, /* staticLevel = */ 0, NULL, 0, 0);
options, /* staticLevel = */ 0, ss, 0, 0);
if (scriptBits & (1 << OwnSource))
ss->attachToRuntime(cx->runtime);
if (!script || !JSScript::partiallyInit(cx, script,
length, nsrcnotes, natoms, nobjects,
nregexps, ntrynotes, nconsts, nClosedArgs,
@ -634,20 +645,10 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
script->filename = enclosingScript->filename;
}
if (scriptBits & (1 << HaveSource)) {
ScriptSource *ss = script->scriptSource();
if (scriptBits & (1 << OwnSource)) {
if (!ScriptSource::performXDR<mode>(xdr, &ss))
return false;
} else {
JS_ASSERT(enclosingScript);
ss = enclosingScript->scriptSource();
}
if (mode == XDR_DECODE)
script->setScriptSource(cx, ss);
} else if (mode == XDR_DECODE) {
script->setScriptSource(cx, NULL);
JS_ASSERT_IF(enclosingScript, !enclosingScript->scriptSource());
if (scriptBits & (1 << HasSourceData)) {
JS_ASSERT(scriptBits & (1 << OwnSource));
if (!script->scriptSource()->performXDR<mode>(xdr))
return false;
}
if (!xdr->codeUint32(&script->sourceStart))
return false;
@ -1127,9 +1128,10 @@ SourceCompressorThread::abort(SourceCompressionToken *userTok)
void
JSScript::setScriptSource(JSContext *cx, ScriptSource *ss)
{
JS_ASSERT(ss);
#ifdef JSGC_INCREMENTAL
// During IGC, we need to barrier writing to scriptSource_.
if (ss && cx->runtime->gcIncrementalState != NO_INCREMENTAL && cx->runtime->gcIsFull)
if (cx->runtime->gcIncrementalState != NO_INCREMENTAL && cx->runtime->gcIsFull)
ss->mark();
#endif
scriptSource_ = ss;
@ -1138,7 +1140,7 @@ JSScript::setScriptSource(JSContext *cx, ScriptSource *ss)
bool
JSScript::loadSource(JSContext *cx, bool *worked)
{
JS_ASSERT(!scriptSource_);
JS_ASSERT(!scriptSource_->hasSourceData());
*worked = false;
if (!cx->runtime->sourceHook)
return true;
@ -1148,13 +1150,8 @@ JSScript::loadSource(JSContext *cx, bool *worked)
return false;
if (!src)
return true;
ScriptSource *ss = ScriptSource::createFromSource(cx, src, length, false, NULL, true);
if (!ss) {
cx->free_(src);
return false;
}
setScriptSource(cx, ss);
ss->attachToRuntime(cx->runtime);
ScriptSource *ss = scriptSource();
JS_ALWAYS_TRUE(ss->setSource(cx, src, length, false, NULL, true));
*worked = true;
return true;
}
@ -1162,7 +1159,7 @@ JSScript::loadSource(JSContext *cx, bool *worked)
JSFixedString *
JSScript::sourceData(JSContext *cx)
{
JS_ASSERT(scriptSource_);
JS_ASSERT(scriptSource_->hasSourceData());
return scriptSource_->substring(cx, sourceStart, sourceEnd);
}
@ -1238,51 +1235,44 @@ ScriptSource::substring(JSContext *cx, uint32_t start, uint32_t stop)
return js_NewStringCopyN(cx, chars + start, stop - start);
}
ScriptSource *
ScriptSource::createFromSource(JSContext *cx, const jschar *src, uint32_t length,
bool argumentsNotIncluded, SourceCompressionToken *tok,
bool ownSource)
bool
ScriptSource::setSource(JSContext *cx, const jschar *src, uint32_t length,
bool argumentsNotIncluded, SourceCompressionToken *tok,
bool ownSource)
{
ScriptSource *ss = static_cast<ScriptSource *>(cx->runtime->malloc_(sizeof(*ss)));
if (!ss)
return NULL;
JS_ASSERT(!hasSourceData());
if (!ownSource) {
const size_t nbytes = length * sizeof(jschar);
ss->data.compressed = static_cast<unsigned char *>(cx->runtime->malloc_(nbytes));
if (!ss->data.compressed) {
cx->free_(ss);
return NULL;
}
data.compressed = static_cast<unsigned char *>(cx->malloc_(nbytes));
if (!data.compressed)
return false;
}
ss->next = NULL;
ss->length_ = length;
ss->compressedLength_ = 0;
ss->marked = ss->onRuntime_ = false;
ss->argumentsNotIncluded_ = argumentsNotIncluded;
#ifdef DEBUG
ss->ready_ = false;
#endif
length_ = length;
argumentsNotIncluded_ = argumentsNotIncluded;
JS_ASSERT_IF(ownSource, !tok);
#ifdef JS_THREADSAFE
if (tok && !ownSource) {
tok->ss = ss;
#ifdef DEBUG
ready_ = false;
#endif
tok->ss = this;
tok->chars = src;
cx->runtime->sourceCompressorThread.compress(tok);
} else
#endif
{
if (ownSource)
ss->data.source = const_cast<jschar *>(src);
data.source = const_cast<jschar *>(src);
else
PodCopy(ss->data.source, src, ss->length_);
PodCopy(data.source, src, length_);
#ifdef DEBUG
ss->ready_ = true;
ready_ = true;
#endif
}
return ss;
return true;
}
void
@ -1355,69 +1345,50 @@ ScriptSource::sweep(JSRuntime *rt)
template<XDRMode mode>
bool
ScriptSource::performXDR(XDRState<mode> *xdr, ScriptSource **ssp)
ScriptSource::performXDR(XDRState<mode> *xdr)
{
class Cleanup {
JSContext *cx;
ScriptSource *ss;
public:
explicit Cleanup(JSContext *cx)
: cx(cx), ss(NULL) {}
~Cleanup()
{
if (ss) {
if (ss->data.compressed)
cx->free_(ss->data.compressed);
cx->free_(ss);
}
uint8_t hasSource = hasSourceData();
if (!xdr->codeUint8(&hasSource))
return false;
if (hasSource) {
// Only set members when we know decoding cannot fail. This prevents the
// script source from being partially initialized.
uint32_t length = length_;
if (!xdr->codeUint32(&length))
return false;
uint32_t compressedLength = compressedLength_;
if (!xdr->codeUint32(&compressedLength))
return false;
uint8_t argumentsNotIncluded = argumentsNotIncluded_;
if (!xdr->codeUint8(&argumentsNotIncluded))
return false;
size_t byteLen = compressedLength ? compressedLength : (length * sizeof(jschar));
if (mode == XDR_DECODE) {
data.compressed = static_cast<unsigned char *>(xdr->cx()->malloc_(byteLen));
if (!data.compressed)
return false;
}
void protect(ScriptSource *source) { ss = source; }
void release() { ss = NULL; }
} cleanup(xdr->cx());
ScriptSource *ss = *ssp;
if (mode == XDR_DECODE) {
*ssp = static_cast<ScriptSource *>(xdr->cx()->malloc_(sizeof(ScriptSource)));
ss = *ssp;
if (!ss)
if (!xdr->codeBytes(data.compressed, byteLen)) {
if (mode == XDR_DECODE) {
xdr->cx()->free_(data.compressed);
data.compressed = NULL;
}
return false;
ss->marked = ss->onRuntime_ = ss->argumentsNotIncluded_ = false;
#ifdef DEBUG
ss->ready_ = false;
#endif
ss->data.compressed = NULL;
cleanup.protect(ss);
#ifdef JSGC_INCREMENTAL
// See comment in ScriptSource::createFromSource.
if (xdr->cx()->runtime->gcIncrementalState != NO_INCREMENTAL &&
xdr->cx()->runtime->gcIsFull)
ss->marked = true;
#endif
}
length_ = length;
compressedLength_ = compressedLength;
argumentsNotIncluded_ = argumentsNotIncluded;
}
if (!xdr->codeUint32(&ss->length_))
return false;
if (!xdr->codeUint32(&ss->compressedLength_))
return false;
uint8_t argumentsNotIncluded = ss->argumentsNotIncluded_;
if (!xdr->codeUint8(&argumentsNotIncluded))
return false;
ss->argumentsNotIncluded_ = argumentsNotIncluded;
size_t byteLen = ss->compressed() ? ss->compressedLength_ : (ss->length_ * sizeof(jschar));
if (mode == XDR_DECODE) {
ss->data.compressed = static_cast<unsigned char *>(xdr->cx()->malloc_(byteLen));
if (!ss->data.compressed)
return false;
}
if (!xdr->codeBytes(ss->data.compressed, byteLen))
return false;
if (mode == XDR_DECODE) {
#ifdef DEBUG
ss->ready_ = true;
if (mode == XDR_DECODE)
ready_ = true;
#endif
ss->attachToRuntime(xdr->cx()->runtime);
cleanup.release();
}
return true;
}
@ -2637,7 +2608,7 @@ JSScript::markChildren(JSTracer *trc)
if (filename)
MarkScriptFilename(trc->runtime, filename);
if (trc->runtime->gcIsFull && scriptSource_)
if (trc->runtime->gcIsFull)
scriptSource_->mark();
}

View File

@ -997,21 +997,40 @@ struct ScriptSource
#endif
public:
static ScriptSource *createFromSource(JSContext *cx,
const jschar *src,
uint32_t length,
bool argumentsNotIncluded = false,
SourceCompressionToken *tok = NULL,
bool ownSource = false);
ScriptSource()
: next(NULL),
length_(0),
compressedLength_(0),
marked(false),
onRuntime_(false),
argumentsNotIncluded_(false)
#ifdef DEBUG
,ready_(true)
#endif
{
data.source = NULL;
}
bool setSource(JSContext *cx,
const jschar *src,
uint32_t length,
bool argumentsNotIncluded = false,
SourceCompressionToken *tok = NULL,
bool ownSource = false);
void attachToRuntime(JSRuntime *rt);
void mark() { marked = true; }
void destroy(JSRuntime *rt);
uint32_t length() const { return length_; }
bool onRuntime() const { return onRuntime_; }
bool argumentsNotIncluded() const { return argumentsNotIncluded_; }
#ifdef DEBUG
bool ready() const { return ready_; }
#endif
bool hasSourceData() const { return !!data.source; }
uint32_t length() const {
JS_ASSERT(hasSourceData());
return length_;
}
bool argumentsNotIncluded() const {
JS_ASSERT(hasSourceData());
return argumentsNotIncluded_;
}
JSFixedString *substring(JSContext *cx, uint32_t start, uint32_t stop);
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf);
@ -1020,9 +1039,10 @@ struct ScriptSource
// XDR handling
template <XDRMode mode>
static bool performXDR(XDRState<mode> *xdr, ScriptSource **ss);
bool performXDR(XDRState<mode> *xdr);
private:
void destroy(JSRuntime *rt);
bool compressed() { return compressedLength_ != 0; }
};

View File

@ -2920,8 +2920,11 @@ JSFunctionSpec _typedArray::jsfuncs[] = { \
} \
JS_FRIEND_API(JSBool) JS_Is ## Name ## Array(JSObject *obj, JSContext *cx) \
{ \
if (!(obj = UnwrapObjectChecked(cx, obj))) \
MOZ_ASSERT(!cx->isExceptionPending()); \
if (!(obj = UnwrapObjectChecked(cx, obj))) { \
cx->clearPendingException(); \
return false; \
} \
Class *clasp = obj->getClass(); \
return (clasp == &TypedArray::classes[TypedArrayTemplate<NativeType>::ArrayTypeID()]); \
}
@ -2936,6 +2939,40 @@ IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint32, uint32_t)
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float32, float)
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float64, double)
#define IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Name, ExternalType, InternalType) \
JS_FRIEND_API(JSObject *) JS_GetObjectAs ## Name ## Array(JSContext *cx, \
JSObject *obj, \
uint32_t *length, \
ExternalType **data) \
{ \
if (obj->isWrapper()) { \
MOZ_ASSERT(!cx->isExceptionPending()); \
if (!(obj = UnwrapObjectChecked(cx, obj))) { \
cx->clearPendingException(); \
return NULL; \
} \
} \
\
Class *clasp = obj->getClass(); \
if (clasp != &TypedArray::classes[TypedArrayTemplate<InternalType>::ArrayTypeID()]) \
return NULL; \
\
*length = obj->getSlot(TypedArray::FIELD_LENGTH).toInt32(); \
*data = static_cast<ExternalType *>(TypedArray::viewData(obj)); \
\
return obj; \
}
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Int8, int8_t, int8_t)
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint8, uint8_t, uint8_t)
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint8Clamped, uint8_t, uint8_clamped)
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Int16, int16_t, int16_t)
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint16, uint16_t, uint16_t)
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Int32, int32_t, int32_t)
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint32, uint32_t, uint32_t)
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float32, float, float)
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
#define IMPL_TYPED_ARRAY_PROTO_CLASS(_typedArray) \
{ \
#_typedArray "Prototype", \
@ -3558,3 +3595,42 @@ JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx)
? obj->asDataView().byteLength()
: TypedArray::byteLengthValue(obj).toInt32();
}
JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBufferView(JSContext *cx, JSObject *obj,
uint32_t *length, uint8_t **data)
{
if (obj->isWrapper()) {
if (!(obj = UnwrapObjectChecked(cx, obj))) {
cx->clearPendingException();
return NULL;
}
}
if (!(obj->isTypedArray() || obj->isDataView()))
return NULL;
*length = obj->isDataView() ? obj->asDataView().byteLength()
: TypedArray::byteLengthValue(obj).toInt32();
*data = static_cast<uint8_t *>(obj->isDataView() ? obj->asDataView().dataPointer()
: TypedArray::viewData(obj));
return obj;
}
JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBuffer(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data)
{
if (obj->isWrapper()) {
if (!(obj = UnwrapObjectChecked(cx, obj))) {
cx->clearPendingException();
return NULL;
}
}
if (!obj->isArrayBuffer())
return NULL;
*length = obj->asArrayBuffer().byteLength();
*data = obj->asArrayBuffer().dataPointer();
return obj;
}

View File

@ -2645,6 +2645,15 @@ mjit::Compiler::generateMethod()
}
END_CASE(JSOP_NAME)
BEGIN_CASE(JSOP_INTRINSICNAME)
BEGIN_CASE(JSOP_CALLINTRINSIC)
{
PropertyName *name = script->getName(GET_UINT32_INDEX(PC));
jsop_intrinsicname(name, knownPushedType(0));
frame.extra(frame.peek(-1)).name = name;
}
END_CASE(JSOP_INTRINSICNAME)
BEGIN_CASE(JSOP_IMPLICITTHIS)
{
prepareStubCall(Uses(0));
@ -5552,6 +5561,13 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed)
return true;
}
void
mjit::Compiler::jsop_intrinsicname(PropertyName *name, JSValueType type)
{
JSFunction *fun = cx->global().get()->getIntrinsicFunction(cx, name);
frame.push(ObjectValue(*fun));
}
void
mjit::Compiler::jsop_name(PropertyName *name, JSValueType type)
{

View File

@ -653,6 +653,7 @@ private:
bool jsop_setprop(PropertyName *name, bool popGuaranteed);
void jsop_setprop_slow(PropertyName *name);
bool jsop_instanceof();
void jsop_intrinsicname(PropertyName *name, JSValueType type);
void jsop_name(PropertyName *name, JSValueType type);
bool jsop_xname(PropertyName *name);
void enterBlock(StaticBlockObject *block);

View File

@ -713,15 +713,13 @@ Load(JSContext *cx, unsigned argc, jsval *vp)
if (!filename)
return false;
errno = 0;
uint32_t oldopts = JS_GetOptions(cx);
JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
JSScript *script = JS_CompileUTF8File(cx, thisobj, filename.ptr());
JS_SetOptions(cx, oldopts);
if (!script)
return false;
if (!compileOnly && !JS_ExecuteScript(cx, thisobj, script, NULL))
CompileOptions opts(cx);
opts.setCompileAndGo(true).setNoScriptRval(true);
if ((compileOnly && !Compile(cx, thisobj, opts, filename.ptr())) ||
!Evaluate(cx, thisobj, opts, filename.ptr(), NULL))
{
return false;
}
}
JS_SET_RVAL(cx, vp, JSVAL_VOID);

View File

@ -213,6 +213,13 @@ GlobalObject::setProtoGetter(JSFunction *protoGetter)
setSlot(PROTO_GETTER, ObjectValue(*protoGetter));
}
void
GlobalObject::setIntrinsicsHolder(JSObject *obj)
{
JS_ASSERT(getSlotRef(INTRINSICS).isUndefined());
setSlot(INTRINSICS, ObjectValue(*obj));
}
} // namespace js
#endif

View File

@ -173,6 +173,10 @@ ProtoSetter(JSContext *cx, unsigned argc, Value *vp)
return CallNonGenericMethod(cx, TestProtoSetterThis, ProtoSetterImpl, args);
}
JSFunctionSpec intrinsic_functions[] = {
JS_FN("ThrowTypeError", ThrowTypeError, 0,0),
JS_FS_END
};
JSObject *
GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
{
@ -234,10 +238,12 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
jschar *source = InflateString(cx, rawSource, &sourceLen);
if (!source)
return NULL;
ScriptSource *ss = ScriptSource::createFromSource(cx, source, sourceLen);
cx->free_(source);
if (!ss)
ScriptSource *ss = cx->new_<ScriptSource>();
if (!ss) {
cx->free_(source);
return NULL;
}
JS_ALWAYS_TRUE(ss->setSource(cx, source, sourceLen, false, NULL, true));
CompileOptions options(cx);
options.setNoScriptRval(true)
@ -369,14 +375,20 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
self->setOriginalEval(evalobj);
/* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
RootedFunction throwTypeError(cx);
throwTypeError = js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL);
RootedFunction throwTypeError(cx, js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL));
if (!throwTypeError)
return NULL;
if (!throwTypeError->preventExtensions(cx))
return NULL;
self->setThrowTypeError(throwTypeError);
RootedObject intrinsicsHolder(cx, JS_NewObject(cx, NULL, NULL, self));
if (!intrinsicsHolder)
return NULL;
self->setIntrinsicsHolder(intrinsicsHolder);
if (!JS_DefineFunctions(cx, intrinsicsHolder, intrinsic_functions))
return NULL;
/*
* The global object should have |Object.prototype| as its [[Prototype]].
* Eventually we'd like to have standard classes be there from the start,
@ -482,6 +494,7 @@ GlobalObject::clear(JSContext *cx)
setSlot(EVAL, UndefinedValue());
setSlot(CREATE_DATAVIEW_FOR_THIS, UndefinedValue());
setSlot(THROWTYPEERROR, UndefinedValue());
setSlot(INTRINSICS, UndefinedValue());
setSlot(PROTO_GETTER, UndefinedValue());
/*

View File

@ -100,9 +100,10 @@ class GlobalObject : public JSObject
static const unsigned RUNTIME_CODEGEN_ENABLED = FUNCTION_NS + 1;
static const unsigned FLAGS = RUNTIME_CODEGEN_ENABLED + 1;
static const unsigned DEBUGGERS = FLAGS + 1;
static const unsigned INTRINSICS = DEBUGGERS + 1;
/* Total reserved-slot count for global objects. */
static const unsigned RESERVED_SLOTS = DEBUGGERS + 1;
static const unsigned RESERVED_SLOTS = INTRINSICS + 1;
void staticAsserts() {
/*
@ -135,6 +136,8 @@ class GlobalObject : public JSObject
inline void setOriginalEval(JSObject *evalobj);
inline void setProtoGetter(JSFunction *protoGetter);
inline void setIntrinsicsHolder(JSObject *obj);
Value getConstructor(JSProtoKey key) const {
JS_ASSERT(key <= JSProto_LIMIT);
return getSlot(key);
@ -360,6 +363,20 @@ class GlobalObject : public JSObject
return &self->getPrototype(JSProto_DataView).toObject();
}
bool hasIntrinsicFunction(JSContext *cx, PropertyName *name) {
RootedObject holder(cx, &getSlotRef(INTRINSICS).toObject());
Value fun = NullValue();
return HasDataProperty(cx, holder, NameToId(name), &fun);
}
JSFunction *getIntrinsicFunction(JSContext *cx, PropertyName *name) {
RootedObject holder(cx, &getSlotRef(INTRINSICS).toObject());
Value fun = NullValue();
DebugOnly<bool> ok = HasDataProperty(cx, holder, NameToId(name), &fun);
JS_ASSERT(ok);
return fun.toObject().toFunction();
}
inline RegExpStatics *getRegExpStatics() const;
JSObject *getThrowTypeError() const {

View File

@ -25,7 +25,7 @@ namespace js {
* and saved versions. If deserialization fails, the data should be
* invalidated if possible.
*/
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 124);
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 126);
class XDRBuffer {
public:

View File

@ -1382,8 +1382,8 @@ abstract public class GeckoApp
mFullScreenPluginContainer = new FullScreenHolder(this);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT,
Gravity.CENTER);
mFullScreenPluginContainer.addView(view, layoutParams);

View File

@ -21,6 +21,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/last_tab_favicon"
android:layout_marginTop="2dip"
android:layout_marginLeft="12dip"
android:layout_marginRight="12dip"
android:textSize="15sp"

View File

@ -4,12 +4,12 @@
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView android:id="@+id/preview"
android:layout_width="match_parent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#ffffffff"
@ -23,20 +23,20 @@
android:fadeScrollbars="true"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button android:id="@+id/decrease_preview_font_button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:text="@string/pref_font_size_adjust_char"
android:textSize="8sp"/>
<Button android:id="@+id/increase_preview_font_button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:text="@string/pref_font_size_adjust_char"
android:textSize="16sp"/>

View File

@ -8,7 +8,7 @@
<ListView
android:id="@+id/device_list"
android:layout_width="match_parent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/sendtab_top"
android:layout_above="@+id/sendtab_bottom" >
@ -25,4 +25,4 @@
android:enabled="false"
android:text="@string/sync_button_send" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>

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