Bug 897678 - Make worker code stop using propertyops, as a step toward removing propertyops altogether. r=mrbkap

--HG--
extra : rebase_source : 17c2fccbde0b813fcff2b780c1896e35034c071d
This commit is contained in:
Jeff Walden 2013-08-08 15:55:23 -07:00
parent f52f1aa9dc
commit 23303fa434
5 changed files with 500 additions and 335 deletions

View File

@ -7,6 +7,7 @@
#include "mozilla/Util.h"
#include "Events.h"
#include "mozilla/dom/BindingUtils.h"
#include "jsapi.h"
#include "jsfriendapi.h"
@ -16,15 +17,9 @@
#include "WorkerInlines.h"
#include "WorkerPrivate.h"
#define PROPERTY_FLAGS \
(JSPROP_ENUMERATE | JSPROP_SHARED)
#define FUNCTION_FLAGS \
JSPROP_ENUMERATE
#define CONSTANT_FLAGS \
JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_PERMANENT | JSPROP_READONLY
using namespace mozilla;
USING_WORKERS_NAMESPACE
@ -37,7 +32,7 @@ class Event : public PrivatizableBase
static const JSPropertySpec sProperties[];
static const JSFunctionSpec sFunctions[];
static const JSPropertySpec sStaticProperties[];
static const dom::ConstantSpec sStaticConstants[];
protected:
bool mStopPropagationCalled;
@ -77,9 +72,18 @@ public:
JSClass* clasp = parentProto ? &sMainRuntimeClass : &sClass;
JS::Rooted<JSObject*> proto(aCx, JS_InitClass(aCx, aObj, parentProto, clasp, Construct, 0,
sProperties, sFunctions, sStaticProperties,
nullptr));
if (proto && !JS_DefineProperties(aCx, proto, sStaticProperties)) {
sProperties, sFunctions, nullptr, nullptr));
if (!proto) {
return NULL;
}
JS::Rooted<JSObject*> ctor(aCx, JS_GetConstructor(aCx, proto));
if (!ctor) {
return NULL;
}
if (!dom::DefineConstants(aCx, ctor, sStaticConstants) ||
!dom::DefineConstants(aCx, proto, sStaticConstants)) {
return NULL;
}
@ -145,7 +149,7 @@ protected:
MOZ_COUNT_DTOR(mozilla::dom::workers::Event);
}
enum {
enum EventPhase {
CAPTURING_PHASE = 1,
AT_TARGET = 2,
BUBBLING_PHASE = 3
@ -220,34 +224,34 @@ private:
}
static bool
GetProperty(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
IsEvent(JS::Handle<JS::Value> v)
{
JS_ASSERT(JSID_IS_INT(aIdval));
int32_t slot = JSID_TO_INT(aIdval);
const char* name = sProperties[slot - SLOT_FIRST].name;
if (!GetInstancePrivate(aCx, aObj, name)) {
return false;
}
aVp.set(JS_GetReservedSlot(aObj, slot));
return true;
return v.isObject() && GetPrivate(&v.toObject()) != nullptr;
}
template<SLOT Slot>
static bool
GetConstant(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> idval,
JS::MutableHandle<JS::Value> aVp)
GetPropertyImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS_ASSERT(JSID_IS_INT(idval));
JS_ASSERT(JSID_TO_INT(idval) >= CAPTURING_PHASE &&
JSID_TO_INT(idval) <= BUBBLING_PHASE);
aVp.set(INT_TO_JSVAL(JSID_TO_INT(idval)));
aArgs.rval().set(JS_GetReservedSlot(&aArgs.thisv().toObject(), Slot));
return true;
}
// This struct (versus just templating the method directly) is needed only for
// gcc 4.4 (and maybe 4.5 -- 4.6 is okay) being too braindead to allow
// GetProperty<Slot> and friends in the JSPropertySpec[] below.
template<SLOT Slot>
struct Property
{
static bool
Get(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
static_assert(SLOT_FIRST <= Slot && Slot < SLOT_COUNT, "bad slot");
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsEvent, GetPropertyImpl<Slot> >(aCx, args);
}
};
static bool
StopPropagation(JSContext* aCx, unsigned aArgc, jsval* aVp)
{
@ -343,25 +347,25 @@ DECL_EVENT_CLASS(Event::sMainRuntimeClass, "WorkerEvent")
#undef DECL_EVENT_CLASS
const JSPropertySpec Event::sProperties[] = {
{ "type", SLOT_type, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "target", SLOT_target, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "currentTarget", SLOT_currentTarget, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "eventPhase", SLOT_eventPhase, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "bubbles", SLOT_bubbles, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "cancelable", SLOT_cancelable, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "timeStamp", SLOT_timeStamp, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "defaultPrevented", SLOT_defaultPrevented, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "isTrusted", SLOT_isTrusted, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
JS_PSGS("type", Property<SLOT_type>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("target", Property<SLOT_target>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("currentTarget", Property<SLOT_currentTarget>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("eventPhase", Property<SLOT_eventPhase>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("bubbles", Property<SLOT_bubbles>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("cancelable", Property<SLOT_cancelable>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("timeStamp", Property<SLOT_timeStamp>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("defaultPrevented", Property<SLOT_defaultPrevented>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("isTrusted", Property<SLOT_isTrusted>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PS_END
};
const JSFunctionSpec Event::sFunctions[] = {
@ -372,13 +376,11 @@ const JSFunctionSpec Event::sFunctions[] = {
JS_FS_END
};
const JSPropertySpec Event::sStaticProperties[] = {
{ "CAPTURING_PHASE", CAPTURING_PHASE, CONSTANT_FLAGS,
JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER },
{ "AT_TARGET", AT_TARGET, CONSTANT_FLAGS, JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER },
{ "BUBBLING_PHASE", BUBBLING_PHASE, CONSTANT_FLAGS,
JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER },
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
const dom::ConstantSpec Event::sStaticConstants[] = {
{ "CAPTURING_PHASE", JS::Int32Value(CAPTURING_PHASE) },
{ "AT_TARGET", JS::Int32Value(AT_TARGET) },
{ "BUBBLING_PHASE", JS::Int32Value(BUBBLING_PHASE) },
{ nullptr, JS::UndefinedValue() }
};
class MessageEvent : public Event
@ -507,23 +509,27 @@ private:
}
static bool
GetProperty(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
IsMessageEvent(JS::Handle<JS::Value> v)
{
JS_ASSERT(JSID_IS_INT(aIdval));
int32_t slot = JSID_TO_INT(aIdval);
JS_ASSERT(slot >= SLOT_data && slot < SLOT_COUNT);
const char* name = sProperties[slot - SLOT_FIRST].name;
MessageEvent* event = GetInstancePrivate(aCx, aObj, name);
if (!event) {
if (!v.isObject())
return false;
}
JSObject* obj = &v.toObject();
return IsThisClass(JS_GetClass(obj)) &&
GetJSPrivateSafeish<MessageEvent>(obj) != nullptr;
}
template<SLOT Slot>
static bool
GetPropertyImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
const char* name = sProperties[Slot - SLOT_FIRST].name;
MessageEvent* event = GetInstancePrivate(aCx, obj, name);
MOZ_ASSERT(event);
// Deserialize and save the data value if we can.
if (slot == SLOT_data && event->mBuffer.data()) {
if (Slot == SLOT_data && event->mBuffer.data()) {
JSAutoStructuredCloneBuffer buffer;
buffer.swap(event->mBuffer);
@ -537,16 +543,31 @@ private:
WorkerStructuredCloneCallbacks(event->mMainRuntime))) {
return false;
}
JS_SetReservedSlot(aObj, slot, data);
JS_SetReservedSlot(obj, Slot, data);
aVp.set(data);
aArgs.rval().set(data);
return true;
}
aVp.set(JS_GetReservedSlot(aObj, slot));
aArgs.rval().set(JS_GetReservedSlot(obj, Slot));
return true;
}
// This struct (versus just templating the method directly) is needed only for
// gcc 4.4 (and maybe 4.5 -- 4.6 is okay) being too braindead to allow
// GetProperty<Slot> and friends in the JSPropertySpec[] below.
template<SLOT Slot>
struct Property
{
static bool
Get(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
static_assert(SLOT_FIRST <= Slot && Slot < SLOT_COUNT, "bad slot");
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsMessageEvent, GetPropertyImpl<Slot> >(aCx, args);
}
};
static bool
InitMessageEvent(JSContext* aCx, unsigned aArgc, jsval* aVp)
{
@ -589,13 +610,13 @@ DECL_MESSAGEEVENT_CLASS(MessageEvent::sMainRuntimeClass, "WorkerMessageEvent")
#undef DECL_MESSAGEEVENT_CLASS
const JSPropertySpec MessageEvent::sProperties[] = {
{ "data", SLOT_data, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "origin", SLOT_origin, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "source", SLOT_source, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
JS_PSGS("data", Property<SLOT_data>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("origin", Property<SLOT_origin>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("source", Property<SLOT_source>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PS_END
};
const JSFunctionSpec MessageEvent::sFunctions[] = {
@ -715,25 +736,38 @@ private:
}
static bool
GetProperty(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
IsErrorEvent(JS::Handle<JS::Value> v)
{
JS_ASSERT(JSID_IS_INT(aIdval));
int32_t slot = JSID_TO_INT(aIdval);
JS_ASSERT(slot >= SLOT_message && slot < SLOT_COUNT);
const char* name = sProperties[slot - SLOT_FIRST].name;
ErrorEvent* event = GetInstancePrivate(aCx, aObj, name);
if (!event) {
if (!v.isObject())
return false;
}
JSObject* obj = &v.toObject();
return IsThisClass(JS_GetClass(obj)) &&
GetJSPrivateSafeish<ErrorEvent>(obj) != nullptr;
}
aVp.set(JS_GetReservedSlot(aObj, slot));
template<SLOT Slot>
static bool
GetPropertyImpl(JSContext* aCx, JS::CallArgs aArgs)
{
aArgs.rval().set(JS_GetReservedSlot(&aArgs.thisv().toObject(), Slot));
return true;
}
// This struct (versus just templating the method directly) is needed only for
// gcc 4.4 (and maybe 4.5 -- 4.6 is okay) being too braindead to allow
// GetProperty<Slot> and friends in the JSPropertySpec[] below.
template<SLOT Slot>
struct Property
{
static bool
Get(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
static_assert(SLOT_FIRST <= Slot && Slot < SLOT_COUNT, "bad slot");
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsErrorEvent, GetPropertyImpl<Slot> >(aCx, args);
}
};
static bool
InitErrorEvent(JSContext* aCx, unsigned aArgc, jsval* aVp)
{
@ -776,13 +810,13 @@ DECL_ERROREVENT_CLASS(ErrorEvent::sMainRuntimeClass, "WorkerErrorEvent")
#undef DECL_ERROREVENT_CLASS
const JSPropertySpec ErrorEvent::sProperties[] = {
{ "message", SLOT_message, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "filename", SLOT_filename, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "lineno", SLOT_lineno, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
JS_PSGS("message", Property<SLOT_message>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("filename", Property<SLOT_filename>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("lineno", Property<SLOT_lineno>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PS_END
};
const JSFunctionSpec ErrorEvent::sFunctions[] = {
@ -895,24 +929,37 @@ private:
}
static bool
GetProperty(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
IsProgressEvent(JS::Handle<JS::Value> v)
{
JS_ASSERT(JSID_IS_INT(aIdval));
int32_t slot = JSID_TO_INT(aIdval);
JS_ASSERT(slot >= SLOT_lengthComputable && slot < SLOT_COUNT);
const char* name = sProperties[slot - SLOT_FIRST].name;
ProgressEvent* event = GetInstancePrivate(aCx, aObj, name);
if (!event) {
if (!v.isObject())
return false;
}
JSObject* obj = &v.toObject();
return JS_GetClass(obj) == &sClass &&
GetJSPrivateSafeish<ProgressEvent>(obj) != nullptr;
}
aVp.set(JS_GetReservedSlot(aObj, slot));
template<SLOT Slot>
static bool
GetPropertyImpl(JSContext* aCx, JS::CallArgs aArgs)
{
aArgs.rval().set(JS_GetReservedSlot(&aArgs.thisv().toObject(), Slot));
return true;
}
// This struct (versus just templating the method directly) is needed only for
// gcc 4.4 (and maybe 4.5 -- 4.6 is okay) being too braindead to allow
// GetProperty<Slot> and friends in the JSPropertySpec[] below.
template<SLOT Slot>
struct Property
{
static bool
Get(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
static_assert(SLOT_FIRST <= Slot && Slot < SLOT_COUNT, "bad slot");
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsProgressEvent, GetPropertyImpl<Slot> >(aCx, args);
}
};
};
JSClass ProgressEvent::sClass = {
@ -923,13 +970,13 @@ JSClass ProgressEvent::sClass = {
};
const JSPropertySpec ProgressEvent::sProperties[] = {
{ "lengthComputable", SLOT_lengthComputable, PROPERTY_FLAGS,
JSOP_WRAPPER(GetProperty), JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "loaded", SLOT_loaded, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "total", SLOT_total, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
JS_PSGS("lengthComputable", Property<SLOT_lengthComputable>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("loaded", Property<SLOT_loaded>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("total", Property<SLOT_total>::Get, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PS_END
};
Event*

View File

@ -20,9 +20,6 @@
#include "WorkerInlines.h"
#include "WorkerPrivate.h"
#define PROPERTY_FLAGS \
(JSPROP_ENUMERATE | JSPROP_SHARED)
USING_WORKERS_NAMESPACE
using mozilla::dom::Throw;
@ -111,32 +108,40 @@ private:
}
static bool
GetSize(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
IsBlob(JS::Handle<JS::Value> v)
{
nsIDOMBlob* blob = GetInstancePrivate(aCx, aObj, "size");
if (!blob) {
return false;
}
return v.isObject() && GetPrivate(&v.toObject()) != nullptr;
}
static bool
GetSizeImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "size");
MOZ_ASSERT(blob);
uint64_t size;
if (NS_FAILED(blob->GetSize(&size))) {
return Throw(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
}
aVp.set(JS_NumberValue(double(size)));
aArgs.rval().setNumber(double(size));
return true;
}
static bool
GetType(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
GetSize(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
nsIDOMBlob* blob = GetInstancePrivate(aCx, aObj, "type");
if (!blob) {
return false;
}
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsBlob, GetSizeImpl>(aCx, args);
}
static bool
GetTypeImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "type");
MOZ_ASSERT(blob);
nsString type;
if (NS_FAILED(blob->GetType(type))) {
@ -148,11 +153,17 @@ private:
return false;
}
aVp.set(STRING_TO_JSVAL(jsType));
aArgs.rval().setString(jsType);
return true;
}
static bool
GetType(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsBlob, GetTypeImpl>(aCx, args);
}
static bool
Slice(JSContext* aCx, unsigned aArgc, jsval* aVp)
{
@ -205,9 +216,9 @@ JSClass Blob::sClass = {
};
const JSPropertySpec Blob::sProperties[] = {
{ "size", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetSize), JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "type", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetType), JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
JS_PSGS("size", GetSize, GetterOnlyJSNative, JSPROP_ENUMERATE),
JS_PSGS("type", GetType, GetterOnlyJSNative, JSPROP_ENUMERATE),
JS_PS_END
};
const JSFunctionSpec Blob::sFunctions[] = {
@ -299,13 +310,17 @@ private:
}
static bool
GetMozFullPath(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
IsFile(JS::Handle<JS::Value> v)
{
nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "mozFullPath");
if (!file) {
return false;
}
return v.isObject() && GetPrivate(&v.toObject()) != nullptr;
}
static bool
GetMozFullPathImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
nsIDOMFile* file = GetInstancePrivate(aCx, obj, "mozFullPath");
MOZ_ASSERT(file);
nsString fullPath;
@ -320,18 +335,23 @@ private:
return false;
}
aVp.set(STRING_TO_JSVAL(jsFullPath));
aArgs.rval().setString(jsFullPath);
return true;
}
static bool
GetName(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
GetMozFullPath(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "name");
if (!file) {
return false;
}
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsFile, GetMozFullPathImpl>(aCx, args);
}
static bool
GetNameImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
nsIDOMFile* file = GetInstancePrivate(aCx, obj, "name");
MOZ_ASSERT(file);
nsString name;
if (NS_FAILED(file->GetName(name))) {
@ -343,18 +363,23 @@ private:
return false;
}
aVp.set(STRING_TO_JSVAL(jsName));
aArgs.rval().setString(jsName);
return true;
}
static bool
GetPath(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
GetName(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "path");
if (!file) {
return false;
}
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsFile, GetNameImpl>(aCx, args);
}
static bool
GetPathImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
nsIDOMFile* file = GetInstancePrivate(aCx, obj, "path");
MOZ_ASSERT(file);
nsString path;
if (NS_FAILED(file->GetPath(path))) {
@ -366,27 +391,39 @@ private:
return false;
}
aVp.set(STRING_TO_JSVAL(jsPath));
aArgs.rval().setString(jsPath);
return true;
}
static bool
GetLastModifiedDate(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
GetPath(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "lastModifiedDate");
if (!file) {
return false;
}
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsFile, GetPathImpl>(aCx, args);
}
static bool
GetLastModifiedDateImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
nsIDOMFile* file = GetInstancePrivate(aCx, obj, "lastModifiedDate");
MOZ_ASSERT(file);
JS::Rooted<JS::Value> value(aCx);
if (NS_FAILED(file->GetLastModifiedDate(aCx, value.address()))) {
return false;
}
aVp.set(value);
aArgs.rval().set(value);
return true;
}
static bool
GetLastModifiedDate(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsFile, GetLastModifiedDateImpl>(aCx, args);
}
};
JSClass File::sClass = {
@ -397,15 +434,12 @@ JSClass File::sClass = {
};
const JSPropertySpec File::sProperties[] = {
{ "name", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetName),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "path", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetPath),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "lastModifiedDate", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetLastModifiedDate),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "mozFullPath", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetMozFullPath),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
JS_PSGS("name", GetName, GetterOnlyJSNative, JSPROP_ENUMERATE),
JS_PSGS("path", GetPath, GetterOnlyJSNative, JSPROP_ENUMERATE),
JS_PSGS("lastModifiedDate", GetLastModifiedDate, GetterOnlyJSNative,
JSPROP_ENUMERATE),
JS_PSGS("mozFullPath", GetMozFullPath, GetterOnlyJSNative, JSPROP_ENUMERATE),
JS_PS_END
};
nsIDOMBlob*

View File

@ -8,15 +8,13 @@
#include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/BindingUtils.h"
#include "jsapi.h"
#include "EventTarget.h"
#include "RuntimeService.h"
#include "WorkerPrivate.h"
#include "WorkerInlines.h"
#define PROPERTY_FLAGS \
(JSPROP_ENUMERATE | JSPROP_SHARED)
#define FUNCTION_FLAGS \
JSPROP_ENUMERATE
@ -34,16 +32,6 @@ class Worker
static const JSPropertySpec sProperties[];
static const JSFunctionSpec sFunctions[];
enum
{
STRING_onerror = 0,
STRING_onmessage,
STRING_COUNT
};
static const char* const sEventStrings[STRING_COUNT];
protected:
enum {
// The constructor function holds a WorkerPrivate* in its first reserved
@ -176,60 +164,110 @@ private:
~Worker();
static bool
GetEventListener(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
IsWorker(JS::Handle<JS::Value> v)
{
JS_ASSERT(JSID_IS_INT(aIdval));
JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
return v.isObject() && ClassIsWorker(JS_GetClass(&v.toObject()));
}
const char* name = sEventStrings[JSID_TO_INT(aIdval)];
WorkerPrivate* worker = GetInstancePrivate(aCx, aObj, name);
if (!worker) {
return !JS_IsExceptionPending(aCx);
}
static bool
GetEventListener(JSContext* aCx, const JS::CallArgs aArgs,
const nsAString &aNameStr)
{
WorkerPrivate* worker =
GetInstancePrivate(aCx, &aArgs.thisv().toObject(),
NS_ConvertUTF16toUTF8(aNameStr).get());
MOZ_ASSERT(worker);
NS_ConvertASCIItoUTF16 nameStr(name + 2);
ErrorResult rv;
JS::Rooted<JSObject*> listener(aCx, worker->GetEventListener(nameStr, rv));
JS::Rooted<JSObject*> listener(aCx, worker->GetEventListener(Substring(aNameStr, 2), rv));
if (rv.Failed()) {
JS_ReportError(aCx, "Failed to get listener!");
return false;
}
aVp.set(listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL);
aArgs.rval().setObjectOrNull(listener);
return true;
}
static bool
SetEventListener(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
bool aStrict, JS::MutableHandle<JS::Value> aVp)
GetOnerrorImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS_ASSERT(JSID_IS_INT(aIdval));
JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
return GetEventListener(aCx, aArgs, NS_LITERAL_STRING("onerror"));
}
const char* name = sEventStrings[JSID_TO_INT(aIdval)];
WorkerPrivate* worker = GetInstancePrivate(aCx, aObj, name);
if (!worker) {
return !JS_IsExceptionPending(aCx);
}
static bool
GetOnerror(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorker, GetOnerrorImpl>(aCx, args);
}
static bool
GetOnmessageImpl(JSContext* aCx, JS::CallArgs aArgs)
{
return GetEventListener(aCx, aArgs, NS_LITERAL_STRING("onmessage"));
}
static bool
GetOnmessage(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorker, GetOnmessageImpl>(aCx, args);
}
static bool
SetEventListener(JSContext* aCx, JS::CallArgs aArgs,
const nsAString& aNameStr)
{
WorkerPrivate* worker =
GetInstancePrivate(aCx, &aArgs.thisv().toObject(),
NS_ConvertUTF16toUTF8(aNameStr).get());
MOZ_ASSERT(worker);
JS::Rooted<JSObject*> listener(aCx);
if (!JS_ValueToObject(aCx, aVp, listener.address())) {
if (!JS_ValueToObject(aCx, aArgs.get(0), listener.address())) {
return false;
}
NS_ConvertASCIItoUTF16 nameStr(name + 2);
ErrorResult rv;
worker->SetEventListener(nameStr, listener, rv);
worker->SetEventListener(Substring(aNameStr, 2), listener, rv);
if (rv.Failed()) {
JS_ReportError(aCx, "Failed to set listener!");
return false;
}
aArgs.rval().setUndefined();
return true;
}
static bool
SetOnerrorImpl(JSContext* aCx, JS::CallArgs aArgs)
{
return SetEventListener(aCx, aArgs, NS_LITERAL_STRING("onerror"));
}
static bool
SetOnerror(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorker, SetOnerrorImpl>(aCx, args);
}
static bool
SetOnmessageImpl(JSContext* aCx, JS::CallArgs aArgs)
{
return SetEventListener(aCx, aArgs, NS_LITERAL_STRING("onmessage"));
}
static bool
SetOnmessage(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorker, SetOnmessageImpl>(aCx, args);
}
static bool
Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
{
@ -355,11 +393,9 @@ DOMIfaceAndProtoJSClass Worker::sProtoClass = {
};
const JSPropertySpec Worker::sProperties[] = {
{ sEventStrings[STRING_onerror], STRING_onerror, PROPERTY_FLAGS,
JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) },
{ sEventStrings[STRING_onmessage], STRING_onmessage, PROPERTY_FLAGS,
JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) },
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
JS_PSGS("onerror", GetOnerror, SetOnerror, JSPROP_ENUMERATE),
JS_PSGS("onmessage", GetOnmessage, SetOnmessage, JSPROP_ENUMERATE),
JS_PS_END
};
const JSFunctionSpec Worker::sFunctions[] = {
@ -368,11 +404,6 @@ const JSFunctionSpec Worker::sFunctions[] = {
JS_FS_END
};
const char* const Worker::sEventStrings[STRING_COUNT] = {
"onerror",
"onmessage"
};
class ChromeWorker : public Worker
{
static DOMJSClass sClass;
@ -522,7 +553,7 @@ Worker::GetInstancePrivate(JSContext* aCx, JSObject* aObj,
const char* aFunctionName)
{
JSClass* classPtr = JS_GetClass(aObj);
if (classPtr == Class() || classPtr == ChromeWorker::Class()) {
if (ClassIsWorker(classPtr)) {
return UnwrapDOMObject<WorkerPrivate>(aObj);
}
@ -580,4 +611,11 @@ ClassIsWorker(JSClass* aClass)
return Worker::Class() == aClass || ChromeWorker::Class() == aClass;
}
bool
GetterOnlyJSNative(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr, JSMSG_GETTER_ONLY);
return false;
}
END_WORKERS_NAMESPACE

View File

@ -48,9 +48,6 @@
#include "WorkerInlines.h"
#define PROPERTY_FLAGS \
(JSPROP_ENUMERATE | JSPROP_SHARED)
#define FUNCTION_FLAGS \
JSPROP_ENUMERATE
@ -155,18 +152,14 @@ protected:
}
private:
static bool
GetEventListener(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
{
JS_ASSERT(JSID_IS_INT(aIdval));
JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
static bool IsWorkerGlobalScope(JS::Handle<JS::Value> v);
const char* name = sEventStrings[JSID_TO_INT(aIdval)];
WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
if (!scope) {
return false;
}
static bool
GetOnCloseImpl(JSContext* aCx, JS::CallArgs aArgs)
{
const char* name = sEventStrings[STRING_onclose];
WorkerGlobalScope* scope = GetInstancePrivate(aCx, &aArgs.thisv().toObject(), name);
MOZ_ASSERT(scope);
ErrorResult rv;
@ -178,30 +171,32 @@ private:
return false;
}
aVp.set(listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL);
aArgs.rval().setObjectOrNull(listener);
return true;
}
static bool
SetEventListener(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
bool aStrict, JS::MutableHandle<JS::Value> aVp)
GetOnClose(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS_ASSERT(JSID_IS_INT(aIdval));
JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorkerGlobalScope, GetOnCloseImpl>(aCx, args);
}
const char* name = sEventStrings[JSID_TO_INT(aIdval)];
WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
if (!scope) {
return false;
}
static bool
SetOnCloseImpl(JSContext* aCx, JS::CallArgs aArgs)
{
const char* name = sEventStrings[STRING_onclose];
WorkerGlobalScope* scope =
GetInstancePrivate(aCx, &aArgs.thisv().toObject(), name);
MOZ_ASSERT(scope);
if (JSVAL_IS_PRIMITIVE(aVp)) {
if (aArgs.length() == 0 || !aArgs[0].isObject()) {
JS_ReportError(aCx, "Not an event listener!");
return false;
}
ErrorResult rv;
JS::Rooted<JSObject*> listenerObj(aCx, JSVAL_TO_OBJECT(aVp));
JS::Rooted<JSObject*> listenerObj(aCx, &aArgs[0].toObject());
scope->SetEventListener(NS_ConvertASCIItoUTF16(name + 2),
listenerObj, rv);
if (rv.Failed()) {
@ -209,9 +204,17 @@ private:
return false;
}
aArgs.rval().setUndefined();
return true;
}
static bool
SetOnClose(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorkerGlobalScope, SetOnCloseImpl>(aCx, args);
}
static WorkerGlobalScope*
GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName);
@ -224,32 +227,32 @@ private:
}
static bool
GetSelf(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
GetSelfImpl(JSContext* aCx, JS::CallArgs aArgs)
{
if (!GetInstancePrivate(aCx, aObj, "self")) {
return false;
}
aVp.set(OBJECT_TO_JSVAL(aObj));
aArgs.rval().setObject(aArgs.thisv().toObject());
return true;
}
static bool
GetLocation(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
GetSelf(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
WorkerGlobalScope* scope =
GetInstancePrivate(aCx, aObj, sProperties[SLOT_location].name);
if (!scope) {
return false;
}
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorkerGlobalScope, GetSelfImpl>(aCx, args);
}
if (JSVAL_IS_VOID(scope->mSlots[SLOT_location])) {
static bool
GetLocationImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
WorkerGlobalScope* scope =
GetInstancePrivate(aCx, obj, sProperties[SLOT_location].name);
MOZ_ASSERT(scope);
if (scope->mSlots[SLOT_location].isUndefined()) {
WorkerPrivate::LocationInfo& info = scope->mWorker->GetLocationInfo();
nsRefPtr<WorkerLocation> location =
WorkerLocation::Create(aCx, aObj, info);
WorkerLocation::Create(aCx, obj, info);
if (!location) {
return false;
}
@ -257,10 +260,17 @@ private:
scope->mSlots[SLOT_location] = OBJECT_TO_JSVAL(location->GetJSObject());
}
aVp.set(scope->mSlots[SLOT_location]);
aArgs.rval().set(scope->mSlots[SLOT_location]);
return true;
}
static bool
GetLocation(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorkerGlobalScope, GetLocationImpl>(aCx, args);
}
static bool
UnwrapErrorEvent(JSContext* aCx, unsigned aArgc, jsval* aVp)
{
@ -301,14 +311,11 @@ private:
}
static bool
GetOnErrorListener(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
GetOnErrorListenerImpl(JSContext* aCx, JS::CallArgs aArgs)
{
const char* name = sEventStrings[STRING_onerror];
WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
if (!scope) {
return false;
}
WorkerGlobalScope* scope = GetInstancePrivate(aCx, &aArgs.thisv().toObject(), name);
MOZ_ASSERT(scope);
ErrorResult rv;
@ -321,28 +328,31 @@ private:
}
if (!adaptor) {
aVp.setNull();
aArgs.rval().setNull();
return true;
}
aVp.set(js::GetFunctionNativeReserved(adaptor, SLOT_wrappedFunction));
JS_ASSERT(!JSVAL_IS_PRIMITIVE(aVp));
aArgs.rval().set(js::GetFunctionNativeReserved(adaptor, SLOT_wrappedFunction));
MOZ_ASSERT(aArgs.rval().isObject());
return true;
}
static bool
SetOnErrorListener(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
bool aStrict, JS::MutableHandle<JS::Value> aVp)
GetOnErrorListener(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
const char* name = sEventStrings[STRING_onerror];
WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
if (!scope) {
return false;
}
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorkerGlobalScope, GetOnErrorListenerImpl>(aCx, args);
}
if (JSVAL_IS_PRIMITIVE(aVp)) {
static bool
SetOnErrorListenerImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
const char* name = sEventStrings[STRING_onerror];
WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, name);
MOZ_ASSERT(scope);
if (aArgs.length() == 0 || !aArgs[0].isObject()) {
JS_ReportError(aCx, "Not an event listener!");
return false;
}
@ -360,8 +370,8 @@ private:
}
js::SetFunctionNativeReserved(listener, SLOT_wrappedScope,
OBJECT_TO_JSVAL(aObj));
js::SetFunctionNativeReserved(listener, SLOT_wrappedFunction, aVp);
JS::ObjectValue(*obj));
js::SetFunctionNativeReserved(listener, SLOT_wrappedFunction, aArgs[0]);
ErrorResult rv;
@ -372,21 +382,27 @@ private:
return false;
}
aArgs.rval().setUndefined();
return true;
}
static bool
GetNavigator(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
SetOnErrorListener(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
WorkerGlobalScope* scope =
GetInstancePrivate(aCx, aObj, sProperties[SLOT_navigator].name);
if (!scope) {
return false;
}
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorkerGlobalScope, SetOnErrorListenerImpl>(aCx, args);
}
if (JSVAL_IS_VOID(scope->mSlots[SLOT_navigator])) {
nsRefPtr<WorkerNavigator> navigator = WorkerNavigator::Create(aCx, aObj);
static bool
GetNavigatorImpl(JSContext* aCx, JS::CallArgs aArgs)
{
JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
WorkerGlobalScope* scope =
GetInstancePrivate(aCx, obj, sProperties[SLOT_navigator].name);
MOZ_ASSERT(scope);
if (scope->mSlots[SLOT_navigator].isUndefined()) {
nsRefPtr<WorkerNavigator> navigator = WorkerNavigator::Create(aCx, obj);
if (!navigator) {
return false;
}
@ -394,10 +410,17 @@ private:
scope->mSlots[SLOT_navigator] = OBJECT_TO_JSVAL(navigator->GetJSObject());
}
aVp.set(scope->mSlots[SLOT_navigator]);
aArgs.rval().set(scope->mSlots[SLOT_navigator]);
return true;
}
static bool
GetNavigator(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorkerGlobalScope, GetNavigatorImpl>(aCx, args);
}
static bool
Close(JSContext* aCx, unsigned aArgc, jsval* aVp)
{
@ -637,16 +660,14 @@ JSClass WorkerGlobalScope::sClass = {
};
const JSPropertySpec WorkerGlobalScope::sProperties[] = {
{ "location", SLOT_location, PROPERTY_FLAGS, JSOP_WRAPPER(GetLocation),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ sEventStrings[STRING_onerror], STRING_onerror, PROPERTY_FLAGS,
JSOP_WRAPPER(GetOnErrorListener), JSOP_WRAPPER(SetOnErrorListener) },
{ sEventStrings[STRING_onclose], STRING_onclose, PROPERTY_FLAGS,
JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) },
{ "navigator", SLOT_navigator, PROPERTY_FLAGS, JSOP_WRAPPER(GetNavigator),
JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ "self", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetSelf), JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
JS_PSGS("location", GetLocation, GetterOnlyJSNative, JSPROP_ENUMERATE),
JS_PSGS(sEventStrings[STRING_onerror], GetOnErrorListener, SetOnErrorListener,
JSPROP_ENUMERATE),
JS_PSGS(sEventStrings[STRING_onclose], GetOnClose, SetOnClose,
JSPROP_ENUMERATE),
JS_PSGS("navigator", GetNavigator, GetterOnlyJSNative, JSPROP_ENUMERATE),
JS_PSGS("self", GetSelf, GetterOnlyJSNative, JSPROP_ENUMERATE),
JS_PS_END
};
const JSFunctionSpec WorkerGlobalScope::sFunctions[] = {
@ -751,17 +772,18 @@ private:
using EventTarget::SetEventListener;
static bool
GetEventListener(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
JS::MutableHandle<JS::Value> aVp)
IsDedicatedWorkerGlobalScope(JS::Handle<JS::Value> v)
{
JS_ASSERT(JSID_IS_INT(aIdval));
JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
return v.isObject() && JS_GetClass(&v.toObject()) == Class();
}
const char* name = sEventStrings[JSID_TO_INT(aIdval)];
DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
if (!scope) {
return false;
}
static bool
GetOnMessageImpl(JSContext* aCx, JS::CallArgs aArgs)
{
const char* name = sEventStrings[STRING_onmessage];
DedicatedWorkerGlobalScope* scope =
GetInstancePrivate(aCx, &aArgs.thisv().toObject(), name);
MOZ_ASSERT(scope);
ErrorResult rv;
@ -773,31 +795,33 @@ private:
return false;
}
aVp.set(listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL);
aArgs.rval().setObjectOrNull(listener);
return true;
}
static bool
SetEventListener(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
bool aStrict, JS::MutableHandle<JS::Value> aVp)
GetOnMessage(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS_ASSERT(JSID_IS_INT(aIdval));
JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsDedicatedWorkerGlobalScope, GetOnMessageImpl>(aCx, args);
}
const char* name = sEventStrings[JSID_TO_INT(aIdval)];
DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
if (!scope) {
return false;
}
static bool
SetOnMessageImpl(JSContext* aCx, JS::CallArgs aArgs)
{
const char* name = sEventStrings[STRING_onmessage];
DedicatedWorkerGlobalScope* scope =
GetInstancePrivate(aCx, &aArgs.thisv().toObject(), name);
MOZ_ASSERT(scope);
if (JSVAL_IS_PRIMITIVE(aVp)) {
if (aArgs.length() == 0 || !aArgs[0].isObject()) {
JS_ReportError(aCx, "Not an event listener!");
return false;
}
ErrorResult rv;
JS::Rooted<JSObject*> listenerObj(aCx, JSVAL_TO_OBJECT(aVp));
JS::Rooted<JSObject*> listenerObj(aCx, &aArgs[0].toObject());
scope->SetEventListener(NS_ConvertASCIItoUTF16(name + 2),
listenerObj, rv);
@ -806,9 +830,17 @@ private:
return false;
}
aArgs.rval().setUndefined();
return true;
}
static bool
SetOnMessage(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsDedicatedWorkerGlobalScope, SetOnMessageImpl>(aCx, args);
}
static DedicatedWorkerGlobalScope*
GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
{
@ -947,9 +979,9 @@ DOMIfaceAndProtoJSClass DedicatedWorkerGlobalScope::sProtoClass = {
};
const JSPropertySpec DedicatedWorkerGlobalScope::sProperties[] = {
{ sEventStrings[STRING_onmessage], STRING_onmessage, PROPERTY_FLAGS,
JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) },
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
JS_PSGS(sEventStrings[STRING_onmessage], GetOnMessage, SetOnMessage,
JSPROP_ENUMERATE),
JS_PS_END
};
const JSFunctionSpec DedicatedWorkerGlobalScope::sFunctions[] = {
@ -980,6 +1012,12 @@ WorkerGlobalScope::GetInstancePrivate(JSContext* aCx, JSObject* aObj,
return NULL;
}
bool
WorkerGlobalScope::IsWorkerGlobalScope(JS::Handle<JS::Value> v)
{
return v.isObject() && JS_GetClass(&v.toObject()) == DedicatedWorkerGlobalScope::Class();
}
} /* anonymous namespace */
BEGIN_WORKERS_NAMESPACE

View File

@ -225,6 +225,14 @@ ThrowDOMExceptionForNSResult(JSContext* aCx, nsresult aNSResult);
} // namespace exceptions
// Throws the JSMSG_GETTER_ONLY exception. This shouldn't be used going
// forward -- getter-only properties should just use JS_PSG for the setter
// (implying no setter at all), which will not throw when set in non-strict
// code but will in strict code. Old code should use this only for temporary
// compatibility reasons.
extern bool
GetterOnlyJSNative(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
END_WORKERS_NAMESPACE
#endif // mozilla_dom_workers_workers_h__