mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
commit
e5de263e59
@ -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 = [];
|
||||
|
@ -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)
|
||||
|
55
build/unix/build-clang/create-manifest.py
Executable file
55
build/unix/build-clang/create-manifest.py
Executable 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)
|
@ -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,
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -189,7 +189,7 @@ nsHTMLAudioElement::MozCurrentSampleOffset(PRUint64 *aRetVal)
|
||||
if (position < 0) {
|
||||
*aRetVal = 0;
|
||||
} else {
|
||||
*aRetVal = mAudioStream->GetPositionInFrames() * mChannels;
|
||||
*aRetVal = position * mChannels;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -524,6 +524,7 @@ DOMCI_CLASS(BluetoothManager)
|
||||
DOMCI_CLASS(BluetoothAdapter)
|
||||
DOMCI_CLASS(BluetoothDevice)
|
||||
DOMCI_CLASS(BluetoothDeviceEvent)
|
||||
DOMCI_CLASS(BluetoothPropertyEvent)
|
||||
#endif
|
||||
|
||||
DOMCI_CLASS(CameraManager)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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__
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "BluetoothDeviceEvent.h"
|
||||
#include "BluetoothTypes.h"
|
||||
#include "BluetoothDevice.h"
|
||||
#include "nsIDOMDOMRequest.h"
|
||||
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
|
@ -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!");
|
||||
|
@ -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)
|
||||
};
|
||||
|
76
dom/bluetooth/BluetoothPropertyContainer.cpp
Normal file
76
dom/bluetooth/BluetoothPropertyContainer.cpp
Normal 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;
|
||||
}
|
75
dom/bluetooth/BluetoothPropertyContainer.h
Normal file
75
dom/bluetooth/BluetoothPropertyContainer.h
Normal 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
|
53
dom/bluetooth/BluetoothPropertyEvent.cpp
Normal file
53
dom/bluetooth/BluetoothPropertyEvent.cpp
Normal 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;
|
||||
}
|
66
dom/bluetooth/BluetoothPropertyEvent.h
Normal file
66
dom/bluetooth/BluetoothPropertyEvent.h
Normal 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
|
@ -7,8 +7,6 @@
|
||||
#include "base/basictypes.h"
|
||||
#include "BluetoothTypes.h"
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
#include "nsIDOMDOMRequest.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
|
@ -9,10 +9,9 @@
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDOMDOMRequest.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
class nsIDOMDOMRequest;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothReply;
|
||||
|
@ -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()
|
||||
{
|
||||
|
61
dom/bluetooth/BluetoothUtils.cpp
Normal file
61
dom/bluetooth/BluetoothUtils.cpp
Normal 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;
|
||||
}
|
||||
|
24
dom/bluetooth/BluetoothUtils.h
Normal file
24
dom/bluetooth/BluetoothUtils.h
Normal 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
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
13
dom/bluetooth/nsIDOMBluetoothPropertyEvent.idl
Normal file
13
dom/bluetooth/nsIDOMBluetoothPropertyEvent.idl
Normal 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;
|
||||
};
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CameraPreview, CameraPreview)
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(CameraPreview, CameraPreview)
|
||||
|
||||
class CameraPreviewListener : public MediaStreamListener
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -162,7 +162,7 @@ public:
|
||||
|
||||
void
|
||||
Send(ArrayBuffer& aBody, ErrorResult& aRv) {
|
||||
return Send(aBody.mObj, aRv);
|
||||
return Send(aBody.Obj(), aRv);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -163,8 +163,6 @@ private:
|
||||
*/
|
||||
void *mData;
|
||||
|
||||
SurfaceFormat mFormat;
|
||||
|
||||
RefPtr<SourceSurfaceCGContext> mSnapshot;
|
||||
};
|
||||
|
||||
|
@ -1415,7 +1415,7 @@ public:
|
||||
if (mBackingSurface && mUpdateSurface == mBackingSurface) {
|
||||
#ifdef MOZ_X11
|
||||
if (mBackingSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
|
||||
XSync(DefaultXDisplay(), False);
|
||||
FinishX(DefaultXDisplay());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
|
@ -692,7 +692,7 @@ CompositorParent::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame,
|
||||
*aWantNextFrame |=
|
||||
controller->SampleContentTransformForFrame(aCurrentFrame,
|
||||
container->GetFrameMetrics(),
|
||||
aLayer->GetTransform(),
|
||||
aLayer,
|
||||
&newTransform);
|
||||
|
||||
shadow->SetShadowTransform(newTransform);
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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'",
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ enum ParseNodeKind {
|
||||
PNK_LP,
|
||||
PNK_RP,
|
||||
PNK_NAME,
|
||||
PNK_INTRINSICNAME,
|
||||
PNK_NUMBER,
|
||||
PNK_STRING,
|
||||
PNK_REGEXP,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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}")
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -149,3 +149,4 @@ DEFINE_ATOM(unescape, "unescape")
|
||||
DEFINE_ATOM(uneval, "uneval")
|
||||
DEFINE_ATOM(unwatch, "unwatch")
|
||||
DEFINE_ATOM(watch, "watch")
|
||||
DEFINE_ATOM(_CallFunction, "_CallFunction")
|
||||
|
@ -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)
|
||||
|
@ -70,7 +70,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
||||
sourceMapMap(NULL),
|
||||
debugScriptMap(NULL)
|
||||
{
|
||||
setGCMaxMallocBytes(rt->gcMaxMallocBytes * 0.9);
|
||||
setGCMaxMallocBytes(rt->gcMaxMallocBytes);
|
||||
}
|
||||
|
||||
JSCompartment::~JSCompartment()
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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__ */
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
||||
/*
|
||||
|
@ -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 {
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"/>
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user