Import Cobalt 2.10363 2016-09-02
diff --git a/src/base/threading/thread.cc b/src/base/threading/thread.cc
index c940775..29b851a 100644
--- a/src/base/threading/thread.cc
+++ b/src/base/threading/thread.cc
@@ -17,21 +17,10 @@
namespace base {
-namespace {
-
-// We use this thread-local variable to record whether or not a thread exited
-// because its Stop method was called. This allows us to catch cases where
-// MessageLoop::Quit() is called directly, which is unexpected when using a
-// Thread to setup and run a MessageLoop.
-base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool =
- LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
// This is used to trigger the message loop to exit.
-void ThreadQuitHelper() {
+void Thread::ThreadQuitHelper() {
MessageLoop::current()->Quit();
- Thread::SetThreadWasQuitProperly(true);
+ SetThreadWasQuitProperly(true);
}
// Used to pass data to ThreadMain. This structure is allocated on the stack
@@ -60,7 +49,12 @@
thread_(0),
message_loop_(NULL),
thread_id_(kInvalidThreadId),
- name_(name) {
+ name_(name)
+#ifndef NDEBUG
+ ,
+ was_quit_properly_(false)
+#endif
+{
}
Thread::~Thread() {
@@ -153,7 +147,8 @@
return;
stopping_ = true;
- message_loop_->PostTask(FROM_HERE, base::Bind(&ThreadQuitHelper));
+ message_loop_->PostTask(
+ FROM_HERE, base::Bind(&Thread::ThreadQuitHelper, base::Unretained(this)));
}
bool Thread::IsRunning() const {
@@ -165,15 +160,17 @@
}
void Thread::SetThreadWasQuitProperly(bool flag) {
- lazy_tls_bool.Pointer()->Set(flag);
+#ifndef NDEBUG
+ was_quit_properly_ = flag;
+#endif
}
bool Thread::GetThreadWasQuitProperly() {
- bool quit_properly = true;
#ifndef NDEBUG
- quit_properly = lazy_tls_bool.Pointer()->Get();
+ return was_quit_properly_;
+#else
+ return true;
#endif
- return quit_properly;
}
void Thread::ThreadMain() {
diff --git a/src/base/threading/thread.h b/src/base/threading/thread.h
index d0f89af..0a99852 100644
--- a/src/base/threading/thread.h
+++ b/src/base/threading/thread.h
@@ -167,8 +167,9 @@
// Called just after the message loop ends
virtual void CleanUp() {}
- static void SetThreadWasQuitProperly(bool flag);
- static bool GetThreadWasQuitProperly();
+ void ThreadQuitHelper();
+ void SetThreadWasQuitProperly(bool flag);
+ bool GetThreadWasQuitProperly();
void set_message_loop(MessageLoop* message_loop) {
message_loop_ = message_loop;
@@ -218,6 +219,14 @@
// The name of the thread. Used for debugging purposes.
std::string name_;
+#ifndef NDEBUG
+ // We use this member variable to record whether or not a thread exited
+ // because its Stop method was called. This allows us to catch cases where
+ // MessageLoop::Quit() is called directly, which is unexpected when using a
+ // Thread to setup and run a MessageLoop.
+ bool was_quit_properly_;
+#endif
+
friend void ThreadQuitHelper();
DISALLOW_COPY_AND_ASSIGN(Thread);
diff --git a/src/cobalt/audio/audio_buffer_source_node.cc b/src/cobalt/audio/audio_buffer_source_node.cc
index 9bcc91e..6f3538f 100644
--- a/src/cobalt/audio/audio_buffer_source_node.cc
+++ b/src/cobalt/audio/audio_buffer_source_node.cc
@@ -55,15 +55,17 @@
}
// TODO: Fully implement start and stop method. The starting time is
-// based on the current time of AudioContext. We only support start at 0
-// currently.
+// based on the current time of AudioContext. We only support start at 0 and
+// stop at 0 currently.
void AudioBufferSourceNode::Start(double when, double offset, double duration,
script::ExceptionState* exception_state) {
AudioLock::AutoLock lock(audio_lock());
- DCHECK_EQ(when, 0);
- DCHECK_EQ(offset, 0);
- DCHECK_EQ(duration, 0);
+ if (when != 0 || offset != 0 || duration != 0) {
+ dom::DOMException::Raise(dom::DOMException::kInvalidStateErr,
+ exception_state);
+ return;
+ }
if (state_ != kNone) {
dom::DOMException::Raise(dom::DOMException::kInvalidStateErr,
@@ -77,7 +79,11 @@
script::ExceptionState* exception_state) {
AudioLock::AutoLock lock(audio_lock());
- DCHECK_EQ(when, 0);
+ if (when != 0) {
+ dom::DOMException::Raise(dom::DOMException::kInvalidStateErr,
+ exception_state);
+ return;
+ }
if (state_ != kStarted) {
dom::DOMException::Raise(dom::DOMException::kInvalidStateErr,
diff --git a/src/cobalt/base/console_commands.cc b/src/cobalt/base/console_commands.cc
index 8780bcf..eecf31a 100644
--- a/src/cobalt/base/console_commands.cc
+++ b/src/cobalt/base/console_commands.cc
@@ -47,7 +47,7 @@
}
void ConsoleCommandManager::HandleCommand(const std::string& channel,
- const std::string& message) {
+ const std::string& message) const {
DCHECK_GT(channel.length(), size_t(0));
base::AutoLock auto_lock(lock_);
CommandHandlerMap::const_iterator iter = command_channel_map_.find(channel);
@@ -60,6 +60,7 @@
std::set<std::string> ConsoleCommandManager::GetRegisteredChannels() const {
std::set<std::string> result;
+ base::AutoLock auto_lock(lock_);
for (CommandHandlerMap::const_iterator iter = command_channel_map_.begin();
iter != command_channel_map_.end(); ++iter) {
result.insert(iter->first);
@@ -69,6 +70,7 @@
std::string ConsoleCommandManager::GetShortHelp(
const std::string& channel) const {
+ base::AutoLock auto_lock(lock_);
CommandHandlerMap::const_iterator iter = command_channel_map_.find(channel);
if (iter != command_channel_map_.end()) {
return iter->second->short_help();
@@ -78,6 +80,7 @@
std::string ConsoleCommandManager::GetLongHelp(
const std::string& channel) const {
+ base::AutoLock auto_lock(lock_);
CommandHandlerMap::const_iterator iter = command_channel_map_.find(channel);
if (iter != command_channel_map_.end()) {
return iter->second->long_help();
@@ -114,7 +117,7 @@
ConsoleCommandManager::CommandHandler::~CommandHandler() {}
void ConsoleCommandManager::HandleCommand(const std::string& channel,
- const std::string& message) {
+ const std::string& message) const {
UNREFERENCED_PARAMETER(channel);
UNREFERENCED_PARAMETER(message);
}
diff --git a/src/cobalt/base/console_commands.h b/src/cobalt/base/console_commands.h
index 6407174..47144d6 100644
--- a/src/cobalt/base/console_commands.h
+++ b/src/cobalt/base/console_commands.h
@@ -72,7 +72,8 @@
// Handles a command by posting the message to the handler registered for
// the specified channel, if any.
- void HandleCommand(const std::string& channel, const std::string& message);
+ void HandleCommand(const std::string& channel,
+ const std::string& message) const;
// Returns a set of all the currently registered channels.
std::set<std::string> GetRegisteredChannels() const;
@@ -96,7 +97,7 @@
void RegisterCommandHandler(const CommandHandler* handler);
void UnregisterCommandHandler(const CommandHandler* handler);
- base::Lock lock_;
+ mutable base::Lock lock_;
// Map of command handlers, one for each channel.
CommandHandlerMap command_channel_map_;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
index 546197c..8e92cae 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
@@ -411,7 +411,10 @@
// static
JSObject* MozjsAnonymousIndexedGetterInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -430,7 +433,10 @@
//static
const JSClass* MozjsAnonymousIndexedGetterInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
index 9cb9a00..5b5af82 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
@@ -383,7 +383,10 @@
// static
JSObject* MozjsAnonymousNamedGetterInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -402,7 +405,10 @@
//static
const JSClass* MozjsAnonymousNamedGetterInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
index 0b1e79d..04c9194 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
@@ -502,7 +502,10 @@
// static
JSObject* MozjsAnonymousNamedIndexedGetterInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -521,7 +524,10 @@
//static
const JSClass* MozjsAnonymousNamedIndexedGetterInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
index 4073689..1bc5cc0 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
@@ -389,7 +389,10 @@
// static
JSObject* MozjsArbitraryInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -408,7 +411,10 @@
//static
const JSClass* MozjsArbitraryInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
index f0e5922..7f786d8 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
@@ -367,7 +367,10 @@
// static
JSObject* MozjsBaseInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -386,7 +389,10 @@
//static
const JSClass* MozjsBaseInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
index 86e82f3..e0895ab 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
@@ -437,7 +437,10 @@
// static
JSObject* MozjsBooleanTypeTestInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -456,7 +459,10 @@
//static
const JSClass* MozjsBooleanTypeTestInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
index 379afa8..90f8065 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
@@ -666,7 +666,10 @@
// static
JSObject* MozjsCallbackFunctionInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -685,7 +688,10 @@
//static
const JSClass* MozjsCallbackFunctionInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
index b387cf6..7f68bd2 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
@@ -435,7 +435,10 @@
// static
JSObject* MozjsCallbackInterfaceInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -454,7 +457,10 @@
//static
const JSClass* MozjsCallbackInterfaceInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
index dcf4ed6..5b3a117 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
@@ -480,7 +480,10 @@
// static
JSObject* MozjsConditionalInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -499,7 +502,10 @@
//static
const JSClass* MozjsConditionalInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
index 467b6de..a874765 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
@@ -345,7 +345,10 @@
// static
JSObject* MozjsConstantsInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -364,7 +367,10 @@
//static
const JSClass* MozjsConstantsInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
index 8367aeb..1ce35d8 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
@@ -304,7 +304,10 @@
// static
JSObject* MozjsConstructorInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -323,7 +326,10 @@
//static
const JSClass* MozjsConstructorInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
index bcf7385..fcb47c4 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
@@ -388,7 +388,10 @@
// static
JSObject* MozjsConstructorWithArgumentsInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -407,7 +410,10 @@
//static
const JSClass* MozjsConstructorWithArgumentsInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
index 18dd40a..9492765 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
@@ -548,7 +548,10 @@
// static
JSObject* MozjsDOMStringTestInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -567,7 +570,10 @@
//static
const JSClass* MozjsDOMStringTestInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
index e84fa83..eda9b8c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
@@ -713,7 +713,10 @@
// static
JSObject* MozjsDerivedGetterSetterInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -732,7 +735,10 @@
//static
const JSClass* MozjsDerivedGetterSetterInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
index 3edab69..51928b3 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
@@ -367,7 +367,10 @@
// static
JSObject* MozjsDerivedInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -386,7 +389,10 @@
//static
const JSClass* MozjsDerivedInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
index 54c8308..0e86696 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
@@ -379,7 +379,10 @@
// static
JSObject* MozjsDisabledInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -398,7 +401,10 @@
//static
const JSClass* MozjsDisabledInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
index 1ec0bac..0e08a3f 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
@@ -363,7 +363,10 @@
// static
JSObject* MozjsEnumerationInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -382,7 +385,10 @@
//static
const JSClass* MozjsEnumerationInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
index 8a5b4b0..4a0476a 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
@@ -271,16 +271,17 @@
DCHECK(!interface_data->interface_object);
DCHECK(JS_IsGlobalObject(global_object));
- JS::RootedObject parent_prototype(
- context, JS_GetObjectPrototype(context, global_object));
+ // Get Error prototype.
+ JS::RootedObject parent_prototype(context);
+ bool success_check = js_GetClassPrototype(
+ context, GetExceptionProtoKey(JSEXN_ERR), &parent_prototype);
+ DCHECK(success_check);
DCHECK(parent_prototype);
- JS::RootedObject prototype(context);
- // Get Error prototype.
- bool success_check = js_GetClassPrototype(
- context, GetExceptionProtoKey(JSEXN_ERR), &prototype);
- DCHECK(success_check);
- interface_data->prototype = prototype;
+ // Create the Prototype object.
+ interface_data->prototype = JS_NewObjectWithGivenProto(
+ context, &interface_data->prototype_class_definition, parent_prototype,
+ NULL);
bool success = JS_DefineProperties(
context, interface_data->prototype, prototype_properties);
DCHECK(success);
@@ -351,7 +352,10 @@
// static
JSObject* MozjsExceptionObjectInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -370,7 +374,10 @@
//static
const JSClass* MozjsExceptionObjectInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
index c58594c..cc462b9 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
@@ -389,7 +389,10 @@
// static
JSObject* MozjsExceptionsInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -408,7 +411,10 @@
//static
const JSClass* MozjsExceptionsInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
index 3753f38..ea9bef6 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
@@ -329,7 +329,10 @@
// static
JSObject* MozjsExtendedIDLAttributesInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -348,7 +351,10 @@
//static
const JSClass* MozjsExtendedIDLAttributesInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
index 1a71dae..1ac39e0 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
@@ -304,7 +304,10 @@
// static
JSObject* MozjsGetOpaqueRootInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -323,7 +326,10 @@
//static
const JSClass* MozjsGetOpaqueRootInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
index e02ee9c..462c526 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
@@ -327,7 +327,10 @@
// static
JSObject* MozjsGlobalInterfaceParent::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -346,7 +349,10 @@
//static
const JSClass* MozjsGlobalInterfaceParent::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
index a392376..b950039 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
@@ -606,7 +606,10 @@
// static
JSObject* MozjsIndexedGetterInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -625,7 +628,10 @@
//static
const JSClass* MozjsIndexedGetterInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
index d629315..3253e9d 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
@@ -320,7 +320,10 @@
// static
JSObject* MozjsInterfaceWithUnsupportedProperties::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -339,7 +342,10 @@
//static
const JSClass* MozjsInterfaceWithUnsupportedProperties::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
index bdb7519..82151fb 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
@@ -304,7 +304,10 @@
// static
JSObject* MozjsNamedConstructorInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -323,7 +326,10 @@
//static
const JSClass* MozjsNamedConstructorInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
index f77d8de..f0e1c02 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
@@ -578,7 +578,10 @@
// static
JSObject* MozjsNamedGetterInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -597,7 +600,10 @@
//static
const JSClass* MozjsNamedGetterInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
index bc60f6a..bca075c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
@@ -839,7 +839,10 @@
// static
JSObject* MozjsNamedIndexedGetterInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -858,7 +861,10 @@
//static
const JSClass* MozjsNamedIndexedGetterInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
index d30656e..07cf2d8 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
@@ -368,7 +368,10 @@
// static
JSObject* MozjsNestedPutForwardsInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -387,7 +390,10 @@
//static
const JSClass* MozjsNestedPutForwardsInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
index 1848abb..5780f10 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
@@ -292,7 +292,10 @@
// static
JSObject* MozjsNoConstructorInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -311,7 +314,10 @@
//static
const JSClass* MozjsNoConstructorInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
index 1ad2cbb..fc4d206 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
@@ -252,7 +252,10 @@
// static
JSObject* MozjsNoInterfaceObjectInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -271,7 +274,10 @@
//static
const JSClass* MozjsNoInterfaceObjectInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
index 04c7ec4..5ac3c47 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
@@ -876,7 +876,10 @@
// static
JSObject* MozjsNullableTypesTestInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -895,7 +898,10 @@
//static
const JSClass* MozjsNullableTypesTestInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
index 546ed1a..4c45a29 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
@@ -1742,7 +1742,10 @@
// static
JSObject* MozjsNumericTypesTestInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -1761,7 +1764,10 @@
//static
const JSClass* MozjsNumericTypesTestInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
index 4dbc0b3..286a091 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
@@ -482,7 +482,10 @@
// static
JSObject* MozjsObjectTypeBindingsInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -501,7 +504,10 @@
//static
const JSClass* MozjsObjectTypeBindingsInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
index 7d9c1b0..20a6a3c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
@@ -1565,7 +1565,10 @@
// static
JSObject* MozjsOperationsTestInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -1584,7 +1587,10 @@
//static
const JSClass* MozjsOperationsTestInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
index c632988..12b04af 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
@@ -409,7 +409,10 @@
// static
JSObject* MozjsPutForwardsInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -428,7 +431,10 @@
//static
const JSClass* MozjsPutForwardsInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc
index f07d2b5..38b509c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc
@@ -50,45 +50,52 @@
JSContext* context,
JS::HandleObject implementing_object)
: context_(context),
- implementing_object_(implementing_object) { }
+ implementing_object_(context, implementing_object) { }
base::optional<int32_t > MozjsSingleOperationInterface::HandleCallback(
const scoped_refptr<script::Wrappable>& callback_this,
const scoped_refptr<ArbitraryInterface>& value,
bool* had_exception) const {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, implementing_object_);
-
bool success = false;
base::optional<int32_t > cobalt_return_value;
- // Get callable object.
- JS::RootedValue callable(context_);
- if (GetCallableForCallbackInterface(context_, implementing_object_,
- "handleCallback", &callable)) {
- // Convert the callback_this to a JSValue.
- JS::RootedValue this_value(context_);
- ToJSValue(context_, callback_this, &this_value);
- // Convert arguments.
- const int kNumArguments = 1;
- JS::Value args[kNumArguments];
- js::SetValueRangeToNull(args, kNumArguments);
- js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
- ToJSValue(context_, value,
- auto_array_rooter.handleAt(0));
+ // This could be set to NULL if it was garbage collected.
+ JS::RootedObject implementing_object(context_, implementing_object_.Get());
+ DLOG_IF(WARNING, !implementing_object) << "Implementing object is NULL.";
+ if (implementing_object) {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, implementing_object);
- // Call the function.
- JS::RootedValue return_value(context_);
- JSFunction* function = JS_ValueToFunction(context_, callable);
- DCHECK(function);
- success = JS::Call(context_, this_value, function, kNumArguments, args,
- return_value.address());
- DLOG_IF(WARNING, !success) << "Exception in callback.";
- if (success) {
- LoggingExceptionState exception_state;
- FromJSValue(context_, return_value, 0, &exception_state,
- &cobalt_return_value);
- success = !exception_state.is_exception_set();
+ // Get callable object.
+ JS::RootedValue callable(context_);
+ if (GetCallableForCallbackInterface(context_, implementing_object,
+ "handleCallback", &callable)) {
+ // Convert the callback_this to a JSValue.
+ JS::RootedValue this_value(context_);
+ ToJSValue(context_, callback_this, &this_value);
+
+ // Convert arguments.
+ const int kNumArguments = 1;
+ JS::Value args[kNumArguments];
+ js::SetValueRangeToNull(args, kNumArguments);
+ js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+ ToJSValue(context_, value,
+ auto_array_rooter.handleAt(0));
+
+ // Call the function.
+ JS::RootedValue return_value(context_);
+ JS::RootedFunction function(
+ context_, JS_ValueToFunction(context_, callable));
+ DCHECK(function);
+ success = JS::Call(context_, this_value, function, kNumArguments, args,
+ return_value.address());
+ DLOG_IF(WARNING, !success) << "Exception in callback.";
+ if (success) {
+ LoggingExceptionState exception_state;
+ FromJSValue(context_, return_value, 0, &exception_state,
+ &cobalt_return_value);
+ success = !exception_state.is_exception_set();
+ }
}
}
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h
index f2bb3be..65400a2 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h
@@ -26,6 +26,7 @@
// Headers for other bindings wrapper classes
#include "cobalt/bindings/testing/single_operation_interface.h"
+#include "cobalt/script/mozjs/weak_heap_object.h"
#include "third_party/mozjs/js/src/jsapi.h"
namespace cobalt {
@@ -42,11 +43,11 @@
const scoped_refptr<script::Wrappable>& callback_this,
const scoped_refptr<ArbitraryInterface>& value,
bool* had_exception) const OVERRIDE;
- JSObject* handle() const { return implementing_object_; }
+ JSObject* handle() const { return implementing_object_.Get(); }
private:
JSContext* context_;
- JS::Heap<JSObject*> implementing_object_;
+ script::mozjs::WeakHeapObject implementing_object_;
};
} // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
index 7cd708f..fe8a2ad 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
@@ -591,7 +591,10 @@
// static
JSObject* MozjsStaticPropertiesInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -610,7 +613,10 @@
//static
const JSClass* MozjsStaticPropertiesInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
index 2471dfc..bf5fab5 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
@@ -331,7 +331,10 @@
// static
JSObject* MozjsStringifierAnonymousOperationInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -350,7 +353,10 @@
//static
const JSClass* MozjsStringifierAnonymousOperationInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
index f97b025..e7ab56b 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
@@ -381,7 +381,10 @@
// static
JSObject* MozjsStringifierAttributeInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -400,7 +403,10 @@
//static
const JSClass* MozjsStringifierAttributeInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
index 3a96a4b..915226a 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
@@ -372,7 +372,10 @@
// static
JSObject* MozjsStringifierOperationInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -391,7 +394,10 @@
//static
const JSClass* MozjsStringifierOperationInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
index 49786d1..3f3110e 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
@@ -362,7 +362,10 @@
// static
JSObject* MozjsTargetInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -381,7 +384,10 @@
//static
const JSClass* MozjsTargetInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
index bc19f25..df03fdc 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
@@ -500,7 +500,10 @@
// static
JSObject* MozjsUnionTypesInterface::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -519,7 +522,10 @@
//static
const JSClass* MozjsUnionTypesInterface::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
index f52bcf2..a2f79de 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
@@ -643,9 +643,6 @@
JSAutoCompartment auto_compartment(context, global_object);
bool success = JS_InitStandardClasses(context, global_object);
- JS::RootedObject parent_prototype(
- context, JS_GetObjectPrototype(context, global_object));
-
JS::RootedObject prototype(
context, MozjsWindow::GetPrototype(context, global_object));
DCHECK(prototype);
@@ -671,7 +668,10 @@
//static
const JSClass* MozjsWindow::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template b/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template
index 421cddb..3a668f8 100644
--- a/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template
+++ b/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template
@@ -42,7 +42,7 @@
JSContext* context,
JS::HandleObject implementing_object)
: context_(context),
- implementing_object_(implementing_object) { }
+ implementing_object_(context, implementing_object) { }
{% for operation in operations %}
{% for overload in operation.overloads %}
@@ -52,46 +52,53 @@
{{arg.arg_type}} {{arg.name}},
{% endfor %}
bool* had_exception) const {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, implementing_object_);
-
bool success = false;
{% if overload.type != 'void' %}
{{overload.type}} cobalt_return_value;
{% endif %}
- // Get callable object.
- JS::RootedValue callable(context_);
- if (GetCallableForCallbackInterface(context_, implementing_object_,
- "{{overload.idl_name}}", &callable)) {
- // Convert the callback_this to a JSValue.
- JS::RootedValue this_value(context_);
- ToJSValue(context_, callback_this, &this_value);
- // Convert arguments.
- const int kNumArguments = {{overload.arguments|length}};
- JS::Value args[kNumArguments];
- js::SetValueRangeToNull(args, kNumArguments);
- js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
- {% for arg in overload.arguments %}
- ToJSValue(context_, {{arg.name}},
- auto_array_rooter.handleAt({{loop.index0}}));
- {% endfor %}
+ // This could be set to NULL if it was garbage collected.
+ JS::RootedObject implementing_object(context_, implementing_object_.Get());
+ DLOG_IF(WARNING, !implementing_object) << "Implementing object is NULL.";
+ if (implementing_object) {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, implementing_object);
- // Call the function.
- JS::RootedValue return_value(context_);
- JSFunction* function = JS_ValueToFunction(context_, callable);
- DCHECK(function);
- success = JS::Call(context_, this_value, function, kNumArguments, args,
- return_value.address());
- DLOG_IF(WARNING, !success) << "Exception in callback.";
+ // Get callable object.
+ JS::RootedValue callable(context_);
+ if (GetCallableForCallbackInterface(context_, implementing_object,
+ "{{overload.idl_name}}", &callable)) {
+ // Convert the callback_this to a JSValue.
+ JS::RootedValue this_value(context_);
+ ToJSValue(context_, callback_this, &this_value);
+
+ // Convert arguments.
+ const int kNumArguments = {{overload.arguments|length}};
+ JS::Value args[kNumArguments];
+ js::SetValueRangeToNull(args, kNumArguments);
+ js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+{% for arg in overload.arguments %}
+ ToJSValue(context_, {{arg.name}},
+ auto_array_rooter.handleAt({{loop.index0}}));
+{% endfor %}
+
+ // Call the function.
+ JS::RootedValue return_value(context_);
+ JS::RootedFunction function(
+ context_, JS_ValueToFunction(context_, callable));
+ DCHECK(function);
+ success = JS::Call(context_, this_value, function, kNumArguments, args,
+ return_value.address());
+ DLOG_IF(WARNING, !success) << "Exception in callback.";
{% if overload.type != 'void' %}
- if (success) {
- LoggingExceptionState exception_state;
- FromJSValue(context_, return_value, 0, &exception_state,
- &cobalt_return_value);
- success = !exception_state.is_exception_set();
- }
+ if (success) {
+ LoggingExceptionState exception_state;
+ FromJSValue(context_, return_value, 0, &exception_state,
+ &cobalt_return_value);
+ success = !exception_state.is_exception_set();
+ }
{% endif %}
+ }
}
*had_exception = !success;
diff --git a/src/cobalt/bindings/mozjs/templates/callback-interface.h.template b/src/cobalt/bindings/mozjs/templates/callback-interface.h.template
index 1cfeb00..0364b98 100644
--- a/src/cobalt/bindings/mozjs/templates/callback-interface.h.template
+++ b/src/cobalt/bindings/mozjs/templates/callback-interface.h.template
@@ -17,6 +17,7 @@
{% block includes %}
{{ super() }}
+#include "cobalt/script/mozjs/weak_heap_object.h"
#include "third_party/mozjs/js/src/jsapi.h"
{% endblock includes %}
@@ -42,11 +43,11 @@
bool* had_exception) const OVERRIDE;
{% endfor %}
{% endfor %}
- JSObject* handle() const { return implementing_object_; }
+ JSObject* handle() const { return implementing_object_.Get(); }
private:
JSContext* context_;
- JS::Heap<JSObject*> implementing_object_;
+ script::mozjs::WeakHeapObject implementing_object_;
};
{% for component in components %}
diff --git a/src/cobalt/bindings/mozjs/templates/interface.cc.template b/src/cobalt/bindings/mozjs/templates/interface.cc.template
index 16134d5..4d4c20e 100644
--- a/src/cobalt/bindings/mozjs/templates/interface.cc.template
+++ b/src/cobalt/bindings/mozjs/templates/interface.cc.template
@@ -664,25 +664,22 @@
{% if parent_interface %}
JS::RootedObject parent_prototype(
context, {{parent_interface}}::GetPrototype(context, global_object));
+ {% elif is_exception_interface %}
+ // Get Error prototype.
+ JS::RootedObject parent_prototype(context);
+ bool success_check = js_GetClassPrototype(
+ context, GetExceptionProtoKey(JSEXN_ERR), &parent_prototype);
+ DCHECK(success_check);
{% else %}
JS::RootedObject parent_prototype(
context, JS_GetObjectPrototype(context, global_object));
{% endif %}
DCHECK(parent_prototype);
-{% if is_exception_interface %}
- JS::RootedObject prototype(context);
- // Get Error prototype.
- bool success_check = js_GetClassPrototype(
- context, GetExceptionProtoKey(JSEXN_ERR), &prototype);
- DCHECK(success_check);
- interface_data->prototype = prototype;
-{% else %}
// Create the Prototype object.
interface_data->prototype = JS_NewObjectWithGivenProto(
context, &interface_data->prototype_class_definition, parent_prototype,
NULL);
-{% endif %}
bool success = JS_DefineProperties(
context, interface_data->prototype, prototype_properties);
DCHECK(success);
@@ -779,9 +776,6 @@
JSAutoCompartment auto_compartment(context, global_object);
bool success = JS_InitStandardClasses(context, global_object);
- JS::RootedObject parent_prototype(
- context, JS_GetObjectPrototype(context, global_object));
-
JS::RootedObject prototype(
context, {{binding_class}}::GetPrototype(context, global_object));
DCHECK(prototype);
@@ -808,7 +802,10 @@
// static
JSObject* {{binding_class}}::CreateProxy(
JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
InterfaceData* interface_data = GetInterfaceData(context);
@@ -828,7 +825,10 @@
//static
const JSClass* {{binding_class}}::PrototypeClass(
JSContext* context) {
- JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+ DCHECK(MozjsGlobalObjectProxy::GetFromContext(context));
+ JS::RootedObject global_object(
+ context,
+ MozjsGlobalObjectProxy::GetFromContext(context)->global_object());
DCHECK(global_object);
JS::RootedObject prototype(context, GetPrototype(context, global_object));
diff --git a/src/cobalt/bindings/testing/numeric_type_bindings_test.cc b/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
index 88e92d0..ab0546a 100644
--- a/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
+++ b/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
@@ -308,7 +308,7 @@
if (TypeParam::min_value() >= 0) {
expected_result = "18446744073709550000";
EXPECT_CALL(this->test_mock(), MockReturnValueOperation())
- .WillOnce(Return(18446744073709550000l));
+ .WillOnce(Return(18446744073709550000ull));
EXPECT_TRUE(this->EvaluateScript(script, &result));
EXPECT_STREQ(expected_result.c_str(), result.c_str());
}
@@ -363,7 +363,7 @@
// Unsigned : send 18446744073709550000 (between 2^53
// and uint64_t max) to 18446744073709549568.
if (TypeParam::min_value() >= 0) {
- EXPECT_CALL(this->test_mock(), mock_set_property(18446744073709549568));
+ EXPECT_CALL(this->test_mock(), mock_set_property(18446744073709549568ull));
EXPECT_TRUE(this->EvaluateScript(
StringPrintf("test.%sProperty = 18446744073709550000;",
TypeParam::type_string()),
@@ -408,7 +408,8 @@
// Unsigned : send 18446744073709550000 (between 2^53
// and uint64_t max) to 18446744073709549568.
if (TypeParam::min_value() >= 0) {
- EXPECT_CALL(this->test_mock(), MockArgumentOperation(18446744073709549568));
+ EXPECT_CALL(this->test_mock(),
+ MockArgumentOperation(18446744073709549568ull));
EXPECT_TRUE(this->EvaluateScript(
StringPrintf("test.%sArgumentOperation(18446744073709550000);",
TypeParam::type_string()),
diff --git a/src/cobalt/bindings/testing/numeric_types_test_interface.h b/src/cobalt/bindings/testing/numeric_types_test_interface.h
index 713dea5..5730662 100644
--- a/src/cobalt/bindings/testing/numeric_types_test_interface.h
+++ b/src/cobalt/bindings/testing/numeric_types_test_interface.h
@@ -246,7 +246,7 @@
static const char* type_string() { return "unsignedLongLong"; }
- static uint64_t max_value() { return 18446744073709551615; }
+ static uint64_t max_value() { return 18446744073709551615ull; }
static uint64_t min_value() { return 0; }
// This is what the value 18446744073709551615 maps to in javascript.
static const char* max_value_string() { return "18446744073709552000"; }
diff --git a/src/cobalt/bindings/testing/stack_trace_test.cc b/src/cobalt/bindings/testing/stack_trace_test.cc
index c9e39a8..34c4629 100644
--- a/src/cobalt/bindings/testing/stack_trace_test.cc
+++ b/src/cobalt/bindings/testing/stack_trace_test.cc
@@ -16,6 +16,8 @@
#include "cobalt/bindings/testing/bindings_test_base.h"
+using ::testing::MatchesRegex;
+
namespace cobalt {
namespace bindings {
namespace testing {
@@ -45,15 +47,15 @@
EXPECT_TRUE(EvaluateScript(script, &result));
// Expect that bar is on top.
- std::string match_line = "bar @ [object BindingsTestBase]:2\n";
+ std::string match_line = "bar @ [object BindingsTestBase]:2";
size_t position = result.find(match_line);
EXPECT_TRUE(position != std::string::npos);
// Expect a foo at line 6.
- match_line = "foo @ [object BindingsTestBase]:6\n";
+ match_line = "foo @ [object BindingsTestBase]:6";
position = result.find(match_line, ++position);
EXPECT_TRUE(position != std::string::npos);
// Expect 4 subsequent foos at line 8.
- match_line = "foo @ [object BindingsTestBase]:8\n";
+ match_line = "foo @ [object BindingsTestBase]:8";
for (int i = 0; i < 4; ++i) {
position = result.find(match_line, ++position);
EXPECT_TRUE(position != std::string::npos);
@@ -64,6 +66,30 @@
EXPECT_TRUE(position != std::string::npos);
}
+#if defined(ENGINE_SUPPORTS_STACK_TRACE_COLUMNS)
+// Test for column numbers in stack trace. Behavior varies somewhat
+// across engines & versions so, don't check actual column values.
+TEST_F(StackTraceTest, GetStackTraceColumns) {
+ std::string result;
+
+ const std::string script =
+ "function bar() {\n"
+ "// Add extra statements to shift the error right.\n"
+ " var x; var y; return getStackTrace(); var z;\n"
+ "}\n"
+ "function multiArg(in1, in2) {\n"
+ " return in2;\n"
+ "}\n"
+ "multiArg(0, bar());";
+
+ EXPECT_TRUE(EvaluateScript(script, &result));
+ const std::string expected =
+ "bar @ \\[object BindingsTestBase\\]:3:\\d+\n"
+ "global code @ \\[object BindingsTestBase\\]:8:\\d+";
+ EXPECT_THAT(result, MatchesRegex(expected));
+}
+#endif // ENGINE_SUPPORTS_STACK_TRACE_COLUMNS
+
} // namespace testing
} // namespace bindings
} // namespace cobalt
diff --git a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp b/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
index b9f074d..f212dcf 100644
--- a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
+++ b/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
@@ -105,6 +105,7 @@
../dom/Uint32Array.idl
../dom/Uint8Array.idl
../dom/URL.idl
+../dom/VideoPlaybackQuality.idl
../dom/Window.idl
../dom/XMLDocument.idl
../dom/XMLSerializer.idl
diff --git a/src/cobalt/browser/global_objects_idl_files_list.tmp b/src/cobalt/browser/global_objects_idl_files_list.tmp
index b9f074d..f212dcf 100644
--- a/src/cobalt/browser/global_objects_idl_files_list.tmp
+++ b/src/cobalt/browser/global_objects_idl_files_list.tmp
@@ -105,6 +105,7 @@
../dom/Uint32Array.idl
../dom/Uint8Array.idl
../dom/URL.idl
+../dom/VideoPlaybackQuality.idl
../dom/Window.idl
../dom/XMLDocument.idl
../dom/XMLSerializer.idl
diff --git a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp b/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
index 86c81b6..e4de45c 100644
--- a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
+++ b/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
@@ -105,6 +105,7 @@
../dom/Uint32Array.idl
../dom/Uint8Array.idl
../dom/URL.idl
+../dom/VideoPlaybackQuality.idl
../dom/Window.idl
../dom/XMLDocument.idl
../dom/XMLSerializer.idl
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index 828380d..307b437 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -542,6 +542,9 @@
#if defined(ADDRESS_SANITIZER)
// ASAN requires a much bigger stack size here.
const int kStackSize = 4096 * 1024;
+#elif defined(COBALT_BUILD_TYPE_DEBUG)
+ // Non-optimized builds require a bigger stack size.
+ const int kStackSize = 2 * 1024 * 1024;
#else
const int kStackSize = 256 * 1024;
#endif
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 29fb020..f8231a2 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-10060
\ No newline at end of file
+10363
\ No newline at end of file
diff --git a/src/cobalt/css_parser/grammar.y b/src/cobalt/css_parser/grammar.y
index be1ffdd..09e7f2d 100644
--- a/src/cobalt/css_parser/grammar.y
+++ b/src/cobalt/css_parser/grammar.y
@@ -2381,8 +2381,7 @@
break;
}
default:
- parser_impl->LogWarning(@1, "invalid color value");
- $$ = NULL;
+ YYERROR;
break;
}
}
diff --git a/src/cobalt/css_parser/parser_test.cc b/src/cobalt/css_parser/parser_test.cc
index a64f963..77b4874 100644
--- a/src/cobalt/css_parser/parser_test.cc
+++ b/src/cobalt/css_parser/parser_test.cc
@@ -1366,6 +1366,20 @@
style->GetPropertyValue(cssom::kBackgroundImageProperty));
}
+TEST_F(ParserTest, LinearGradientWithInvalidColorStopIsError) {
+ EXPECT_CALL(
+ parser_observer_,
+ OnWarning("[object ParserTest]:1:11: warning: unsupported value"));
+
+ scoped_refptr<cssom::CSSDeclaredStyleData> style =
+ parser_.ParseStyleDeclarationList(
+ "background: linear-gradient(#0123456789abcde 0%));",
+ source_location_);
+
+ EXPECT_EQ(GetPropertyInitialValue(cssom::kBackgroundImageProperty),
+ style->GetPropertyValue(cssom::kBackgroundImageProperty));
+}
+
TEST_F(ParserTest, RadialGradientWithOneColorStopIsError) {
EXPECT_CALL(
parser_observer_,
diff --git a/src/cobalt/cssom/computed_style.cc b/src/cobalt/cssom/computed_style.cc
index 48d8223..ea15228 100644
--- a/src/cobalt/cssom/computed_style.cc
+++ b/src/cobalt/cssom/computed_style.cc
@@ -1631,7 +1631,7 @@
size_t size = specified_position->value().size();
DCHECK_GE(size, 1u);
- DCHECK_LE(size, 2u);
+ DCHECK_LE(size, 4u);
ComputedPositionHelper position_helper(
computed_font_size, root_computed_font_size, viewport_size);
diff --git a/src/cobalt/cssom/computed_style_test.cc b/src/cobalt/cssom/computed_style_test.cc
index d499787..2637dfa 100644
--- a/src/cobalt/cssom/computed_style_test.cc
+++ b/src/cobalt/cssom/computed_style_test.cc
@@ -48,6 +48,24 @@
return computed_style_declaration;
}
+TEST(PromoteToComputedStyle, UnknownPropertyValueShouldBeEmpty) {
+ scoped_refptr<CSSComputedStyleData> computed_style(
+ new CSSComputedStyleData());
+ scoped_refptr<CSSComputedStyleDeclaration> computed_style_declaration(
+ CreateComputedStyleDeclaration(computed_style));
+
+ scoped_refptr<CSSComputedStyleData> parent_computed_style(
+ new CSSComputedStyleData());
+ scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+ CreateComputedStyleDeclaration(parent_computed_style));
+
+ PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
+ parent_computed_style, math::Size(), NULL);
+
+ EXPECT_EQ(
+ computed_style_declaration->GetPropertyValue("cobalt_cobalt_cobalt"), "");
+}
+
TEST(PromoteToComputedStyle, FontWeightShouldBeBoldAsSpecified) {
scoped_refptr<CSSComputedStyleData> computed_style(
new CSSComputedStyleData());
diff --git a/src/cobalt/cssom/css_computed_style_data.cc b/src/cobalt/cssom/css_computed_style_data.cc
index 590ea05..a5e2fcd 100644
--- a/src/cobalt/cssom/css_computed_style_data.cc
+++ b/src/cobalt/cssom/css_computed_style_data.cc
@@ -104,6 +104,8 @@
scoped_refptr<PropertyValue>&
CSSComputedStyleData::GetDeclaredPropertyValueReference(PropertyKey key) {
+ DCHECK_GT(key, kNoneProperty);
+ DCHECK_LE(key, kMaxLonghandPropertyKey);
DCHECK(declared_properties_[key]);
return declared_property_values_.find(key)->second;
}
@@ -329,6 +331,8 @@
void CSSComputedStyleData::AddDeclaredPropertyInheritedFromParent(
PropertyKey key) {
+ DCHECK_GT(key, kNoneProperty);
+ DCHECK_LE(key, kMaxLonghandPropertyKey);
declared_properties_inherited_from_parent_.push_back(key);
}
diff --git a/src/cobalt/cssom/css_computed_style_declaration.cc b/src/cobalt/cssom/css_computed_style_declaration.cc
index 11c7dbb..ed4b4c8 100644
--- a/src/cobalt/cssom/css_computed_style_declaration.cc
+++ b/src/cobalt/cssom/css_computed_style_declaration.cc
@@ -56,7 +56,7 @@
std::string CSSComputedStyleDeclaration::GetDeclaredPropertyValueStringByKey(
const PropertyKey key) const {
- if (!data_) {
+ if (!data_ || key == kNoneProperty) {
return std::string();
}
const scoped_refptr<PropertyValue>& property_value =
diff --git a/src/cobalt/cssom/css_declared_style_data.cc b/src/cobalt/cssom/css_declared_style_data.cc
index 6b96bd3..6768e50 100644
--- a/src/cobalt/cssom/css_declared_style_data.cc
+++ b/src/cobalt/cssom/css_declared_style_data.cc
@@ -45,7 +45,7 @@
}
bool CSSDeclaredStyleData::IsSupportedPropertyKey(PropertyKey key) const {
- return key >= kNoneProperty && key <= kMaxLonghandPropertyKey;
+ return key > kNoneProperty && key <= kMaxLonghandPropertyKey;
}
scoped_refptr<PropertyValue> CSSDeclaredStyleData::GetPropertyValue(
diff --git a/src/cobalt/cssom/css_declared_style_declaration.cc b/src/cobalt/cssom/css_declared_style_declaration.cc
index 9774686..c1d455c 100644
--- a/src/cobalt/cssom/css_declared_style_declaration.cc
+++ b/src/cobalt/cssom/css_declared_style_declaration.cc
@@ -105,7 +105,8 @@
std::string CSSDeclaredStyleDeclaration::GetDeclaredPropertyValueStringByKey(
const PropertyKey key) const {
- return data_ ? data_->GetPropertyValueString(key) : std::string();
+ return (data_ && key != kNoneProperty) ? data_->GetPropertyValueString(key)
+ : std::string();
}
void CSSDeclaredStyleDeclaration::SetPropertyValue(
diff --git a/src/cobalt/cssom/css_style_declaration_test.cc b/src/cobalt/cssom/css_style_declaration_test.cc
index fe62b27..0e71d24 100644
--- a/src/cobalt/cssom/css_style_declaration_test.cc
+++ b/src/cobalt/cssom/css_style_declaration_test.cc
@@ -1387,6 +1387,16 @@
"center");
}
+TEST(CSSStyleDeclarationTest, UnknownDeclaredStylePropertyValueShouldBeEmpty) {
+ testing::MockCSSParser css_parser;
+ scoped_refptr<CSSDeclaredStyleData> initial_style =
+ new CSSDeclaredStyleData();
+ scoped_refptr<CSSDeclaredStyleDeclaration> style =
+ new CSSDeclaredStyleDeclaration(initial_style, &css_parser);
+
+ EXPECT_EQ(style->GetPropertyValue("cobalt_cobalt_cobalt"), "");
+}
+
TEST(CSSStyleDeclarationTest, LengthAttributeGetterEmpty) {
testing::MockCSSParser css_parser;
scoped_refptr<CSSDeclaredStyleDeclaration> style =
diff --git a/src/cobalt/dom/document.cc b/src/cobalt/dom/document.cc
index 0d2b543..0a294ac 100644
--- a/src/cobalt/dom/document.cc
+++ b/src/cobalt/dom/document.cc
@@ -444,6 +444,11 @@
are_font_faces_dirty_ = true;
are_keyframes_dirty_ = true;
+ scoped_refptr<HTMLHtmlElement> current_html = html();
+ if (current_html) {
+ current_html->InvalidateComputedStylesRecursively();
+ }
+
RecordMutation();
}
diff --git a/src/cobalt/dom/dom_parser.cc b/src/cobalt/dom/dom_parser.cc
index feebac7..c70d4e2 100644
--- a/src/cobalt/dom/dom_parser.cc
+++ b/src/cobalt/dom/dom_parser.cc
@@ -47,8 +47,9 @@
case kImageSvgXml:
return html_element_context_->dom_parser()->ParseXMLDocument(
str, GetInlineSourceLocation());
+ case kMaxSupportedType:
default:
- NOTREACHED();
+ LOG(WARNING) << "DOMParse.ParseFromString received invalid type value.";
return NULL;
}
}
diff --git a/src/cobalt/dom/dom_parser.h b/src/cobalt/dom/dom_parser.h
index 946121a..975097a 100644
--- a/src/cobalt/dom/dom_parser.h
+++ b/src/cobalt/dom/dom_parser.h
@@ -41,6 +41,7 @@
kApplicationXml,
kApplicationXhtmlXml,
kImageSvgXml,
+ kMaxSupportedType,
};
explicit DOMParser(script::EnvironmentSettings* environment_settings);
diff --git a/src/cobalt/dom/dom_parser_test.cc b/src/cobalt/dom/dom_parser_test.cc
index 3f1705c..5d392e1 100644
--- a/src/cobalt/dom/dom_parser_test.cc
+++ b/src/cobalt/dom/dom_parser_test.cc
@@ -73,5 +73,11 @@
EXPECT_TRUE(document->IsXMLDocument());
}
+TEST_F(DOMParserTest, InvalidType) {
+ scoped_refptr<Document> document =
+ dom_parser_->ParseFromString("", DOMParser::kMaxSupportedType);
+ EXPECT_FALSE(document);
+}
+
} // namespace dom
} // namespace cobalt
diff --git a/src/cobalt/dom/html_element.cc b/src/cobalt/dom/html_element.cc
index f63dbbf..0d57ebd 100644
--- a/src/cobalt/dom/html_element.cc
+++ b/src/cobalt/dom/html_element.cc
@@ -618,13 +618,7 @@
void HTMLElement::InvalidateComputedStylesRecursively() {
computed_style_valid_ = false;
-
- for (Element* element = first_element_child(); element;
- element = element->next_element_sibling()) {
- HTMLElement* html_element = element->AsHTMLElement();
- DCHECK(html_element);
- html_element->InvalidateComputedStylesRecursively();
- }
+ Node::InvalidateComputedStylesRecursively();
}
void HTMLElement::UpdateComputedStyleRecursively(
@@ -713,6 +707,7 @@
HTMLElement::~HTMLElement() {
--(non_trivial_static_fields.Get().html_element_count_log.count);
dom_stat_tracker_->OnHtmlElementDestroyed();
+ style_->set_mutation_observer(NULL);
}
void HTMLElement::CopyDirectionality(const HTMLElement& other) {
@@ -1068,6 +1063,7 @@
void HTMLElement::OnBackgroundImageLoaded() {
node_document()->RecordMutation();
+ InvalidateRenderTreeNodesFromNode();
}
bool HTMLElement::IsRootElement() {
diff --git a/src/cobalt/dom/html_element.h b/src/cobalt/dom/html_element.h
index 11837a8..5e7fcae 100644
--- a/src/cobalt/dom/html_element.h
+++ b/src/cobalt/dom/html_element.h
@@ -201,7 +201,7 @@
}
// Invalidates the cached computed style of this element and its descendants.
- void InvalidateComputedStylesRecursively();
+ void InvalidateComputedStylesRecursively() OVERRIDE;
// Updates the cached computed style of this element and its descendants.
void UpdateComputedStyleRecursively(
const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
diff --git a/src/cobalt/dom/html_link_element.cc b/src/cobalt/dom/html_link_element.cc
index e101525..fd85733 100644
--- a/src/cobalt/dom/html_link_element.cc
+++ b/src/cobalt/dom/html_link_element.cc
@@ -57,6 +57,15 @@
TRACE_EVENT0("cobalt::dom", "HTMLLinkElement::Obtain()");
// Custom, not in any spec.
DCHECK(thread_checker_.CalledOnValidThread());
+
+ Document* document = node_document();
+
+ // If the document has no browsing context, do not obtain, parse or apply the
+ // style sheet.
+ if (!document->html_element_context()) {
+ return;
+ }
+
DCHECK(MessageLoop::current());
DCHECK(!loader_);
@@ -78,7 +87,6 @@
// the mode being the current state of the element's crossorigin content
// attribute, the origin being the origin of the link element's Document, and
// the default origin behaviour set to taint.
- Document* document = node_document();
csp::SecurityCallback csp_callback = base::Bind(
&CspDelegate::CanLoad, base::Unretained(document->csp_delegate()),
CspDelegate::kStyle);
@@ -100,7 +108,6 @@
void HTMLLinkElement::OnLoadingDone(const std::string& content) {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK_EQ(rel(), "stylesheet");
TRACE_EVENT0("cobalt::dom", "HTMLLinkElement::OnLoadingDone()");
Document* document = node_document();
diff --git a/src/cobalt/dom/html_media_element.cc b/src/cobalt/dom/html_media_element.cc
index f4f04bb..12a4e8e 100644
--- a/src/cobalt/dom/html_media_element.cc
+++ b/src/cobalt/dom/html_media_element.cc
@@ -638,6 +638,13 @@
GURL url = initial_url;
+ if (!url.is_valid()) {
+ // Try to filter out invalid urls as GURL::spec() DCHECKs if the url is
+ // valid.
+ NoneSupported();
+ return;
+ }
+
DCHECK(!media_source_);
if (url.SchemeIs(kMediaSourceUrlProtocol)) {
// Check whether url is allowed by security policy.
@@ -1186,7 +1193,7 @@
}
void HTMLMediaElement::ConfigureMediaControls() {
- DCHECK(!controls_) << "media control is not supported";
+ DLOG_IF(WARNING, controls_) << "media control is not supported";
}
void HTMLMediaElement::MediaEngineError(scoped_refptr<MediaError> error) {
diff --git a/src/cobalt/dom/html_script_element.cc b/src/cobalt/dom/html_script_element.cc
index 09004f7..16acbde 100644
--- a/src/cobalt/dom/html_script_element.cc
+++ b/src/cobalt/dom/html_script_element.cc
@@ -76,6 +76,18 @@
return this;
}
+scoped_refptr<Node> HTMLScriptElement::Duplicate() const {
+ // The cloning steps for script elements must set the "already started" flag
+ // on the copy if it is set on the element being cloned.
+ // https://www.w3.org/TR/html5/scripting-1.html#already-started
+ scoped_refptr<HTMLScriptElement> new_script = HTMLElement::Duplicate()
+ ->AsElement()
+ ->AsHTMLElement()
+ ->AsHTMLScriptElement();
+ new_script->is_already_started_ = is_already_started_;
+ return new_script;
+}
+
HTMLScriptElement::~HTMLScriptElement() {
// Remove the script from the list of scripts that will execute in order as
// soon as possible associated with the Document, only if the document still
diff --git a/src/cobalt/dom/html_script_element.h b/src/cobalt/dom/html_script_element.h
index 91fe882..9335314 100644
--- a/src/cobalt/dom/html_script_element.h
+++ b/src/cobalt/dom/html_script_element.h
@@ -77,6 +77,9 @@
DEFINE_WRAPPABLE_TYPE(HTMLScriptElement);
+ protected:
+ scoped_refptr<Node> Duplicate() const OVERRIDE;
+
private:
~HTMLScriptElement() OVERRIDE;
diff --git a/src/cobalt/dom/html_style_element.cc b/src/cobalt/dom/html_style_element.cc
index a529cc9..88a5626 100644
--- a/src/cobalt/dom/html_style_element.cc
+++ b/src/cobalt/dom/html_style_element.cc
@@ -56,6 +56,13 @@
void HTMLStyleElement::Process() {
Document* document = node_document();
+
+ // If the document has no browsing context, do not parse or apply the style
+ // sheet.
+ if (!document->html_element_context()) {
+ return;
+ }
+
CspDelegate* csp_delegate = document->csp_delegate();
// If the style element has a valid nonce, we always permit it.
const bool bypass_csp = csp_delegate->IsValidNonce(
diff --git a/src/cobalt/dom/node.cc b/src/cobalt/dom/node.cc
index cf81ef0..041836c 100644
--- a/src/cobalt/dom/node.cc
+++ b/src/cobalt/dom/node.cc
@@ -402,6 +402,7 @@
Node::~Node() {
Node* node = last_child_;
while (node) {
+ node->parent_ = NULL;
node->next_sibling_ = NULL;
node = node->previous_sibling_;
}
@@ -432,6 +433,14 @@
}
}
+void Node::InvalidateComputedStylesRecursively() {
+ Node* child = first_child_;
+ while (child) {
+ child->InvalidateComputedStylesRecursively();
+ child = child->next_sibling_;
+ }
+}
+
void Node::InvalidateLayoutBoxesFromNodeAndAncestors() {
if (parent_) {
parent_->InvalidateLayoutBoxesFromNodeAndAncestors();
@@ -566,9 +575,14 @@
// Custom, not in any spec.
OnMutation();
- InvalidateLayoutBoxesFromNodeAndAncestors();
node->UpdateGenerationForNodeAndAncestors();
+ // Invalidate the layout boxes of the new parent as a result of its children
+ // being changed.
+ // NOTE: The added node does not have any invalidations done, because they
+ // occur on the remove and are guaranteed to not be needed at this point.
+ InvalidateLayoutBoxesFromNodeAndAncestors();
+
if (inserted_into_document_) {
node->OnInsertedIntoDocument();
Document* document = node_document();
@@ -600,10 +614,17 @@
DCHECK(node);
OnMutation();
- InvalidateLayoutBoxesFromNodeAndAncestors();
- node->InvalidateLayoutBoxesFromNodeAndDescendants();
node->UpdateGenerationForNodeAndAncestors();
+ // Invalidate the layout boxes of the previous parent as a result of its
+ // children being changed.
+ InvalidateLayoutBoxesFromNodeAndAncestors();
+ // Invalidate the styles and layout boxes of the node being removed from
+ // the tree. These are no longer valid as a result of the child and its
+ // descendants losing their inherited styles.
+ node->InvalidateComputedStylesRecursively();
+ node->InvalidateLayoutBoxesFromNodeAndDescendants();
+
bool was_inserted_to_document = node->inserted_into_document_;
if (was_inserted_to_document) {
node->OnRemovedFromDocument();
diff --git a/src/cobalt/dom/node.h b/src/cobalt/dom/node.h
index 0b2ca54..0c2a4f6 100644
--- a/src/cobalt/dom/node.h
+++ b/src/cobalt/dom/node.h
@@ -231,6 +231,8 @@
// removed from to its owner document.
virtual void OnRemovedFromDocument();
+ // Invalidate computed styles from this node and all child nodes.
+ virtual void InvalidateComputedStylesRecursively();
// Invalidate layout boxes from this node and all parent nodes.
virtual void InvalidateLayoutBoxesFromNodeAndAncestors();
// Invalidate layout boxes from this node and all child nodes.
diff --git a/src/cobalt/dom/test_runner.cc b/src/cobalt/dom/test_runner.cc
index c81aded..f838050 100644
--- a/src/cobalt/dom/test_runner.cc
+++ b/src/cobalt/dom/test_runner.cc
@@ -24,21 +24,21 @@
TestRunner::TestRunner() : should_wait_(false) {}
void TestRunner::NotifyDone() {
- DCHECK(should_wait_);
- should_wait_ = false;
- if (!trigger_layout_callback_.is_null()) {
- trigger_layout_callback_.Run();
+ if (should_wait_) {
+ should_wait_ = false;
+ if (!trigger_layout_callback_.is_null()) {
+ trigger_layout_callback_.Run();
+ }
+ // Reset |should_wait_| to prevent a second layout if the document onLoad
+ // event occurs after the layout trigger.
+ should_wait_ = true;
}
- // Reset |should_wait_| to prevent a second layout if the document onLoad
- // event occurs after the layout trigger.
- should_wait_ = true;
}
void TestRunner::WaitUntilDone() { should_wait_ = true; }
void TestRunner::DoNonMeasuredLayout() {
- DCHECK(should_wait_);
- if (!trigger_layout_callback_.is_null()) {
+ if (should_wait_ && !trigger_layout_callback_.is_null()) {
trigger_layout_callback_.Run();
}
}
diff --git a/src/cobalt/layout/box_generator.cc b/src/cobalt/layout/box_generator.cc
index 1f2d803..99f2b2c 100644
--- a/src/cobalt/layout/box_generator.cc
+++ b/src/cobalt/layout/box_generator.cc
@@ -325,9 +325,13 @@
DCHECK(*paragraph_);
int32 text_position = (*paragraph_)->GetTextEndPosition();
- scoped_refptr<TextBox> br_text_box = new TextBox(
- css_computed_style_declaration, *paragraph_, text_position, text_position,
- true, context_->used_style_provider, context_->layout_stat_tracker);
+ const bool kTriggersLineBreakTrue = true;
+ const bool kIsProductOfSplitFalse = false;
+
+ scoped_refptr<TextBox> br_text_box =
+ new TextBox(css_computed_style_declaration, *paragraph_, text_position,
+ text_position, kTriggersLineBreakTrue, kIsProductOfSplitFalse,
+ context_->used_style_provider, context_->layout_stat_tracker);
// Add a line feed code point to the paragraph to signify the new line for
// the line breaking and bidirectional algorithms.
@@ -953,10 +957,12 @@
(*paragraph_)->AppendUtf8String(modifiable_text, transform);
int32 text_end_position = (*paragraph_)->GetTextEndPosition();
+ const bool kIsProductOfSplitFalse = false;
+
boxes_.push_back(new TextBox(
css_computed_style_declaration, *paragraph_, text_start_position,
- text_end_position, generates_newline, context_->used_style_provider,
- context_->layout_stat_tracker));
+ text_end_position, generates_newline, kIsProductOfSplitFalse,
+ context_->used_style_provider, context_->layout_stat_tracker));
// Newline sequences should be transformed into a preserved line feed.
// https://www.w3.org/TR/css3-text/#line-break-transform
diff --git a/src/cobalt/layout/text_box.cc b/src/cobalt/layout/text_box.cc
index 1b4e96e..c0cb5fb 100644
--- a/src/cobalt/layout/text_box.cc
+++ b/src/cobalt/layout/text_box.cc
@@ -37,7 +37,7 @@
css_computed_style_declaration,
const scoped_refptr<Paragraph>& paragraph,
int32 text_start_position, int32 text_end_position,
- bool has_trailing_line_break,
+ bool has_trailing_line_break, bool is_product_of_split,
UsedStyleProvider* used_style_provider,
LayoutStatTracker* layout_stat_tracker)
: Box(css_computed_style_declaration, used_style_provider,
@@ -58,6 +58,7 @@
should_collapse_leading_white_space_(false),
should_collapse_trailing_white_space_(false),
has_trailing_line_break_(has_trailing_line_break),
+ is_product_of_split_(is_product_of_split),
update_size_results_valid_(false),
ascent_(0) {
DCHECK(text_start_position_ <= text_end_position_);
@@ -177,10 +178,19 @@
}
// Even when the text box's style prevents wrapping, wrapping can still occur
- // before the box if the line's existence has already been justified and
- // whitespace precedes the box.
+ // before the box if the following requirements are met:
+ // - The text box is not the product of a split. If it is, and this box's
+ // style prevents text wrapping, then the previous box also prevents text
+ // wrapping, and no wrap should occur between them.
+ // - The line's existence has already been justified. Wrapping cannot occur
+ // prior to that.
+ // - Whitespace precedes the text box. This can only occur in the case where
+ // the preceding box allows wrapping, otherwise a no-breaking space will
+ // have been appended (the one exception to this is when this box was the
+ // product of a split, but that case is already handled above).
if (!DoesAllowTextWrapping(computed_style()->white_space())) {
- if (is_line_existence_justified && text_start_position_ > 0 &&
+ if (!is_product_of_split_ && is_line_existence_justified &&
+ text_start_position_ > 0 &&
paragraph_->IsCollapsibleWhiteSpace(text_start_position_ - 1)) {
return kWrapResultWrapBefore;
} else {
@@ -640,10 +650,12 @@
update_size_results_valid_ = false;
non_collapsible_text_width_ = base::nullopt;
+ const bool kIsProductOfSplitTrue = true;
+
scoped_refptr<TextBox> box_after_split(new TextBox(
css_computed_style_declaration(), paragraph_, split_start_position,
- split_end_position, has_trailing_line_break_, used_style_provider(),
- layout_stat_tracker()));
+ split_end_position, has_trailing_line_break_, kIsProductOfSplitTrue,
+ used_style_provider(), layout_stat_tracker()));
// Update the split sibling links.
box_after_split->split_sibling_ = split_sibling_;
diff --git a/src/cobalt/layout/text_box.h b/src/cobalt/layout/text_box.h
index dc55439..c7008eb 100644
--- a/src/cobalt/layout/text_box.h
+++ b/src/cobalt/layout/text_box.h
@@ -40,7 +40,7 @@
css_computed_style_declaration,
const scoped_refptr<Paragraph>& paragraph, int32 text_start_position,
int32 text_end_position, bool triggers_line_break,
- UsedStyleProvider* used_style_provider,
+ bool is_created_from_split, UsedStyleProvider* used_style_provider,
LayoutStatTracker* layout_stat_tracker);
// From |Box|.
@@ -180,6 +180,10 @@
// A vertical offset of the baseline relatively to the origin of the text box.
base::optional<LayoutUnit> baseline_offset_from_top_;
+ // Specifies whether or not this text box was created as a result of the split
+ // of a text box.
+ const bool is_product_of_split_;
+
// A reference to the next text box in a linked list of text boxes produced
// from splits of the initial text box. This enables HTMLElement to retain
// access to all of its layout boxes after they are split.
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/3-bidirectional-content-should-overflow-the-line-with-white-space-nowrap-expected.png b/src/cobalt/layout_tests/testdata/css-text-3/3-bidirectional-content-should-overflow-the-line-with-white-space-nowrap-expected.png
new file mode 100644
index 0000000..03e1d7a
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css-text-3/3-bidirectional-content-should-overflow-the-line-with-white-space-nowrap-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/3-bidirectional-content-should-overflow-the-line-with-white-space-nowrap.html b/src/cobalt/layout_tests/testdata/css-text-3/3-bidirectional-content-should-overflow-the-line-with-white-space-nowrap.html
new file mode 100644
index 0000000..032c4e5
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css-text-3/3-bidirectional-content-should-overflow-the-line-with-white-space-nowrap.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+ | The value "nowrap" of property "white-space" does not allow wrapping. Content
+ | that does not fit the block container overflows it.
+ | https://www.w3.org/TR/css3-text/#white-space-property
+ -->
+<html>
+<head>
+ <meta charset="utf-8">
+ <style>
+ body {
+ margin: 0px;
+ font-family: Roboto;
+ font-size: 20px;
+ }
+ span {
+ white-space: nowrap;
+ }
+ .containing-block {
+ background-color: #03a9f4;
+ width: 200px;
+ }
+ </style>
+</head>
+<body>
+ <div class="containing-block">
+ <span>الØلقة النهائية من #MBCTheVoiceKids بتقنية الـ 360</span>
+ </div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt b/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt
index a001297..f76855c 100644
--- a/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt
+++ b/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt
@@ -1,4 +1,5 @@
2-1-letters-should-all-appear-in-uppercase-with-text-transform-uppercase
+3-bidirectional-content-should-overflow-the-line-with-white-space-nowrap
3-br-elements-within-white-space-nowrap-block-should-generate-new-lines
3-br-elements-within-white-space-pre-block-should-generate-new-lines
3-br-elements-within-white-space-pre-line-block-should-generate-new-lines
diff --git a/src/cobalt/layout_tests/testdata/incremental-layout/child-being-moved-to-new-parent-should-trigger-inherited-style-update-expected.png b/src/cobalt/layout_tests/testdata/incremental-layout/child-being-moved-to-new-parent-should-trigger-inherited-style-update-expected.png
new file mode 100644
index 0000000..c3f8378
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/incremental-layout/child-being-moved-to-new-parent-should-trigger-inherited-style-update-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/incremental-layout/child-being-moved-to-new-parent-should-trigger-inherited-style-update.html b/src/cobalt/layout_tests/testdata/incremental-layout/child-being-moved-to-new-parent-should-trigger-inherited-style-update.html
new file mode 100644
index 0000000..de05b21
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/incremental-layout/child-being-moved-to-new-parent-should-trigger-inherited-style-update.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+ | When a child is moved from one parent to another it should update
+ | its inherited properties with the style of the new parent.
+ -->
+<html>
+<head>
+ <style>
+ body {
+ margin: 0px;
+ font-family: Roboto;
+ font-size: 18px;
+ }
+ #small-font {
+ font-size: 20px;
+ font-style: normal;
+ }
+ #large-font {
+ font-size: 40px;
+ font-style: italic;
+ }
+ </style>
+ <script>
+ if (window.testRunner) {
+ window.testRunner.waitUntilDone();
+ }
+
+ window.onload = function() {
+ if (window.testRunner) {
+ window.testRunner.DoNonMeasuredLayout();
+ }
+
+ var child = document.getElementById('child');
+ child.parentNode.removeChild(child);
+
+ var new_parent = document.getElementById('large-font');
+ new_parent.appendChild(child);
+
+ if (window.testRunner) {
+ window.testRunner.notifyDone();
+ }
+ }
+ </script>
+</head>
+<body>
+ <span id="small-font"><span id="child">TEST</span></span>
+ <span id="large-font"></span>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/incremental-layout/layout_tests.txt b/src/cobalt/layout_tests/testdata/incremental-layout/layout_tests.txt
index d6667ab..b74e440 100644
--- a/src/cobalt/layout_tests/testdata/incremental-layout/layout_tests.txt
+++ b/src/cobalt/layout_tests/testdata/incremental-layout/layout_tests.txt
@@ -1,4 +1,5 @@
added_inline_child_of_inline_box_gets_rendered
+child-being-moved-to-new-parent-should-trigger-inherited-style-update
computed_style_change_gets_rendered
cross_references_style_change_should_trigger_containing_block_update
cross_references_style_change_should_trigger_stacking_context_update
diff --git a/src/cobalt/loader/about_fetcher.cc b/src/cobalt/loader/about_fetcher.cc
index 478c08e..81efad0 100644
--- a/src/cobalt/loader/about_fetcher.cc
+++ b/src/cobalt/loader/about_fetcher.cc
@@ -22,10 +22,15 @@
namespace cobalt {
namespace loader {
-AboutFetcher::AboutFetcher(Handler* handler) : Fetcher(handler) {
+AboutFetcher::AboutFetcher(Handler* handler)
+ : Fetcher(handler),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&Handler::OnDone, base::Unretained(handler), this));
+ FROM_HERE,
+ base::Bind(&AboutFetcher::Fetch, weak_ptr_factory_.GetWeakPtr()));
}
+void AboutFetcher::Fetch() { handler()->OnDone(this); }
+
} // namespace loader
} // namespace cobalt
diff --git a/src/cobalt/loader/about_fetcher.h b/src/cobalt/loader/about_fetcher.h
index deedfbd..606b7ef 100644
--- a/src/cobalt/loader/about_fetcher.h
+++ b/src/cobalt/loader/about_fetcher.h
@@ -19,6 +19,7 @@
#if defined(ENABLE_ABOUT_SCHEME)
+#include "base/memory/weak_ptr.h"
#include "cobalt/loader/fetcher.h"
namespace cobalt {
@@ -29,6 +30,11 @@
class AboutFetcher : public Fetcher {
public:
explicit AboutFetcher(Handler* handler);
+
+ void Fetch();
+
+ private:
+ base::WeakPtrFactory<AboutFetcher> weak_ptr_factory_;
};
} // namespace loader
diff --git a/src/cobalt/loader/embedded_resources/splash_screen.css b/src/cobalt/loader/embedded_resources/splash_screen.css
index c1400c9..0af40bf 100644
--- a/src/cobalt/loader/embedded_resources/splash_screen.css
+++ b/src/cobalt/loader/embedded_resources/splash_screen.css
@@ -1,5 +1,6 @@
body {
overflow: hidden;
+ font-size: 1.4815vh; /* Corresponds to 16px at 1080p. */
}
#splash {
diff --git a/src/cobalt/media/fetcher_buffered_data_source.cc b/src/cobalt/media/fetcher_buffered_data_source.cc
index 3d96ea7..b50aabc 100644
--- a/src/cobalt/media/fetcher_buffered_data_source.cc
+++ b/src/cobalt/media/fetcher_buffered_data_source.cc
@@ -113,7 +113,6 @@
DCHECK(message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
- DCHECK_EQ(fetcher_.get(), source);
if (fetcher_.get() != source) {
return;
}
diff --git a/src/cobalt/renderer/backend/egl/graphics_context.cc b/src/cobalt/renderer/backend/egl/graphics_context.cc
index e62c053..a418417 100644
--- a/src/cobalt/renderer/backend/egl/graphics_context.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_context.cc
@@ -390,7 +390,6 @@
void GraphicsContextEGL::SwapBuffers(RenderTargetEGL* surface) {
TRACE_EVENT0("cobalt::renderer", "GraphicsContextEGL::SwapBuffers()");
- GL_CALL(glFlush());
EGL_CALL(eglSwapBuffers(display_, surface->GetSurface()));
surface->increment_swap_count();
diff --git a/src/cobalt/renderer/backend/egl/graphics_system.cc b/src/cobalt/renderer/backend/egl/graphics_system.cc
index 4d615d5..16b5104 100644
--- a/src/cobalt/renderer/backend/egl/graphics_system.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_system.cc
@@ -16,6 +16,9 @@
#include "cobalt/renderer/backend/egl/graphics_system.h"
+#if defined(ENABLE_GLIMP_TRACING)
+#include "base/debug/trace_event.h"
+#endif
#if defined(GLES3_SUPPORTED)
#include "cobalt/renderer/backend/egl/texture_data_pbo.h"
#else
@@ -26,12 +29,34 @@
#include "cobalt/renderer/backend/egl/graphics_context.h"
#include "cobalt/renderer/backend/egl/texture.h"
#include "cobalt/renderer/backend/egl/utils.h"
+#if defined(ENABLE_GLIMP_TRACING)
+#include "glimp/tracing/tracing.h"
+#endif
namespace cobalt {
namespace renderer {
namespace backend {
+#if defined(ENABLE_GLIMP_TRACING)
+// Hookup glimp tracing to Chromium's base trace_event tracing.
+class GlimpToBaseTraceEventBridge : public glimp::TraceEventImpl {
+ public:
+ void BeginTrace(const char* name) OVERRIDE {
+ TRACE_EVENT_BEGIN0("glimp", name);
+ }
+ void EndTrace(const char* name) OVERRIDE { TRACE_EVENT_END0("glimp", name); }
+};
+
+GlimpToBaseTraceEventBridge s_glimp_to_base_trace_event_bridge;
+#endif // #if defined(ENABLE_GLIMP_TRACING)
+
GraphicsSystemEGL::GraphicsSystemEGL() {
+#if defined(ENABLE_GLIMP_TRACING)
+ // If glimp tracing is enabled, hook up glimp trace calls to Chromium's
+ // base trace_event calls.
+ glimp::SetTraceEventImplementation(&s_glimp_to_base_trace_event_bridge);
+#endif // #if defined(ENABLE_GLIMP_TRACING)
+
display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
CHECK_NE(EGL_NO_DISPLAY, display_);
CHECK_EQ(EGL_SUCCESS, eglGetError());
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
index 1a1fc84..2cb69c9 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
@@ -30,7 +30,6 @@
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
-#include "third_party/skia/include/ports/SkFontMgr.h"
using cobalt::render_tree::Image;
using cobalt::render_tree::ImageData;
@@ -45,6 +44,7 @@
backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context)
: cobalt_context_(cobalt_context),
gr_context_(gr_context),
+ font_manager_(SkFontMgr::RefDefault()),
self_message_loop_(MessageLoop::current()) {}
bool HardwareResourceProvider::PixelFormatSupported(
@@ -137,8 +137,8 @@
TRACE_EVENT0("cobalt::renderer",
"HardwareResourceProvider::HasLocalFontFamily()");
- SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
- SkAutoTUnref<SkFontStyleSet> style_set(fm->matchFamily(font_family_name));
+ SkAutoTUnref<SkFontStyleSet> style_set(
+ font_manager_->matchFamily(font_family_name));
return style_set->count() > 0;
}
@@ -147,8 +147,7 @@
TRACE_EVENT0("cobalt::renderer",
"HardwareResourceProvider::GetLocalTypeface()");
- SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
- SkAutoTUnref<SkTypeface> typeface(fm->matchFamilyStyle(
+ SkAutoTUnref<SkTypeface> typeface(font_manager_->matchFamilyStyle(
font_family_name, CobaltFontStyleToSkFontStyle(font_style)));
return scoped_refptr<render_tree::Typeface>(new SkiaTypeface(typeface));
}
@@ -160,10 +159,9 @@
TRACE_EVENT0("cobalt::renderer",
"HardwareResourceProvider::GetCharacterFallbackTypeface()");
- SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
- SkAutoTUnref<SkTypeface> typeface(
- fm->matchFamilyStyleCharacter(0, CobaltFontStyleToSkFontStyle(font_style),
- language.c_str(), character));
+ SkAutoTUnref<SkTypeface> typeface(font_manager_->matchFamilyStyleCharacter(
+ 0, CobaltFontStyleToSkFontStyle(font_style), language.c_str(),
+ character));
return scoped_refptr<render_tree::Typeface>(new SkiaTypeface(typeface));
}
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
index aec9c85..5e01f73 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
@@ -24,6 +24,7 @@
#include "cobalt/renderer/rasterizer/skia/hardware_image.h"
#include "cobalt/renderer/rasterizer/skia/text_shaper.h"
#include "third_party/skia/include/gpu/GrContext.h"
+#include "third_party/skia/include/ports/SkFontMgr.h"
namespace cobalt {
namespace renderer {
@@ -89,6 +90,7 @@
backend::GraphicsContextEGL* cobalt_context_;
GrContext* gr_context_;
+ SkAutoTUnref<SkFontMgr> font_manager_;
TextShaper text_shaper_;
// We keep a handle to the message loop that this resource provider was
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
index 6c9c5f6..1f8996b 100644
--- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
@@ -685,6 +685,12 @@
const cobalt::render_tree::SolidColorBrush* solid_color_brush) {
const cobalt::render_tree::ColorRGBA& color = solid_color_brush->color();
+ if (color.a() == 1.0f) {
+ paint_->setXfermodeMode(SkXfermode::kSrc_Mode);
+ } else {
+ paint_->setXfermodeMode(SkXfermode::kSrcOver_Mode);
+ }
+
paint_->setARGB(color.a() * 255, color.r() * 255, color.g() * 255,
color.b() * 255);
}
@@ -695,8 +701,14 @@
// methods will easily accept.
struct SkiaColorStops {
explicit SkiaColorStops(const render_tree::ColorStopList& color_stops)
- : colors(color_stops.size()), positions(color_stops.size()) {
+ : colors(color_stops.size()),
+ positions(color_stops.size()),
+ has_alpha(false) {
for (size_t i = 0; i < color_stops.size(); ++i) {
+ if (color_stops[i].color.a() < 1.0f) {
+ has_alpha = true;
+ }
+
colors[i] = ToSkColor(color_stops[i].color);
positions[i] = color_stops[i].position;
}
@@ -704,6 +716,7 @@
std::vector<SkColor> colors;
std::vector<SkScalar> positions;
+ bool has_alpha;
};
} // namespace
@@ -722,6 +735,12 @@
linear_gradient_brush->color_stops().size(), SkShader::kClamp_TileMode,
SkGradientShader::kInterpolateColorsInPremul_Flag, NULL));
paint_->setShader(shader);
+
+ if (!skia_color_stops.has_alpha) {
+ paint_->setXfermodeMode(SkXfermode::kSrc_Mode);
+ } else {
+ paint_->setXfermodeMode(SkXfermode::kSrcOver_Mode);
+ }
}
void SkiaBrushVisitor::Visit(
@@ -751,6 +770,12 @@
radial_gradient_brush->color_stops().size(), SkShader::kClamp_TileMode,
SkGradientShader::kInterpolateColorsInPremul_Flag, &local_matrix));
paint_->setShader(shader);
+
+ if (!skia_color_stops.has_alpha) {
+ paint_->setXfermodeMode(SkXfermode::kSrc_Mode);
+ } else {
+ paint_->setXfermodeMode(SkXfermode::kSrcOver_Mode);
+ }
}
void DrawRectWithBrush(SkCanvas* render_target,
@@ -820,6 +845,11 @@
paint.setARGB(color.a() * 255, color.r() * 255, color.g() * 255,
color.b() * 255);
paint.setAntiAlias(anti_alias);
+ if (color.a() == 1.0f) {
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ } else {
+ paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+ }
SkPath path;
path.addPoly(points, 4, true);
@@ -902,6 +932,11 @@
const render_tree::ColorRGBA& color = border.top.color;
paint.setARGB(color.a() * 255, color.r() * 255, color.g() * 255,
color.b() * 255);
+ if (color.a() == 1.0f) {
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ } else {
+ paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+ }
render_target->drawDRRect(
RoundedRectToSkia(rect, rounded_corners),
diff --git a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc
index 409c787..f959c8b 100644
--- a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc
+++ b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc
@@ -73,6 +73,10 @@
// state when re-using the sk_surface.
canvas->save();
+ // Indicate that we do not care about the existing state of the canvas, which
+ // can allow for optimization on tile-based renderers.
+ canvas->discard();
+
// Setup a clip rect on the sk_surface to the requested area. This can save
// us from drawing to pixels outside of the requested area, since the actual
// sk_surface returned may be larger than the requested area.
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h b/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h
index 5695744..078fff6 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h
+++ b/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h
@@ -237,10 +237,18 @@
// ===== End Cobalt-specific definitions =====
+// GrGLConfig.h settings customization for Cobalt.
+
#if defined(STARBOARD)
#if SB_HAS_QUIRK(GL_NO_CONSTANT_ATTRIBUTE_SUPPORT)
#define GR_GL_NO_CONSTANT_ATTRIBUTES 1
#endif // SB_HAS_QUIRK(GL_NO_CONSTANT_ATTRIBUTE_SUPPORT)
#endif // defined(STARBOARD)
+// Avoid calling glGetError() after glTexImage, glBufferData,
+// glRenderbufferStorage, etc... It can be potentially expensive to call on
+// some platforms, and Cobalt is designed for devices where we can ensure we
+// do not fail by running out of memory.
+#define GR_GL_CHECK_ALLOC_WITH_GET_ERROR 0
+
#endif // SkUserConfig_DEFINED
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
index 93717ca..5be8703 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
+++ b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
@@ -17,13 +17,11 @@
'sources': [
'config/SkUserConfig.h',
- 'egl/src/gpu/cobalt/GrGpuFactory.cc',
'src/effects/SkNV122RGBShader.cc',
'src/effects/SkNV122RGBShader.h',
'src/effects/SkYUV2RGBShader.cc',
'src/effects/SkYUV2RGBShader.h',
'src/google_logging.cc',
- 'src/gpu/gl/GrGLCreateNativeInterface_cobalt.cc',
'src/ports/SkFontConfigParser_cobalt.cc',
'src/ports/SkFontConfigParser_cobalt.h',
'src/ports/SkFontMgr_cobalt.cc',
@@ -46,5 +44,11 @@
'src/ports/SkMemory_starboard.cc',
],
}],
+ ['gl_type != "none"', {
+ 'sources': [
+ 'egl/src/gpu/cobalt/GrGpuFactory.cc',
+ 'src/gpu/gl/GrGLCreateNativeInterface_cobalt.cc',
+ ],
+ }],
],
}
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
index abe46c6..ee59b76 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
@@ -37,6 +37,9 @@
namespace rasterizer {
namespace skia {
+SoftwareResourceProvider::SoftwareResourceProvider()
+ : font_manager_(SkFontMgr::RefDefault()) {}
+
bool SoftwareResourceProvider::PixelFormatSupported(
render_tree::PixelFormat pixel_format) {
return RenderTreeSurfaceFormatToSkia(pixel_format) == kN32_SkColorType;
@@ -99,8 +102,8 @@
TRACE_EVENT0("cobalt::renderer",
"SoftwareResourceProvider::HasLocalFontFamily()");
- SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
- SkAutoTUnref<SkFontStyleSet> style_set(fm->matchFamily(font_family_name));
+ SkAutoTUnref<SkFontStyleSet> style_set(
+ font_manager_->matchFamily(font_family_name));
return style_set->count() > 0;
}
@@ -108,8 +111,7 @@
const char* font_family_name, render_tree::FontStyle font_style) {
TRACE_EVENT0("cobalt::renderer", "SoftwareResourceProvider::GetLocalFont()");
- SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
- SkAutoTUnref<SkTypeface> typeface(fm->matchFamilyStyle(
+ SkAutoTUnref<SkTypeface> typeface(font_manager_->matchFamilyStyle(
font_family_name, CobaltFontStyleToSkFontStyle(font_style)));
return scoped_refptr<render_tree::Typeface>(new SkiaTypeface(typeface));
}
@@ -121,10 +123,9 @@
TRACE_EVENT0("cobalt::renderer",
"SoftwareResourceProvider::GetCharacterFallbackTypeface()");
- SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
- SkAutoTUnref<SkTypeface> typeface(
- fm->matchFamilyStyleCharacter(0, CobaltFontStyleToSkFontStyle(font_style),
- language.c_str(), character));
+ SkAutoTUnref<SkTypeface> typeface(font_manager_->matchFamilyStyleCharacter(
+ 0, CobaltFontStyleToSkFontStyle(font_style), language.c_str(),
+ character));
return scoped_refptr<render_tree::Typeface>(new SkiaTypeface(typeface));
}
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
index 890f929..fd4419e 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
@@ -21,6 +21,7 @@
#include "cobalt/render_tree/resource_provider.h"
#include "cobalt/renderer/rasterizer/skia/text_shaper.h"
+#include "third_party/skia/include/ports/SkFontMgr.h"
namespace cobalt {
namespace renderer {
@@ -31,6 +32,8 @@
// are to be consumed by this skia software rasterizer.
class SoftwareResourceProvider : public render_tree::ResourceProvider {
public:
+ SoftwareResourceProvider();
+
bool PixelFormatSupported(render_tree::PixelFormat pixel_format) OVERRIDE;
bool AlphaFormatSupported(render_tree::AlphaFormat alpha_format) OVERRIDE;
@@ -79,6 +82,7 @@
render_tree::FontVector* maybe_used_fonts) OVERRIDE;
private:
+ SkAutoTUnref<SkFontMgr> font_manager_;
TextShaper text_shaper_;
};
diff --git a/src/cobalt/script/mozjs/mozjs.gyp b/src/cobalt/script/mozjs/mozjs.gyp
index 49f8313..23ec990 100644
--- a/src/cobalt/script/mozjs/mozjs.gyp
+++ b/src/cobalt/script/mozjs/mozjs.gyp
@@ -27,7 +27,12 @@
'mozjs_property_enumerator.cc',
'mozjs_source_code.cc',
'proxy_handler.cc',
+ 'referenced_object_map.cc',
'util/exception_helpers.cc',
+ 'weak_heap_object.cc',
+ 'weak_heap_object.h',
+ 'weak_heap_object_manager.cc',
+ 'weak_heap_object_manager.h',
'wrapper_factory.cc',
'wrapper_private.cc',
],
@@ -40,7 +45,8 @@
'defines': [
# SpiderMonkey bindings implements indexed deleters.
'ENGINE_SUPPORTS_INDEXED_DELETERS',
- 'ENGINE_SUPPORTS_INT64', ],
+ 'ENGINE_SUPPORTS_INT64',
+ 'ENGINE_SUPPORTS_STACK_TRACE_COLUMNS', ],
},
'conditions' :[
['cobalt_enable_jit == 1', {
diff --git a/src/cobalt/script/mozjs/mozjs_callback_function.h b/src/cobalt/script/mozjs/mozjs_callback_function.h
index bcdf94e..2994166 100644
--- a/src/cobalt/script/mozjs/mozjs_callback_function.h
+++ b/src/cobalt/script/mozjs/mozjs_callback_function.h
@@ -27,6 +27,7 @@
#include "cobalt/script/callback_function.h"
#include "cobalt/script/mozjs/conversion_helpers.h"
#include "cobalt/script/mozjs/convert_callback_return_value.h"
+#include "cobalt/script/mozjs/weak_heap_object.h"
#include "third_party/mozjs/js/src/jsapi.h"
#include "third_party/mozjs/js/src/jscntxt.h"
@@ -49,40 +50,44 @@
typedef CallbackFunction<R()> BaseType;
explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
- : context_(context), function_(function) {
+ : context_(context), weak_function_(context, function) {
DCHECK(context_);
- DCHECK(JS_ObjectIsFunction(context_, function_));
+ DCHECK(JS_ObjectIsFunction(context_, function));
}
CallbackResult<R> Run()
const OVERRIDE {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, function_);
-
- // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
- // Callback 'this' is set to null, unless overridden by other specifications
- JS::Value this_value(JS::NullValue());
- JS::RootedValue return_value(context_);
- const int kNumArguments = 0;
-
- JSBool call_result = JS::Call(context_, this_value, function_, 0, NULL,
- return_value.address());
-
+ JS::RootedObject function(context_, weak_function_.Get());
CallbackResult<R> callback_result;
- if (!call_result) {
- DLOG(WARNING) << "Exception in callback.";
- callback_result.exception = true;
- } else {
- callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ DLOG_IF(WARNING, !function) << "Function was garbage collected.";
+ if (function) {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, function);
+
+ // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+ // Callback 'this' is set to null, unless overridden by other
+ // specifications
+ JS::Value this_value(JS::NullValue());
+ JS::RootedValue return_value(context_);
+ const int kNumArguments = 0;
+
+ JSBool call_result = JS::Call(context_, this_value, function, 0, NULL,
+ return_value.address());
+ if (!call_result) {
+ DLOG(WARNING) << "Exception in callback.";
+ callback_result.exception = true;
+ } else {
+ callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ }
}
return callback_result;
}
- JSObject* handle() const { return function_; }
+ JSObject* handle() const { return weak_function_.Get(); }
private:
JSContext* context_;
- mutable JS::Heap<JSObject*> function_;
+ WeakHeapObject weak_function_;
};
template <typename R, typename A1>
@@ -92,46 +97,50 @@
typedef CallbackFunction<R(A1)> BaseType;
explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
- : context_(context), function_(function) {
+ : context_(context), weak_function_(context, function) {
DCHECK(context_);
- DCHECK(JS_ObjectIsFunction(context_, function_));
+ DCHECK(JS_ObjectIsFunction(context_, function));
}
CallbackResult<R> Run(
typename base::internal::CallbackParamTraits<A1>::ForwardType a1)
const OVERRIDE {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, function_);
-
- // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
- // Callback 'this' is set to null, unless overridden by other specifications
- JS::Value this_value(JS::NullValue());
- JS::RootedValue return_value(context_);
- const int kNumArguments = 1;
-
- JS::Value args[1];
- js::SetValueRangeToNull(args, kNumArguments);
- js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
- ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
-
- JSBool call_result = JS::Call(context_, this_value, function_,
- kNumArguments, args, return_value.address());
-
+ JS::RootedObject function(context_, weak_function_.Get());
CallbackResult<R> callback_result;
- if (!call_result) {
- DLOG(WARNING) << "Exception in callback.";
- callback_result.exception = true;
- } else {
- callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ DLOG_IF(WARNING, !function) << "Function was garbage collected.";
+ if (function) {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, function);
+
+ // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+ // Callback 'this' is set to null, unless overridden by other
+ // specifications
+ JS::Value this_value(JS::NullValue());
+ JS::RootedValue return_value(context_);
+ const int kNumArguments = 1;
+
+ JS::Value args[1];
+ js::SetValueRangeToNull(args, kNumArguments);
+ js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+ ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+
+ JSBool call_result = JS::Call(context_, this_value, function,
+ kNumArguments, args, return_value.address());
+ if (!call_result) {
+ DLOG(WARNING) << "Exception in callback.";
+ callback_result.exception = true;
+ } else {
+ callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ }
}
return callback_result;
}
- JSObject* handle() const { return function_; }
+ JSObject* handle() const { return weak_function_.Get(); }
private:
JSContext* context_;
- mutable JS::Heap<JSObject*> function_;
+ WeakHeapObject weak_function_;
};
template <typename R, typename A1, typename A2>
@@ -141,48 +150,52 @@
typedef CallbackFunction<R(A1, A2)> BaseType;
explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
- : context_(context), function_(function) {
+ : context_(context), weak_function_(context, function) {
DCHECK(context_);
- DCHECK(JS_ObjectIsFunction(context_, function_));
+ DCHECK(JS_ObjectIsFunction(context_, function));
}
CallbackResult<R> Run(
typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
typename base::internal::CallbackParamTraits<A2>::ForwardType a2)
const OVERRIDE {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, function_);
-
- // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
- // Callback 'this' is set to null, unless overridden by other specifications
- JS::Value this_value(JS::NullValue());
- JS::RootedValue return_value(context_);
- const int kNumArguments = 2;
-
- JS::Value args[2];
- js::SetValueRangeToNull(args, kNumArguments);
- js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
- ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
- ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
-
- JSBool call_result = JS::Call(context_, this_value, function_,
- kNumArguments, args, return_value.address());
-
+ JS::RootedObject function(context_, weak_function_.Get());
CallbackResult<R> callback_result;
- if (!call_result) {
- DLOG(WARNING) << "Exception in callback.";
- callback_result.exception = true;
- } else {
- callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ DLOG_IF(WARNING, !function) << "Function was garbage collected.";
+ if (function) {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, function);
+
+ // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+ // Callback 'this' is set to null, unless overridden by other
+ // specifications
+ JS::Value this_value(JS::NullValue());
+ JS::RootedValue return_value(context_);
+ const int kNumArguments = 2;
+
+ JS::Value args[2];
+ js::SetValueRangeToNull(args, kNumArguments);
+ js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+ ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+ ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+
+ JSBool call_result = JS::Call(context_, this_value, function,
+ kNumArguments, args, return_value.address());
+ if (!call_result) {
+ DLOG(WARNING) << "Exception in callback.";
+ callback_result.exception = true;
+ } else {
+ callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ }
}
return callback_result;
}
- JSObject* handle() const { return function_; }
+ JSObject* handle() const { return weak_function_.Get(); }
private:
JSContext* context_;
- mutable JS::Heap<JSObject*> function_;
+ WeakHeapObject weak_function_;
};
template <typename R, typename A1, typename A2, typename A3>
@@ -192,9 +205,9 @@
typedef CallbackFunction<R(A1, A2, A3)> BaseType;
explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
- : context_(context), function_(function) {
+ : context_(context), weak_function_(context, function) {
DCHECK(context_);
- DCHECK(JS_ObjectIsFunction(context_, function_));
+ DCHECK(JS_ObjectIsFunction(context_, function));
}
CallbackResult<R> Run(
@@ -202,40 +215,44 @@
typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
typename base::internal::CallbackParamTraits<A3>::ForwardType a3)
const OVERRIDE {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, function_);
-
- // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
- // Callback 'this' is set to null, unless overridden by other specifications
- JS::Value this_value(JS::NullValue());
- JS::RootedValue return_value(context_);
- const int kNumArguments = 3;
-
- JS::Value args[3];
- js::SetValueRangeToNull(args, kNumArguments);
- js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
- ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
- ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
- ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
-
- JSBool call_result = JS::Call(context_, this_value, function_,
- kNumArguments, args, return_value.address());
-
+ JS::RootedObject function(context_, weak_function_.Get());
CallbackResult<R> callback_result;
- if (!call_result) {
- DLOG(WARNING) << "Exception in callback.";
- callback_result.exception = true;
- } else {
- callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ DLOG_IF(WARNING, !function) << "Function was garbage collected.";
+ if (function) {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, function);
+
+ // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+ // Callback 'this' is set to null, unless overridden by other
+ // specifications
+ JS::Value this_value(JS::NullValue());
+ JS::RootedValue return_value(context_);
+ const int kNumArguments = 3;
+
+ JS::Value args[3];
+ js::SetValueRangeToNull(args, kNumArguments);
+ js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+ ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+ ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+ ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
+
+ JSBool call_result = JS::Call(context_, this_value, function,
+ kNumArguments, args, return_value.address());
+ if (!call_result) {
+ DLOG(WARNING) << "Exception in callback.";
+ callback_result.exception = true;
+ } else {
+ callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ }
}
return callback_result;
}
- JSObject* handle() const { return function_; }
+ JSObject* handle() const { return weak_function_.Get(); }
private:
JSContext* context_;
- mutable JS::Heap<JSObject*> function_;
+ WeakHeapObject weak_function_;
};
template <typename R, typename A1, typename A2, typename A3, typename A4>
@@ -245,9 +262,9 @@
typedef CallbackFunction<R(A1, A2, A3, A4)> BaseType;
explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
- : context_(context), function_(function) {
+ : context_(context), weak_function_(context, function) {
DCHECK(context_);
- DCHECK(JS_ObjectIsFunction(context_, function_));
+ DCHECK(JS_ObjectIsFunction(context_, function));
}
CallbackResult<R> Run(
@@ -256,41 +273,45 @@
typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
typename base::internal::CallbackParamTraits<A4>::ForwardType a4)
const OVERRIDE {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, function_);
-
- // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
- // Callback 'this' is set to null, unless overridden by other specifications
- JS::Value this_value(JS::NullValue());
- JS::RootedValue return_value(context_);
- const int kNumArguments = 4;
-
- JS::Value args[4];
- js::SetValueRangeToNull(args, kNumArguments);
- js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
- ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
- ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
- ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
- ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
-
- JSBool call_result = JS::Call(context_, this_value, function_,
- kNumArguments, args, return_value.address());
-
+ JS::RootedObject function(context_, weak_function_.Get());
CallbackResult<R> callback_result;
- if (!call_result) {
- DLOG(WARNING) << "Exception in callback.";
- callback_result.exception = true;
- } else {
- callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ DLOG_IF(WARNING, !function) << "Function was garbage collected.";
+ if (function) {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, function);
+
+ // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+ // Callback 'this' is set to null, unless overridden by other
+ // specifications
+ JS::Value this_value(JS::NullValue());
+ JS::RootedValue return_value(context_);
+ const int kNumArguments = 4;
+
+ JS::Value args[4];
+ js::SetValueRangeToNull(args, kNumArguments);
+ js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+ ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+ ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+ ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
+ ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
+
+ JSBool call_result = JS::Call(context_, this_value, function,
+ kNumArguments, args, return_value.address());
+ if (!call_result) {
+ DLOG(WARNING) << "Exception in callback.";
+ callback_result.exception = true;
+ } else {
+ callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ }
}
return callback_result;
}
- JSObject* handle() const { return function_; }
+ JSObject* handle() const { return weak_function_.Get(); }
private:
JSContext* context_;
- mutable JS::Heap<JSObject*> function_;
+ WeakHeapObject weak_function_;
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
@@ -301,9 +322,9 @@
typedef CallbackFunction<R(A1, A2, A3, A4, A5)> BaseType;
explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
- : context_(context), function_(function) {
+ : context_(context), weak_function_(context, function) {
DCHECK(context_);
- DCHECK(JS_ObjectIsFunction(context_, function_));
+ DCHECK(JS_ObjectIsFunction(context_, function));
}
CallbackResult<R> Run(
@@ -313,42 +334,46 @@
typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
typename base::internal::CallbackParamTraits<A5>::ForwardType a5)
const OVERRIDE {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, function_);
-
- // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
- // Callback 'this' is set to null, unless overridden by other specifications
- JS::Value this_value(JS::NullValue());
- JS::RootedValue return_value(context_);
- const int kNumArguments = 5;
-
- JS::Value args[5];
- js::SetValueRangeToNull(args, kNumArguments);
- js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
- ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
- ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
- ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
- ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
- ToJSValue(context_, a5, auto_array_rooter.handleAt(4));
-
- JSBool call_result = JS::Call(context_, this_value, function_,
- kNumArguments, args, return_value.address());
-
+ JS::RootedObject function(context_, weak_function_.Get());
CallbackResult<R> callback_result;
- if (!call_result) {
- DLOG(WARNING) << "Exception in callback.";
- callback_result.exception = true;
- } else {
- callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ DLOG_IF(WARNING, !function) << "Function was garbage collected.";
+ if (function) {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, function);
+
+ // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+ // Callback 'this' is set to null, unless overridden by other
+ // specifications
+ JS::Value this_value(JS::NullValue());
+ JS::RootedValue return_value(context_);
+ const int kNumArguments = 5;
+
+ JS::Value args[5];
+ js::SetValueRangeToNull(args, kNumArguments);
+ js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+ ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+ ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+ ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
+ ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
+ ToJSValue(context_, a5, auto_array_rooter.handleAt(4));
+
+ JSBool call_result = JS::Call(context_, this_value, function,
+ kNumArguments, args, return_value.address());
+ if (!call_result) {
+ DLOG(WARNING) << "Exception in callback.";
+ callback_result.exception = true;
+ } else {
+ callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ }
}
return callback_result;
}
- JSObject* handle() const { return function_; }
+ JSObject* handle() const { return weak_function_.Get(); }
private:
JSContext* context_;
- mutable JS::Heap<JSObject*> function_;
+ WeakHeapObject weak_function_;
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
@@ -359,9 +384,9 @@
typedef CallbackFunction<R(A1, A2, A3, A4, A5, A6)> BaseType;
explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
- : context_(context), function_(function) {
+ : context_(context), weak_function_(context, function) {
DCHECK(context_);
- DCHECK(JS_ObjectIsFunction(context_, function_));
+ DCHECK(JS_ObjectIsFunction(context_, function));
}
CallbackResult<R> Run(
@@ -372,43 +397,47 @@
typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
typename base::internal::CallbackParamTraits<A6>::ForwardType a6)
const OVERRIDE {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, function_);
-
- // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
- // Callback 'this' is set to null, unless overridden by other specifications
- JS::Value this_value(JS::NullValue());
- JS::RootedValue return_value(context_);
- const int kNumArguments = 6;
-
- JS::Value args[6];
- js::SetValueRangeToNull(args, kNumArguments);
- js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
- ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
- ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
- ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
- ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
- ToJSValue(context_, a5, auto_array_rooter.handleAt(4));
- ToJSValue(context_, a6, auto_array_rooter.handleAt(5));
-
- JSBool call_result = JS::Call(context_, this_value, function_,
- kNumArguments, args, return_value.address());
-
+ JS::RootedObject function(context_, weak_function_.Get());
CallbackResult<R> callback_result;
- if (!call_result) {
- DLOG(WARNING) << "Exception in callback.";
- callback_result.exception = true;
- } else {
- callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ DLOG_IF(WARNING, !function) << "Function was garbage collected.";
+ if (function) {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, function);
+
+ // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+ // Callback 'this' is set to null, unless overridden by other
+ // specifications
+ JS::Value this_value(JS::NullValue());
+ JS::RootedValue return_value(context_);
+ const int kNumArguments = 6;
+
+ JS::Value args[6];
+ js::SetValueRangeToNull(args, kNumArguments);
+ js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+ ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+ ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+ ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
+ ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
+ ToJSValue(context_, a5, auto_array_rooter.handleAt(4));
+ ToJSValue(context_, a6, auto_array_rooter.handleAt(5));
+
+ JSBool call_result = JS::Call(context_, this_value, function,
+ kNumArguments, args, return_value.address());
+ if (!call_result) {
+ DLOG(WARNING) << "Exception in callback.";
+ callback_result.exception = true;
+ } else {
+ callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ }
}
return callback_result;
}
- JSObject* handle() const { return function_; }
+ JSObject* handle() const { return weak_function_.Get(); }
private:
JSContext* context_;
- mutable JS::Heap<JSObject*> function_;
+ WeakHeapObject weak_function_;
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
@@ -419,9 +448,9 @@
typedef CallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> BaseType;
explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
- : context_(context), function_(function) {
+ : context_(context), weak_function_(context, function) {
DCHECK(context_);
- DCHECK(JS_ObjectIsFunction(context_, function_));
+ DCHECK(JS_ObjectIsFunction(context_, function));
}
CallbackResult<R> Run(
@@ -433,44 +462,48 @@
typename base::internal::CallbackParamTraits<A6>::ForwardType a6,
typename base::internal::CallbackParamTraits<A7>::ForwardType a7)
const OVERRIDE {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, function_);
-
- // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
- // Callback 'this' is set to null, unless overridden by other specifications
- JS::Value this_value(JS::NullValue());
- JS::RootedValue return_value(context_);
- const int kNumArguments = 7;
-
- JS::Value args[7];
- js::SetValueRangeToNull(args, kNumArguments);
- js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
- ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
- ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
- ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
- ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
- ToJSValue(context_, a5, auto_array_rooter.handleAt(4));
- ToJSValue(context_, a6, auto_array_rooter.handleAt(5));
- ToJSValue(context_, a7, auto_array_rooter.handleAt(6));
-
- JSBool call_result = JS::Call(context_, this_value, function_,
- kNumArguments, args, return_value.address());
-
+ JS::RootedObject function(context_, weak_function_.Get());
CallbackResult<R> callback_result;
- if (!call_result) {
- DLOG(WARNING) << "Exception in callback.";
- callback_result.exception = true;
- } else {
- callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ DLOG_IF(WARNING, !function) << "Function was garbage collected.";
+ if (function) {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, function);
+
+ // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+ // Callback 'this' is set to null, unless overridden by other
+ // specifications
+ JS::Value this_value(JS::NullValue());
+ JS::RootedValue return_value(context_);
+ const int kNumArguments = 7;
+
+ JS::Value args[7];
+ js::SetValueRangeToNull(args, kNumArguments);
+ js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+ ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+ ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+ ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
+ ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
+ ToJSValue(context_, a5, auto_array_rooter.handleAt(4));
+ ToJSValue(context_, a6, auto_array_rooter.handleAt(5));
+ ToJSValue(context_, a7, auto_array_rooter.handleAt(6));
+
+ JSBool call_result = JS::Call(context_, this_value, function,
+ kNumArguments, args, return_value.address());
+ if (!call_result) {
+ DLOG(WARNING) << "Exception in callback.";
+ callback_result.exception = true;
+ } else {
+ callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ }
}
return callback_result;
}
- JSObject* handle() const { return function_; }
+ JSObject* handle() const { return weak_function_.Get(); }
private:
JSContext* context_;
- mutable JS::Heap<JSObject*> function_;
+ WeakHeapObject weak_function_;
};
template <typename Signature>
diff --git a/src/cobalt/script/mozjs/mozjs_callback_function.h.pump b/src/cobalt/script/mozjs/mozjs_callback_function.h.pump
index fb4e78e..6ea3efe 100644
--- a/src/cobalt/script/mozjs/mozjs_callback_function.h.pump
+++ b/src/cobalt/script/mozjs/mozjs_callback_function.h.pump
@@ -32,6 +32,7 @@
#include "cobalt/script/callback_function.h"
#include "cobalt/script/mozjs/conversion_helpers.h"
#include "cobalt/script/mozjs/convert_callback_return_value.h"
+#include "cobalt/script/mozjs/weak_heap_object.h"
#include "third_party/mozjs/js/src/jsapi.h"
#include "third_party/mozjs/js/src/jscntxt.h"
@@ -66,55 +67,60 @@
typedef CallbackFunction<R($for ARG , [[A$(ARG)]])> BaseType;
explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
- : context_(context), function_(function) {
+ : context_(context), weak_function_(context, function) {
DCHECK(context_);
- DCHECK(JS_ObjectIsFunction(context_, function_));
+ DCHECK(JS_ObjectIsFunction(context_, function));
}
CallbackResult<R> Run($for ARG , [[
typename base::internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]])
const OVERRIDE {
- JSAutoRequest auto_request(context_);
- JSAutoCompartment auto_compartment(context_, function_);
+ CallbackResult<R> callback_result;
+ JS::RootedObject function(context_, weak_function_.Get());
+ if (!function) {
+ DLOG(WARNING) << "Function was garbage collected.";
+ callback_result.exception = true;
+ } else {
+ JSAutoRequest auto_request(context_);
+ JSAutoCompartment auto_compartment(context_, function);
- // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
- // Callback 'this' is set to null, unless overridden by other specifications
- JS::Value this_value(JS::NullValue());
- JS::RootedValue return_value(context_);
- const int kNumArguments = $(ARITY);
+ // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+ // Callback 'this' is set to null, unless overridden by other specifications
+ JS::Value this_value(JS::NullValue());
+ JS::RootedValue return_value(context_);
+ const int kNumArguments = $(ARITY);
$if ARITY > 0 [[
- JS::Value args[$(ARITY)];
- js::SetValueRangeToNull(args, kNumArguments);
- js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
- $for ARG [[ToJSValue(context_, a$(ARG), auto_array_rooter.handleAt($(ARG - 1)));
- ]]
+ JS::Value args[$(ARITY)];
+ js::SetValueRangeToNull(args, kNumArguments);
+ js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+ $for ARG [[ToJSValue(context_, a$(ARG), auto_array_rooter.handleAt($(ARG - 1)));
+ ]]
- JSBool call_result = JS::Call(context_, this_value, function_,
- kNumArguments, args, return_value.address());
+ JSBool call_result = JS::Call(context_, this_value, function,
+ kNumArguments, args, return_value.address());
]] $else [[
- JSBool call_result = JS::Call(context_, this_value, function_, 0, NULL,
- return_value.address());
+ JSBool call_result = JS::Call(context_, this_value, function, 0, NULL,
+ return_value.address());
]]
-
- CallbackResult<R> callback_result;
- if (!call_result) {
- DLOG(WARNING) << "Exception in callback.";
- callback_result.exception = true;
- } else {
- callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ if (!call_result) {
+ DLOG(WARNING) << "Exception in callback.";
+ callback_result.exception = true;
+ } else {
+ callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+ }
}
return callback_result;
}
- JSObject* handle() const { return function_; }
+ JSObject* handle() const { return weak_function_.Get(); }
private:
JSContext* context_;
- mutable JS::Heap<JSObject*> function_;
+ WeakHeapObject weak_function_;
};
]]
diff --git a/src/cobalt/script/mozjs/mozjs_engine.cc b/src/cobalt/script/mozjs/mozjs_engine.cc
index 5587773..23444fa 100644
--- a/src/cobalt/script/mozjs/mozjs_engine.cc
+++ b/src/cobalt/script/mozjs/mozjs_engine.cc
@@ -16,9 +16,10 @@
#include "cobalt/script/mozjs/mozjs_engine.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
-
#include "third_party/mozjs/js/src/jsapi.h"
namespace cobalt {
@@ -36,12 +37,22 @@
JS_NewRuntime(kGarbageCollectionThresholdBytes, JS_NO_HELPER_THREADS);
CHECK(runtime_);
+ JS_SetRuntimePrivate(runtime_, this);
+
// Use incremental garbage collection.
JS_SetGCParameter(runtime_, JSGC_MODE, JSGC_MODE_INCREMENTAL);
+
// Allow Spidermonkey to allocate as much memory as it needs. If this limit
// is set we could limit the memory used by JS and "gracefully" restart,
// for example.
JS_SetGCParameter(runtime_, JSGC_MAX_BYTES, 0xffffffff);
+
+ // Callback to be called whenever a JSContext is created or destroyed for this
+ // JSRuntime.
+ JS_SetContextCallback(runtime_, &MozjsEngine::ContextCallback);
+
+ // Callback to be called during garbage collection during the sweep phase.
+ JS_SetFinalizeCallback(runtime_, &MozjsEngine::FinalizeCallback);
}
MozjsEngine::~MozjsEngine() {
@@ -61,10 +72,42 @@
void MozjsEngine::ReportExtraMemoryCost(size_t bytes) { NOTIMPLEMENTED(); }
+JSBool MozjsEngine::ContextCallback(JSContext* context, unsigned context_op) {
+ JSRuntime* runtime = JS_GetRuntime(context);
+ MozjsEngine* engine =
+ static_cast<MozjsEngine*>(JS_GetRuntimePrivate(runtime));
+ DCHECK(engine->thread_checker_.CalledOnValidThread());
+ if (context_op == JSCONTEXT_NEW) {
+ engine->contexts_.push_back(context);
+ } else if (context_op == JSCONTEXT_DESTROY) {
+ ContextVector::iterator it =
+ std::find(engine->contexts_.begin(), engine->contexts_.end(), context);
+ if (it != engine->contexts_.end()) {
+ engine->contexts_.erase(it);
+ }
+ }
+ return true;
+}
+
+void MozjsEngine::FinalizeCallback(JSFreeOp* free_op, JSFinalizeStatus status,
+ JSBool is_compartment) {
+ MozjsEngine* engine =
+ static_cast<MozjsEngine*>(JS_GetRuntimePrivate(free_op->runtime()));
+ DCHECK(engine->thread_checker_.CalledOnValidThread());
+ if (status == JSFINALIZE_GROUP_START) {
+ for (int i = 0; i < engine->contexts_.size(); ++i) {
+ MozjsGlobalObjectProxy* global_environment =
+ MozjsGlobalObjectProxy::GetFromContext(engine->contexts_[i]);
+ global_environment->DoSweep();
+ }
+ }
+}
+
} // namespace mozjs
scoped_ptr<JavaScriptEngine> JavaScriptEngine::CreateEngine() {
return make_scoped_ptr<JavaScriptEngine>(new mozjs::MozjsEngine());
}
+
} // namespace script
} // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_engine.h b/src/cobalt/script/mozjs/mozjs_engine.h
index bfed33e..12a24fd 100644
--- a/src/cobalt/script/mozjs/mozjs_engine.h
+++ b/src/cobalt/script/mozjs/mozjs_engine.h
@@ -16,6 +16,8 @@
#ifndef COBALT_SCRIPT_MOZJS_MOZJS_ENGINE_H_
#define COBALT_SCRIPT_MOZJS_MOZJS_ENGINE_H_
+#include <vector>
+
#include "base/threading/thread_checker.h"
#include "cobalt/script/javascript_engine.h"
#include "third_party/mozjs/js/src/jsapi.h"
@@ -34,11 +36,19 @@
void ReportExtraMemoryCost(size_t bytes) OVERRIDE;
private:
+ static JSBool ContextCallback(JSContext* context, unsigned context_op);
+ static void FinalizeCallback(JSFreeOp* free_op, JSFinalizeStatus status,
+ JSBool is_compartment);
+
base::ThreadChecker thread_checker_;
// Top-level object that represents the Javascript engine. Typically there is
// one per process, but it's allowed to have multiple.
JSRuntime* runtime_;
+
+ // A list of all contexts created for this JSRuntime.
+ typedef std::vector<JSContext*> ContextVector;
+ ContextVector contexts_;
};
} // namespace mozjs
} // namespace script
diff --git a/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc b/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc
index 8622146..c56be2c 100644
--- a/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc
+++ b/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc
@@ -26,6 +26,7 @@
#include "cobalt/script/mozjs/mozjs_source_code.h"
#include "cobalt/script/mozjs/mozjs_wrapper_handle.h"
#include "cobalt/script/mozjs/proxy_handler.h"
+#include "cobalt/script/mozjs/referenced_object_map.h"
#include "cobalt/script/mozjs/util/exception_helpers.h"
#include "third_party/mozjs/js/src/jsfriendapi.h"
#include "third_party/mozjs/js/src/jsfun.h"
@@ -154,6 +155,7 @@
JS_SetErrorReporter(context_, &MozjsGlobalObjectProxy::ReportErrorHandler);
wrapper_factory_.reset(new WrapperFactory(context_));
+ referenced_objects_.reset(new ReferencedObjectMap(context_));
JS_AddExtraGCRootsTracer(runtime, TraceFunction, this);
}
@@ -268,6 +270,12 @@
return NULL;
}
+void MozjsGlobalObjectProxy::DoSweep() {
+ weak_object_manager_.SweepUnmarkedObjects();
+ // Remove NULL references after sweeping weak references.
+ referenced_objects_->RemoveNullReferences();
+}
+
MozjsGlobalObjectProxy* MozjsGlobalObjectProxy::GetFromContext(
JSContext* context) {
MozjsGlobalObjectProxy* global_proxy =
@@ -336,9 +344,16 @@
global_object_environment->cached_interface_data_.begin();
it != global_object_environment->cached_interface_data_.end(); ++it) {
InterfaceData* data = it->second;
- JS_CallHeapObjectTracer(trace, &data->prototype, "MozjsGlobalObjectProxy");
- JS_CallHeapObjectTracer(trace, &data->interface_object,
- "MozjsGlobalObjectProxy");
+ // Check whether prototype and interface object for this interface have been
+ // created yet or not before attempting to trace them.
+ if (data->prototype) {
+ JS_CallHeapObjectTracer(trace, &data->prototype,
+ "MozjsGlobalObjectProxy");
+ }
+ if (data->interface_object) {
+ JS_CallHeapObjectTracer(trace, &data->interface_object,
+ "MozjsGlobalObjectProxy");
+ }
}
}
diff --git a/src/cobalt/script/mozjs/mozjs_global_object_proxy.h b/src/cobalt/script/mozjs/mozjs_global_object_proxy.h
index 0355d37..fc0b760 100644
--- a/src/cobalt/script/mozjs/mozjs_global_object_proxy.h
+++ b/src/cobalt/script/mozjs/mozjs_global_object_proxy.h
@@ -27,6 +27,7 @@
#include "cobalt/script/global_object_proxy.h"
#include "cobalt/script/mozjs/interface_data.h"
#include "cobalt/script/mozjs/util/exception_helpers.h"
+#include "cobalt/script/mozjs/weak_heap_object_manager.h"
#include "cobalt/script/mozjs/wrapper_factory.h"
#include "third_party/mozjs/js/src/jsapi.h"
#include "third_party/mozjs/js/src/jsproxy.h"
@@ -35,6 +36,9 @@
namespace script {
namespace mozjs {
+class ReferencedObjectMap;
+class WeakHandle;
+
// Manages a handle to a JavaScript engine's global object. The lifetime of
// the global object is not necessarily tied to the lifetime of the proxy.
class MozjsGlobalObjectProxy : public GlobalObjectProxy,
@@ -86,6 +90,12 @@
WrapperFactory* wrapper_factory() { return wrapper_factory_.get(); }
+ ReferencedObjectMap* referenced_objects() {
+ return referenced_objects_.get();
+ }
+
+ WeakHeapObjectManager* weak_object_manager() { return &weak_object_manager_; }
+
// Used for CallWith=EnvironmentSettings
void SetEnvironmentSettings(EnvironmentSettings* environment_settings) {
DCHECK(!environment_settings_);
@@ -107,6 +117,11 @@
void CacheInterfaceData(intptr_t key, InterfaceData* interface_data);
InterfaceData* GetInterfaceData(intptr_t key);
+ // This will be called during garbage collection after GC objects have been
+ // marked, but before they have been finalized. This allows an opportunity to
+ // sweep away references to GC objects that will be deleted.
+ void DoSweep();
+
static MozjsGlobalObjectProxy* GetFromContext(JSContext* context);
protected:
@@ -132,6 +147,8 @@
base::ThreadChecker thread_checker_;
JSContext* context_;
+ WeakHeapObjectManager weak_object_manager_;
+ scoped_ptr<ReferencedObjectMap> referenced_objects_;
CachedInterfaceData cached_interface_data_;
STLValueDeleter<CachedInterfaceData> cached_interface_data_deleter_;
ContextDestructor context_destructor_;
diff --git a/src/cobalt/script/mozjs/mozjs_object_handle.h b/src/cobalt/script/mozjs/mozjs_object_handle.h
index 6e59df8..e6c7827 100644
--- a/src/cobalt/script/mozjs/mozjs_object_handle.h
+++ b/src/cobalt/script/mozjs/mozjs_object_handle.h
@@ -19,6 +19,7 @@
#include "base/optional.h"
#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
#include "cobalt/script/mozjs/type_traits.h"
+#include "cobalt/script/mozjs/weak_heap_object.h"
#include "cobalt/script/opaque_handle.h"
#include "third_party/mozjs/js/src/jsapi.h"
@@ -33,17 +34,14 @@
class MozjsObjectHandle : public OpaqueHandle {
public:
typedef OpaqueHandle BaseType;
- JSObject* handle() const { return handle_; }
+ JSObject* handle() const { return handle_.Get(); }
private:
- MozjsObjectHandle(JSContext*, JS::HandleObject object)
- : handle_(object) {}
+ MozjsObjectHandle(JSContext* context, JS::HandleObject object)
+ : handle_(context, object) {}
~MozjsObjectHandle() {}
- // Note that this class does not root this JS::Heap<> object. Rooting of this
- // object is done in MozjsUserObjectHolder when ownership of a reference to
- // this is registered.
- JS::Heap<JSObject*> handle_;
+ WeakHeapObject handle_;
friend class MozjsUserObjectHolder<MozjsObjectHandle>;
friend class base::optional<MozjsObjectHandle>;
diff --git a/src/cobalt/script/mozjs/mozjs_user_object_holder.h b/src/cobalt/script/mozjs/mozjs_user_object_holder.h
index de47435..e51a8bb 100644
--- a/src/cobalt/script/mozjs/mozjs_user_object_holder.h
+++ b/src/cobalt/script/mozjs/mozjs_user_object_holder.h
@@ -19,6 +19,8 @@
#include "base/hash_tables.h"
#include "base/memory/weak_ptr.h"
#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
+#include "cobalt/script/mozjs/referenced_object_map.h"
#include "cobalt/script/mozjs/wrapper_factory.h"
#include "cobalt/script/mozjs/wrapper_private.h"
#include "cobalt/script/script_object.h"
@@ -50,22 +52,26 @@
void RegisterOwner(Wrappable* owner) OVERRIDE {
JS::RootedObject owned_object(context_, js_object());
- WrapperPrivate* wrapper_private =
- WrapperPrivate::GetFromWrappable(owner, context_, wrapper_factory_);
- wrappable_and_private_hash_map_.insert(
- std::make_pair(owner, wrapper_private->AsWeakPtr()));
- wrapper_private->AddReferencedObject(owned_object);
+ DLOG_IF(WARNING, !owned_object)
+ << "Owned object has been garbage collected.";
+ if (owned_object) {
+ MozjsGlobalObjectProxy* global_environment =
+ MozjsGlobalObjectProxy::GetFromContext(context_);
+ intptr_t key = ReferencedObjectMap::GetKeyForWrappable(owner);
+ global_environment->referenced_objects()->AddReferencedObject(
+ key, owned_object);
+ }
}
void DeregisterOwner(Wrappable* owner) OVERRIDE {
+ // |owner| may be in the process of being destructed, so don't use it.
JS::RootedObject owned_object(context_, js_object());
- WrappableAndPrivateHashMap::iterator it =
- wrappable_and_private_hash_map_.find(owner);
- if (it != wrappable_and_private_hash_map_.end() && it->second) {
- JS::RootedObject object_proxy(context_, it->second->js_object_proxy());
- if (object_proxy) {
- it->second->RemoveReferencedObject(owned_object);
- }
+ if (owned_object) {
+ MozjsGlobalObjectProxy* global_environment =
+ MozjsGlobalObjectProxy::GetFromContext(context_);
+ intptr_t key = ReferencedObjectMap::GetKeyForWrappable(owner);
+ global_environment->referenced_objects()->RemoveReferencedObject(
+ key, owned_object);
}
}
@@ -104,7 +110,6 @@
JSContext* context_;
base::optional<MozjsUserObjectType> object_handle_;
WrapperFactory* wrapper_factory_;
- WrappableAndPrivateHashMap wrappable_and_private_hash_map_;
};
} // namespace mozjs
diff --git a/src/cobalt/script/mozjs/referenced_object_map.cc b/src/cobalt/script/mozjs/referenced_object_map.cc
new file mode 100644
index 0000000..d356f62
--- /dev/null
+++ b/src/cobalt/script/mozjs/referenced_object_map.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/script/mozjs/referenced_object_map.h"
+
+#include <utility>
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+ReferencedObjectMap::ReferencedObjectMap(JSContext* context)
+ : context_(context) {}
+
+// Add/Remove a reference from a WrapperPrivate to a JSValue.
+void ReferencedObjectMap::AddReferencedObject(intptr_t key,
+ JS::HandleObject referee) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(referee);
+ referenced_objects_.insert(
+ std::make_pair(key, WeakHeapObject(context_, referee)));
+}
+
+void ReferencedObjectMap::RemoveReferencedObject(intptr_t key,
+ JS::HandleObject referee) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ std::pair<ReferencedObjectMultiMap::iterator,
+ ReferencedObjectMultiMap::iterator> pair_range =
+ referenced_objects_.equal_range(key);
+ for (ReferencedObjectMultiMap::iterator it = pair_range.first;
+ it != pair_range.second; ++it) {
+ if (it->second.Get() == referee) {
+ // There may be multiple mappings between a specific owner and a JS
+ // object. Only remove the first mapping.
+ referenced_objects_.erase(it);
+ return;
+ }
+ }
+ DLOG(WARNING) << "No reference to the specified object found.";
+}
+
+void ReferencedObjectMap::TraceReferencedObjects(JSTracer* trace,
+ intptr_t key) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ std::pair<ReferencedObjectMultiMap::iterator,
+ ReferencedObjectMultiMap::iterator> pair_range =
+ referenced_objects_.equal_range(key);
+ for (ReferencedObjectMultiMap::iterator it = pair_range.first;
+ it != pair_range.second; ++it) {
+ it->second.Trace(trace);
+ }
+}
+
+void ReferencedObjectMap::RemoveNullReferences() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ for (ReferencedObjectMultiMap::iterator it = referenced_objects_.begin();
+ it != referenced_objects_.end();
+ /*Incremented in the loop */) {
+ if (it->second.Get()) {
+ ++it;
+ } else {
+ ReferencedObjectMultiMap::iterator erase_iterator = it++;
+ referenced_objects_.erase(erase_iterator);
+ }
+ }
+}
+
+} // namespace mozjs
+} // namespace script
+} // namespace cobalt
diff --git a/src/cobalt/script/mozjs/referenced_object_map.h b/src/cobalt/script/mozjs/referenced_object_map.h
new file mode 100644
index 0000000..c1d4924
--- /dev/null
+++ b/src/cobalt/script/mozjs/referenced_object_map.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef COBALT_SCRIPT_MOZJS_REFERENCED_OBJECT_MAP_H_
+#define COBALT_SCRIPT_MOZJS_REFERENCED_OBJECT_MAP_H_
+
+#include "base/hash_tables.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/script/mozjs/weak_heap_object.h"
+#include "cobalt/script/wrappable.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+// Maintains a set of JSObjects that are reachable from a given object. This
+// relationship is registered by mapping a key to a JSObject. The calling code
+// should ensure that a key uniquely identifies the entity that holds a
+// reference to the JSObjects.
+// During garbage collection, supply a key to TraceReferencedObjects to trace
+// all objects that are registered as being reachable from the object
+// represented by that key.
+class ReferencedObjectMap {
+ public:
+ explicit ReferencedObjectMap(JSContext* context);
+
+ // Reinterpret the pointer as an integer to be used as a key for tracking
+ // referenced objects.
+ static intptr_t GetKeyForWrappable(const Wrappable* wrappable) {
+ return reinterpret_cast<intptr_t>(wrappable);
+ }
+
+ void AddReferencedObject(intptr_t key, JS::HandleObject referee);
+ void RemoveReferencedObject(intptr_t key, JS::HandleObject referee);
+
+ // Trace all objects referenced from this WrapperPrivate*.
+ void TraceReferencedObjects(JSTracer* trace, intptr_t key);
+
+ // Remove any referenced objects that are NULL. It may be the case that a
+ // weak reference to an object was garbage collected, so remove it from the
+ // internal list.
+ void RemoveNullReferences();
+
+ private:
+ typedef base::hash_multimap<intptr_t, WeakHeapObject>
+ ReferencedObjectMultiMap;
+
+ base::ThreadChecker thread_checker_;
+ JSContext* context_;
+ ReferencedObjectMultiMap referenced_objects_;
+};
+
+} // namespace mozjs
+} // namespace script
+} // namespace cobalt
+
+#endif // COBALT_SCRIPT_MOZJS_REFERENCED_OBJECT_MAP_H_
diff --git a/src/cobalt/script/mozjs/util/exception_helpers.cc b/src/cobalt/script/mozjs/util/exception_helpers.cc
index 9ef7f2c..1c4b8ad 100644
--- a/src/cobalt/script/mozjs/util/exception_helpers.cc
+++ b/src/cobalt/script/mozjs/util/exception_helpers.cc
@@ -41,7 +41,7 @@
for (int i = 0; i < max_frames; ++i) {
StackFrame sf;
sf.line_number = stack_trace[i].lineno;
- sf.column_number = 0;
+ sf.column_number = stack_trace[i].columnno;
sf.function_name = "global code";
if (stack_trace[i].fun) {
JS::RootedString rooted_string(context,
diff --git a/src/cobalt/script/mozjs/weak_heap_object.cc b/src/cobalt/script/mozjs/weak_heap_object.cc
new file mode 100644
index 0000000..6b719bb
--- /dev/null
+++ b/src/cobalt/script/mozjs/weak_heap_object.cc
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/script/mozjs/weak_heap_object.h"
+
+#include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+WeakHeapObject::WeakHeapObject(JSContext* context, JS::HandleObject handle) {
+ MozjsGlobalObjectProxy* global_environment =
+ MozjsGlobalObjectProxy::GetFromContext(context);
+ Initialize(global_environment->weak_object_manager(), handle);
+}
+
+WeakHeapObject::WeakHeapObject(const WeakHeapObject& other) {
+ Initialize(other.weak_object_manager_, other.heap_);
+}
+
+WeakHeapObject& WeakHeapObject::operator=(const WeakHeapObject& rhs) {
+ Initialize(rhs.weak_object_manager_, rhs.heap_);
+ return *this;
+}
+
+void WeakHeapObject::Trace(JSTracer* trace) {
+ if (heap_) {
+ JS_CallHeapObjectTracer(trace, &heap_, "WeakHeapObject::Trace");
+ }
+}
+
+WeakHeapObject::~WeakHeapObject() {
+ // It's safe to call StopTracking even if StartTracking wasn't called. the
+ // WeakObjectManager handles the case where it's not currently tracking the
+ // WeakHeapObject.
+ weak_object_manager_->StopTracking(this);
+}
+
+void WeakHeapObject::Initialize(WeakHeapObjectManager* weak_heap_object_manager,
+ JSObject* object) {
+ weak_object_manager_ = weak_heap_object_manager;
+ heap_ = object;
+ // Don't bother registering if the pointer is already NULL.
+ if (heap_) {
+ weak_object_manager_->StartTracking(this);
+ }
+}
+
+} // namespace mozjs
+} // namespace script
+} // namespace cobalt
diff --git a/src/cobalt/script/mozjs/weak_heap_object.h b/src/cobalt/script/mozjs/weak_heap_object.h
new file mode 100644
index 0000000..4a9a5b6
--- /dev/null
+++ b/src/cobalt/script/mozjs/weak_heap_object.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef COBALT_SCRIPT_MOZJS_WEAK_HEAP_OBJECT_H_
+#define COBALT_SCRIPT_MOZJS_WEAK_HEAP_OBJECT_H_
+
+#include "cobalt/script/mozjs/weak_heap_object_manager.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+// This class implements a weak reference to a JSObject. The JSObject that an
+// instance of this class is created with may get garbage collected. In that
+// case, subsequent calls to WeakHeapObject::Get() will return a NULL pointer.
+class WeakHeapObject {
+ public:
+ WeakHeapObject(JSContext* context, JS::HandleObject handle);
+ WeakHeapObject(const WeakHeapObject& other);
+
+ WeakHeapObject& operator=(const WeakHeapObject& rhs);
+ JSObject* Get() const { return heap_; }
+ void Trace(JSTracer* trace);
+
+ ~WeakHeapObject();
+
+ private:
+ void Initialize(WeakHeapObjectManager* weak_heap_object_manager,
+ JSObject* object);
+
+ WeakHeapObjectManager* weak_object_manager_;
+ JS::Heap<JSObject*> heap_;
+
+ friend class WeakHeapObjectManager;
+};
+
+} // namespace mozjs
+} // namespace script
+} // namespace cobalt
+
+#endif // COBALT_SCRIPT_MOZJS_WEAK_HEAP_OBJECT_H_
diff --git a/src/cobalt/script/mozjs/weak_heap_object_manager.cc b/src/cobalt/script/mozjs/weak_heap_object_manager.cc
new file mode 100644
index 0000000..8f72068
--- /dev/null
+++ b/src/cobalt/script/mozjs/weak_heap_object_manager.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/script/mozjs/weak_heap_object_manager.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "cobalt/script/mozjs/weak_heap_object.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+void WeakHeapObjectManager::SweepUnmarkedObjects() {
+ for (WeakHeapObjects::iterator it = weak_objects_.begin();
+ it != weak_objects_.end();
+ /* Incremented in the loop */) {
+ if (MaybeSweep(*it)) {
+ WeakHeapObjects::iterator erase_iterator = it++;
+ weak_objects_.erase(erase_iterator);
+ } else {
+ ++it;
+ }
+ }
+}
+
+WeakHeapObjectManager::~WeakHeapObjectManager() {
+ // If this is not empty, that means that some WeakHeapObject may outlive this
+ // class.
+ DCHECK(weak_objects_.empty());
+}
+
+void WeakHeapObjectManager::StartTracking(WeakHeapObject* weak_object) {
+ std::pair<WeakHeapObjects::iterator, bool> pib =
+ weak_objects_.insert(weak_object);
+ DCHECK(pib.second) << "WeakHeapObject was already being tracked.";
+}
+
+void WeakHeapObjectManager::StopTracking(WeakHeapObject* weak_object) {
+ // The WeakHeapObject may have already been removed from the weak_objects_
+ // set during the sweep phase.
+ WeakHeapObjects::iterator it = weak_objects_.find(weak_object);
+ if (it != weak_objects_.end()) {
+ weak_objects_.erase(it);
+ }
+}
+
+bool WeakHeapObjectManager::MaybeSweep(WeakHeapObject* weak_object) {
+ if (weak_object->heap_ &&
+ JS_IsAboutToBeFinalized(weak_object->heap_.unsafeGet())) {
+ weak_object->heap_.set(NULL);
+ }
+ return weak_object->heap_ == NULL;
+}
+
+} // namespace mozjs
+} // namespace script
+} // namespace cobalt
diff --git a/src/cobalt/script/mozjs/weak_heap_object_manager.h b/src/cobalt/script/mozjs/weak_heap_object_manager.h
new file mode 100644
index 0000000..64e158b
--- /dev/null
+++ b/src/cobalt/script/mozjs/weak_heap_object_manager.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef COBALT_SCRIPT_MOZJS_WEAK_HEAP_OBJECT_MANAGER_H_
+#define COBALT_SCRIPT_MOZJS_WEAK_HEAP_OBJECT_MANAGER_H_
+
+#include "base/hash_tables.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+class WeakHeapObject;
+
+// WeakHeapObjectManager holds a reference to all WeakHeapObject instances. The
+// SweepUnmarkedObjects function should be called during garbage collection
+// after the marking phase. The underlying JS::Heap<> handle for any unmarked
+// handles will be set to NULL.
+class WeakHeapObjectManager {
+ public:
+ // Iterates over all WeakHeapObjects and sets their JS::Heap<> handles to NULL
+ // if the objects to which they hold a reference are about to be finalized.
+ void SweepUnmarkedObjects();
+ ~WeakHeapObjectManager();
+
+ private:
+ void StartTracking(WeakHeapObject* weak_object);
+ void StopTracking(WeakHeapObject* weak_object);
+
+ // Returns true if the underlying pointer is NULL, which will be the case if
+ // the object has been swept.
+ bool MaybeSweep(WeakHeapObject* weak_object);
+
+ typedef base::hash_set<WeakHeapObject*> WeakHeapObjects;
+ WeakHeapObjects weak_objects_;
+
+ friend class WeakHeapObject;
+};
+
+} // namespace mozjs
+} // namespace script
+} // namespace cobalt
+
+#endif // COBALT_SCRIPT_MOZJS_WEAK_HEAP_OBJECT_MANAGER_H_
diff --git a/src/cobalt/script/mozjs/wrapper_private.cc b/src/cobalt/script/mozjs/wrapper_private.cc
index e129678..9328993 100644
--- a/src/cobalt/script/mozjs/wrapper_private.cc
+++ b/src/cobalt/script/mozjs/wrapper_private.cc
@@ -16,6 +16,8 @@
#include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
+#include "cobalt/script/mozjs/referenced_object_map.h"
#include "third_party/mozjs/js/src/jsapi.h"
#include "third_party/mozjs/js/src/jsproxy.h"
@@ -23,27 +25,13 @@
namespace script {
namespace mozjs {
-void WrapperPrivate::AddReferencedObject(JS::HandleObject referee) {
- referenced_objects_.push_back(new JS::Heap<JSObject*>(referee));
-}
-
-void WrapperPrivate::RemoveReferencedObject(JS::HandleObject referee) {
- for (ReferencedObjectVector::iterator it = referenced_objects_.begin();
- it != referenced_objects_.end(); ++it) {
- if ((**it) == referee) {
- referenced_objects_.erase(it);
- return;
- }
- }
- NOTREACHED();
-}
-
// static
void WrapperPrivate::AddPrivateData(JSContext* context,
JS::HandleObject wrapper_proxy,
const scoped_refptr<Wrappable>& wrappable) {
DCHECK(js::IsProxy(wrapper_proxy));
- WrapperPrivate* private_data = new WrapperPrivate(wrappable, wrapper_proxy);
+ WrapperPrivate* private_data =
+ new WrapperPrivate(context, wrappable, wrapper_proxy);
JS::RootedObject target_object(context,
js::GetProxyTargetObject(wrapper_proxy));
JS_SetPrivate(target_object, private_data);
@@ -101,18 +89,36 @@
void WrapperPrivate::Trace(JSTracer* trace, JSObject* object) {
WrapperPrivate* wrapper_private =
reinterpret_cast<WrapperPrivate*>(JS_GetPrivate(object));
- DCHECK(wrapper_private);
- for (ReferencedObjectVector::iterator it =
- wrapper_private->referenced_objects_.begin();
- it != wrapper_private->referenced_objects_.end(); ++it) {
- JS::Heap<JSObject*>* referenced_object = *it;
- JS_CallHeapObjectTracer(trace, referenced_object, "WrapperPrivate::Trace");
+ // Verify that this trace function is called for the object (rather than the
+ // proxy object).
+ DCHECK(!js::IsProxy(object));
+
+ // The GC could run on this object before we've had a chance to set its
+ // private data, so we must handle the case where JS_GetPrivate returns NULL.
+ if (wrapper_private) {
+ // Verify that WrapperPrivate::wrapper_proxy_'s target object is this
+ // object.
+ DCHECK_EQ(object,
+ js::GetProxyTargetObject(wrapper_private->wrapper_proxy_));
+
+ // The wrapper's proxy object will keep the wrapper object alive, but the
+ // reverse is not true, so we must trace it explicitly.
+ JS_CallHeapObjectTracer(trace, &wrapper_private->wrapper_proxy_,
+ "WrapperPrivate::Trace");
+
+ MozjsGlobalObjectProxy* global_environment =
+ MozjsGlobalObjectProxy::GetFromContext(wrapper_private->context_);
+ intptr_t key = ReferencedObjectMap::GetKeyForWrappable(
+ wrapper_private->wrappable_.get());
+ global_environment->referenced_objects()->TraceReferencedObjects(trace,
+ key);
}
}
-WrapperPrivate::WrapperPrivate(const scoped_refptr<Wrappable>& wrappable,
+WrapperPrivate::WrapperPrivate(JSContext* context,
+ const scoped_refptr<Wrappable>& wrappable,
JS::HandleObject wrapper_proxy)
- : wrappable_(wrappable), wrapper_proxy_(wrapper_proxy) {
+ : context_(context), wrappable_(wrappable), wrapper_proxy_(wrapper_proxy) {
DCHECK(js::IsProxy(wrapper_proxy));
}
diff --git a/src/cobalt/script/mozjs/wrapper_private.h b/src/cobalt/script/mozjs/wrapper_private.h
index e80ec75..aecb44d 100644
--- a/src/cobalt/script/mozjs/wrapper_private.h
+++ b/src/cobalt/script/mozjs/wrapper_private.h
@@ -75,14 +75,13 @@
static void Trace(JSTracer* trace, JSObject* object);
private:
- typedef ScopedVector<JS::Heap<JSObject*> > ReferencedObjectVector;
- WrapperPrivate(const scoped_refptr<Wrappable>& wrappable,
+ WrapperPrivate(JSContext* context, const scoped_refptr<Wrappable>& wrappable,
JS::HandleObject wrapper_proxy);
~WrapperPrivate();
+ JSContext* context_;
scoped_refptr<Wrappable> wrappable_;
JS::Heap<JSObject*> wrapper_proxy_;
- ReferencedObjectVector referenced_objects_;
};
} // namespace mozjs
diff --git a/src/cobalt/script/stack_frame.cc b/src/cobalt/script/stack_frame.cc
index 09de508..6e6e15d 100644
--- a/src/cobalt/script/stack_frame.cc
+++ b/src/cobalt/script/stack_frame.cc
@@ -31,6 +31,7 @@
if (!stack_frames[i].source_url.empty()) {
backtrace_stream << " @ " << stack_frames[i].source_url << ':'
<< stack_frames[i].line_number;
+ backtrace_stream << ":" << stack_frames[i].column_number;
}
}
return backtrace_stream.str();
diff --git a/src/cobalt/storage/storage_manager.cc b/src/cobalt/storage/storage_manager.cc
index 3f91fda..d7d2e9c 100644
--- a/src/cobalt/storage/storage_manager.cc
+++ b/src/cobalt/storage/storage_manager.cc
@@ -108,6 +108,30 @@
DCHECK(ok);
}
+const std::string& GetFirstValidDatabaseFile(
+ const std::vector<std::string>& filenames) {
+ // Caller must ensure at least one file exists.
+ DCHECK_GT(filenames.size(), size_t(0));
+
+ for (size_t i = 0; i < filenames.size(); ++i) {
+ sql::Connection connection;
+ bool is_opened = connection.Open(FilePath(filenames[i]));
+ if (!is_opened) {
+ continue;
+ }
+ int err = connection.ExecuteAndReturnErrorCode("pragma schema_version;");
+ if (err != SQLITE_OK) {
+ continue;
+ }
+ // File can be opened as a database.
+ return filenames[i];
+ }
+
+ // Caller must handle case where a valid database file cannot be found.
+ DLOG(WARNING) << "Cannot find valid database file in save data";
+ return filenames[0];
+}
+
} // namespace
StorageManager::StorageManager(const Options& options)
@@ -253,11 +277,9 @@
filenames.push_back(kDefaultSaveFile);
}
- // Not a limitation of the VFS- we just need to figure out how to handle
- // the case where there are multiple files in here.
- DCHECK_EQ(1, filenames.size());
-
- const std::string& save_name = filenames[0];
+ // Legacy Steel save data may contain multiple files (e.g. db-journal as well
+ // as db), so use the first one that looks like a valid database file.
+ const std::string& save_name = GetFirstValidDatabaseFile(filenames);
bool ok = connection_->Open(FilePath(save_name));
DCHECK(ok);
diff --git a/src/glimp/glimp_settings.gypi b/src/glimp/glimp_settings.gypi
index af9bf97..7ea4b74 100644
--- a/src/glimp/glimp_settings.gypi
+++ b/src/glimp/glimp_settings.gypi
@@ -26,5 +26,7 @@
# http://stackoverflow.com/questions/29601786/c-preprocessor-building-a-path-string
'GLIMP_EGLPLATFORM_INCLUDE="../../<(target_arch)/eglplatform_public.h"',
'GLIMP_KHRPLATFORM_INCLUDE="../../<(target_arch)/khrplatform_public.h"',
+ # Uncomment the define below to enable and use tracing inside glimp.
+ # 'ENABLE_GLIMP_TRACING',
],
}
diff --git a/src/glimp/tracing/tracing.cc b/src/glimp/tracing/tracing.cc
index 5f6dfae..ddf3031 100644
--- a/src/glimp/tracing/tracing.cc
+++ b/src/glimp/tracing/tracing.cc
@@ -14,9 +14,11 @@
* limitations under the License.
*/
+#include <cstddef>
+
#include "glimp/tracing/tracing.h"
-#if GLIMP_TRACING_ENABLED
+#if defined(ENABLE_GLIMP_TRACING)
namespace glimp {
@@ -42,4 +44,4 @@
} // namespace glimp
-#endif // #if GLIMP_TRACING_ENABLED
+#endif // #if defined(ENABLE_GLIMP_TRACING)
diff --git a/src/glimp/tracing/tracing.gyp b/src/glimp/tracing/tracing.gyp
index 785a711..f2635bd 100644
--- a/src/glimp/tracing/tracing.gyp
+++ b/src/glimp/tracing/tracing.gyp
@@ -13,7 +13,7 @@
# limitations under the License.
{
- # When GLIMP_TRACING_ENABLED is defined to 1 in tracing.h, the many
+ # When ENABLE_GLIMP_TRACING is defined in glimp_settings.gypi, the many
# implementation functions that are annotated with GLIMP_TRACE_EVENT0 calls
# will activate and allow profiling and flow visualization within glimp.
#
@@ -34,6 +34,9 @@
'tracing.h',
'tracing.cc',
],
+ 'includes': [
+ '../glimp_settings.gypi',
+ ],
},
],
}
diff --git a/src/glimp/tracing/tracing.h b/src/glimp/tracing/tracing.h
index 5e3ce08..8471f40 100644
--- a/src/glimp/tracing/tracing.h
+++ b/src/glimp/tracing/tracing.h
@@ -17,15 +17,11 @@
#ifndef GLIMP_TRACING_TRACING_H_
#define GLIMP_TRACING_TRACING_H_
-#if !defined(GLIMP_TRACING_ENABLED)
-#define GLIMP_TRACING_ENABLED 0
-#endif
-
-#if !GLIMP_TRACING_ENABLED
+#if !defined(ENABLE_GLIMP_TRACING)
#define GLIMP_TRACE_EVENT0(event)
-#else // #if GLIMP_TRACING_ENABLED
+#else // !defined(ENABLE_GLIMP_TRACING)
#define GLIMP_TRACE_EVENT0(event) \
glimp::ScopedTraceEvent profileScope##__LINE__(event)
@@ -56,6 +52,6 @@
} // namespace glimp
-#endif // #if GLIMP_TRACING_ENABLED
+#endif // !defined(ENABLE_GLIMP_TRACING)
#endif // GLIMP_TRACING_TRACING_H_
diff --git a/src/media/base/pipeline_impl.cc b/src/media/base/pipeline_impl.cc
index 3b3918e..6857cf6 100644
--- a/src/media/base/pipeline_impl.cc
+++ b/src/media/base/pipeline_impl.cc
@@ -407,7 +407,6 @@
}
void PipelineImpl::SetDuration(TimeDelta duration) {
- DCHECK(IsRunning());
media_log_->AddEvent(
media_log_->CreateTimeEvent(
MediaLogEvent::DURATION_SET, "duration", duration));
diff --git a/src/media/base/shell_audio_bus.cc b/src/media/base/shell_audio_bus.cc
index db3da54..86f4129 100644
--- a/src/media/base/shell_audio_bus.cc
+++ b/src/media/base/shell_audio_bus.cc
@@ -50,10 +50,8 @@
} // namespace
-ShellAudioBus::ShellAudioBus(size_t channels,
- size_t frames,
- SampleType sample_type,
- StorageType storage_type)
+ShellAudioBus::ShellAudioBus(size_t channels, size_t frames,
+ SampleType sample_type, StorageType storage_type)
: channels_(channels),
frames_(frames),
sample_type_(sample_type),
@@ -220,6 +218,44 @@
}
}
+template <ShellAudioBus::StorageType T>
+inline uint8* ShellAudioBus::GetSamplePtrForType(size_t channel,
+ size_t frame) const {
+ DCHECK_LT(channel, channels_);
+ DCHECK_LT(frame, frames_);
+
+ if (T == kInterleaved) {
+ return channel_data_[0] + sizeof(float) * (channels_ * frame + channel);
+ } else if (T == kPlanar) {
+ return channel_data_[channel] + sizeof(float) * frame;
+ } else {
+ NOTREACHED();
+ }
+
+ return NULL;
+}
+
+template <ShellAudioBus::StorageType T>
+inline float ShellAudioBus::GetFloat32SampleForType(size_t channel,
+ size_t frame) const {
+ return *reinterpret_cast<const float*>(
+ GetSamplePtrForType<T>(channel, frame));
+}
+
+template <ShellAudioBus::StorageType SourceStorageType,
+ ShellAudioBus::StorageType DestStorageType>
+void ShellAudioBus::MixForType(const ShellAudioBus& source) {
+ const size_t frames = std::min(frames_, source.frames_);
+
+ for (size_t channel = 0; channel < channels_; ++channel) {
+ for (size_t frame = 0; frame < frames; ++frame) {
+ *reinterpret_cast<float*>(
+ GetSamplePtrForType<DestStorageType>(channel, frame)) +=
+ source.GetFloat32SampleForType<SourceStorageType>(channel, frame);
+ }
+ }
+}
+
void ShellAudioBus::Mix(const ShellAudioBus& source) {
DCHECK_EQ(channels_, source.channels_);
DCHECK_EQ(sample_type_, kFloat32);
@@ -230,12 +266,20 @@
return;
}
- size_t frames = std::min(frames_, source.frames_);
- for (size_t channel = 0; channel < channels_; ++channel) {
- for (size_t frame = 0; frame < frames; ++frame) {
- *reinterpret_cast<float*>(GetSamplePtr(channel, frame)) +=
- source.GetFloat32Sample(channel, frame);
- }
+ // Profiling has identified this area of code as hot, so instead of calling
+ // GetSamplePtr, which branches on storage_type_ each time it is called, we
+ // branch once before we loop and inline the branch of the function we want.
+ DCHECK_EQ(GetSampleSizeInBytes(), sizeof(float));
+ if (source.storage_type_ == kInterleaved && storage_type_ == kInterleaved) {
+ MixForType<kInterleaved, kInterleaved>(source);
+ } else if (source.storage_type_ == kInterleaved && storage_type_ == kPlanar) {
+ MixForType<kInterleaved, kPlanar>(source);
+ } else if (source.storage_type_ == kPlanar && storage_type_ == kInterleaved) {
+ MixForType<kPlanar, kInterleaved>(source);
+ } else if (source.storage_type_ == kPlanar && storage_type_ == kPlanar) {
+ MixForType<kPlanar, kPlanar>(source);
+ } else {
+ NOTREACHED();
}
}
diff --git a/src/media/base/shell_audio_bus.h b/src/media/base/shell_audio_bus.h
index 195ce7c..6c43f8c 100644
--- a/src/media/base/shell_audio_bus.h
+++ b/src/media/base/shell_audio_bus.h
@@ -50,9 +50,7 @@
enum StorageType { kInterleaved, kPlanar };
- ShellAudioBus(size_t channels,
- size_t frames,
- SampleType sample_type,
+ ShellAudioBus(size_t channels, size_t frames, SampleType sample_type,
StorageType storage_type);
ShellAudioBus(size_t frames, const std::vector<float*>& samples);
ShellAudioBus(size_t channels, size_t frames, float* samples);
@@ -111,6 +109,20 @@
uint8* GetSamplePtr(size_t channel, size_t frame);
const uint8* GetSamplePtr(size_t channel, size_t frame) const;
+ // The *ForType functions below are optimized versions that assume what
+ // storage type the bus is using. They are meant to be called after checking
+ // what storage type the bus is once, and then performing a batch of
+ // operations, where it is known that the type will not change.
+ // Note: The bus must have storage type of kFloat32.
+ template <StorageType T>
+ inline uint8* GetSamplePtrForType(size_t channel, size_t frame) const;
+
+ template <StorageType T>
+ inline float GetFloat32SampleForType(size_t channel, size_t frame) const;
+
+ template <StorageType SourceStorageType, StorageType DestStorageType>
+ void MixForType(const ShellAudioBus& source);
+
// Contiguous block of channel memory if the memory is owned by this object.
scoped_ptr_malloc<uint8, base::ScopedPtrAlignedFree> data_;
diff --git a/src/media/filters/video_renderer_base.cc b/src/media/filters/video_renderer_base.cc
index 80d1f3d..de91f9f 100644
--- a/src/media/filters/video_renderer_base.cc
+++ b/src/media/filters/video_renderer_base.cc
@@ -65,6 +65,19 @@
#endif // defined(__LB_SHELL__) || defined(COBALT)
}
+VideoRendererBase::~VideoRendererBase() {
+ base::AutoLock auto_lock(lock_);
+ DCHECK(state_ == kStopped || state_ == kUninitialized) << state_;
+ DCHECK_EQ(thread_, base::kNullThreadHandle);
+#if !defined(__LB_SHELL__FOR_RELEASE__)
+ ++videos_played_;
+ DLOG_IF(INFO, late_frames_ != 0) << "Finished playing back with "
+ << late_frames_ << " late frames.";
+ DLOG_IF(INFO, late_frames_ == 0)
+ << "Finished playing back with no late frame.";
+#endif // !defined(__LB_SHELL__FOR_RELEASE__)
+}
+
void VideoRendererBase::Play(const base::Closure& callback) {
#if defined(__LB_SHELL__) || defined(COBALT)
TRACE_EVENT0("media_stack", "VideoRendererBase::Play()");
@@ -154,7 +167,12 @@
return;
}
- decoder_->Stop(callback);
+ if (decoder_) {
+ decoder_->Stop(callback);
+ return;
+ }
+
+ callback.Run();
}
void VideoRendererBase::StopDecoder(const base::Closure& callback) {
@@ -223,6 +241,7 @@
error_cb_ = error_cb;
get_time_cb_ = get_time_cb;
get_duration_cb_ = get_duration_cb;
+ state_ = kInitializing;
scoped_ptr<VideoDecoderSelector> decoder_selector(
new VideoDecoderSelector(base::MessageLoopProxy::current(),
@@ -250,6 +269,8 @@
if (state_ == kStopped)
return;
+ DCHECK_EQ(state_, kInitializing);
+
if (!selected_decoder) {
state_ = kUninitialized;
base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
@@ -308,9 +329,11 @@
}
#endif // defined(__LB_SHELL__) || defined(COBALT)
if (frames_dropped > 0) {
- PipelineStatistics statistics;
- statistics.video_frames_dropped = frames_dropped;
- statistics_cb_.Run(statistics);
+ if (!statistics_cb_.is_null()) {
+ PipelineStatistics statistics;
+ statistics.video_frames_dropped = frames_dropped;
+ statistics_cb_.Run(statistics);
+ }
frames_dropped = 0;
}
@@ -545,18 +568,6 @@
}
}
-VideoRendererBase::~VideoRendererBase() {
- base::AutoLock auto_lock(lock_);
- DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
-#if !defined(__LB_SHELL__FOR_RELEASE__)
- ++videos_played_;
- DLOG_IF(INFO, late_frames_ != 0)
- << "Finished playing back with " << late_frames_ << " late frames.";
- DLOG_IF(INFO, late_frames_ == 0)
- << "Finished playing back with no late frame.";
-#endif // !defined(__LB_SHELL__FOR_RELEASE__)
-}
-
void VideoRendererBase::FrameReady(
VideoDecoder::Status status,
const scoped_refptr<VideoFrame>& incoming_frame) {
@@ -771,6 +782,7 @@
return;
case kUninitialized:
+ case kInitializing:
case kPrerolled:
case kFlushingDecoder:
case kFlushed:
@@ -827,22 +839,10 @@
void VideoRendererBase::OnDecoderResetDone() {
base::AutoLock auto_lock(lock_);
- // The state_ can be kStopped if video playback is stopped when a seek is in
- // progress. The easist way to reproduce this is to repost to
- // OnDecoderResetDone() here until state_ is kStopped and manually quit
- // playing a video when the first seek is in progress.
- // To keep running the function when state_ is kStopped is safe, because the
- // flush_cb_ will be handled by SerialRunner::RunNextInSeries() which is
- // posted on a weak pointer. The SerialRunner should already be destroyed in
- // Pipeline::DoStop() when pending_callbacks_ is overwritten.
- // Note that this part has been properly handled in the upstream as the video
- // renderer is owned by Pipeline and all related tasks are posted with a weak
- // pointer of the video renderer. When the Pipeline is stopped, it will
- // destroy the video renderer and this callback will not be called. So don't
- // apply this change during rebase.
- if (state_ != kStopped) {
- DCHECK_EQ(kFlushingDecoder, state_);
- }
+ if (state_ == kStopped)
+ return;
+
+ DCHECK_EQ(kFlushingDecoder, state_);
DCHECK(!pending_read_);
state_ = kFlushing;
diff --git a/src/media/filters/video_renderer_base.h b/src/media/filters/video_renderer_base.h
index af1fec4..f842f18 100644
--- a/src/media/filters/video_renderer_base.h
+++ b/src/media/filters/video_renderer_base.h
@@ -199,6 +199,8 @@
// [kUninitialized] -------> [kError]
// |
// | Initialize()
+ // [kInitializing]
+ // |
// V All frames returned
// +------[kFlushed]<-----[kFlushing]<--- OnDecoderResetDone()
// | | Preroll() or upon ^
@@ -221,6 +223,7 @@
// Simple state tracking variable.
enum State {
kUninitialized,
+ kInitializing,
kPrerolled,
kPaused,
kFlushingDecoder,
diff --git a/src/media/filters/video_renderer_base_unittest.cc b/src/media/filters/video_renderer_base_unittest.cc
index 5a47838..f252a2e 100644
--- a/src/media/filters/video_renderer_base_unittest.cc
+++ b/src/media/filters/video_renderer_base_unittest.cc
@@ -5,6 +5,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "base/debug/stack_trace.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "base/stringprintf.h"
@@ -118,26 +119,26 @@
void InitializeRenderer(PipelineStatus expected) {
SCOPED_TRACE(base::StringPrintf("InitializeRenderer(%d)", expected));
+ WaitableMessageLoopEvent event;
+ CallInitialize(event.GetPipelineStatusCB());
+ event.RunAndWaitForStatus(expected);
+ }
+
+ void CallInitialize(const PipelineStatusCB& status_cb) {
VideoRendererBase::VideoDecoderList decoders;
decoders.push_back(decoder_);
-
- WaitableMessageLoopEvent event;
renderer_->Initialize(
- demuxer_stream_,
- decoders,
- event.GetPipelineStatusCB(),
+ demuxer_stream_, decoders, status_cb,
base::Bind(&MockStatisticsCB::OnStatistics,
base::Unretained(&statistics_cb_object_)),
base::Bind(&VideoRendererBaseTest::OnTimeUpdate,
base::Unretained(this)),
base::Bind(&VideoRendererBaseTest::OnNaturalSizeChanged,
base::Unretained(this)),
- ended_event_.GetClosure(),
- error_event_.GetPipelineStatusCB(),
+ ended_event_.GetClosure(), error_event_.GetPipelineStatusCB(),
base::Bind(&VideoRendererBaseTest::GetTime, base::Unretained(this)),
base::Bind(&VideoRendererBaseTest::GetDuration,
base::Unretained(this)));
- event.RunAndWaitForStatus(expected);
}
void Play() {
@@ -358,12 +359,44 @@
DISALLOW_COPY_AND_ASSIGN(VideoRendererBaseTest);
};
+TEST_F(VideoRendererBaseTest, DoNothing) {
+ // Test that creation and deletion doesn't depend on calls to Initialize()
+ // and/or Stop().
+}
+
+TEST_F(VideoRendererBaseTest, StopWithoutInitialize) {
+ Stop();
+}
+
TEST_F(VideoRendererBaseTest, Initialize) {
Initialize();
EXPECT_EQ(0, GetCurrentTimestampInMs());
Shutdown();
}
+static void ExpectNotCalled(PipelineStatus) {
+ base::debug::StackTrace stack;
+ ADD_FAILURE() << "Expected callback not to be called\n" << stack.ToString();
+}
+
+TEST_F(VideoRendererBaseTest, StopWhileInitializing) {
+ EXPECT_CALL(*decoder_, Initialize(_, _, _))
+ .WillOnce(RunCallback<1>(PIPELINE_OK));
+ CallInitialize(base::Bind(&ExpectNotCalled));
+ Stop();
+
+ // ~VideoRendererBase() will CHECK() if we left anything initialized.
+}
+
+TEST_F(VideoRendererBaseTest, StopWhileFlushing) {
+ Initialize();
+ Pause();
+ renderer_->Flush(base::Bind(&ExpectNotCalled, PIPELINE_OK));
+ Stop();
+
+ // ~VideoRendererBase() will CHECK() if we left anything initialized.
+}
+
TEST_F(VideoRendererBaseTest, Play) {
Initialize();
Play();
diff --git a/src/media/mp4/mp4_stream_parser.cc b/src/media/mp4/mp4_stream_parser.cc
index a001872..dbbc07b 100644
--- a/src/media/mp4/mp4_stream_parser.cc
+++ b/src/media/mp4/mp4_stream_parser.cc
@@ -502,6 +502,10 @@
StreamParserBuffer::CopyFrom(&frame_buf[0], frame_buf.size(),
runs_->is_keyframe());
#endif
+ if (!stream_buf) {
+ DLOG(WARNING) << "Failed to create StreamParserBuffer";
+ return false;
+ }
if (decrypt_config)
stream_buf->SetDecryptConfig(decrypt_config.Pass());
diff --git a/src/media/player/can_play_type.cc b/src/media/player/can_play_type.cc
index d3880ae..5dc1883 100644
--- a/src/media/player/can_play_type.cc
+++ b/src/media/player/can_play_type.cc
@@ -24,9 +24,32 @@
#include "media/audio/shell_audio_streamer.h"
#include "media/player/crypto/key_systems.h"
#include "media/player/mime_util.h"
+#if defined(OS_STARBOARD)
+#include "starboard/media.h"
+#endif // defined(OS_STARBOARD)
namespace media {
+#if defined(OS_STARBOARD)
+
+std::string CanPlayType(const std::string& content_type,
+ const std::string& key_system) {
+ SbMediaSupportType type =
+ SbMediaCanPlayMimeAndKeySystem(content_type.c_str(), key_system.c_str());
+ switch (type) {
+ case kSbMediaSupportTypeNotSupported:
+ return "";
+ case kSbMediaSupportTypeMaybe:
+ return "maybe";
+ case kSbMediaSupportTypeProbably:
+ return "probably";
+ }
+ NOTREACHED();
+ return "";
+}
+
+#else // defined(OS_STARBOARD)
+
namespace {
bool ContainsAAC51(const std::vector<std::string>& codecs) {
@@ -154,4 +177,6 @@
return kProbably;
}
+#endif // defined(OS_STARBOARD)
+
} // namespace media
diff --git a/src/media/webm/webm_cluster_parser.cc b/src/media/webm/webm_cluster_parser.cc
index 8ec2c3a..035963e 100644
--- a/src/media/webm/webm_cluster_parser.cc
+++ b/src/media/webm/webm_cluster_parser.cc
@@ -23,6 +23,80 @@
return counter_block;
}
+namespace {
+
+uint32 ReadInteger(const uint8* buf, int size) {
+ // Read in the big-endian integer.
+ uint32 value = 0;
+ for (int i = 0; i < size; ++i)
+ value = (value << 8) | buf[i];
+ return value;
+}
+
+bool ExtractSubsamples(const uint8* buf,
+ size_t frame_data_size,
+ size_t num_partitions,
+ std::vector<SubsampleEntry>* subsample_entries) {
+ subsample_entries->clear();
+ uint32 clear_bytes = 0;
+ // Partition is the wall between alternating sections. Partition offsets are
+ // relative to the start of the actual frame data.
+ // Size of clear/cipher sections can be calculated from the difference between
+ // adjacent partition offsets.
+ // Here is an example with 4 partitions (5 sections):
+ // "clear |1 cipher |2 clear |3 cipher |4 clear"
+ // With the first and the last implicit partition included:
+ // "|0 clear |1 cipher |2 clear |3 cipher |4 clear |5"
+ // where partition_offset_0 = 0, partition_offset_5 = frame_data_size
+ // There are three subsamples in the above example:
+ // Subsample0.clear_bytes = partition_offset_1 - partition_offset_0
+ // Subsample0.cypher_bytes = partition_offset_2 - partition_offset_1
+ // ...
+ // Subsample2.clear_bytes = partition_offset_5 - partition_offset_4
+ // Subsample2.cypher_bytes = 0
+ uint32 partition_offset = 0;
+ for (size_t i = 0, offset = 0; i <= num_partitions; ++i) {
+ const uint32 prev_partition_offset = partition_offset;
+ partition_offset =
+ (i == num_partitions)
+ ? frame_data_size
+ : ReadInteger(buf + offset, kWebMEncryptedFramePartitionOffsetSize);
+ offset += kWebMEncryptedFramePartitionOffsetSize;
+ if (partition_offset < prev_partition_offset) {
+ DVLOG(1) << "Partition should not be decreasing " << prev_partition_offset
+ << " " << partition_offset;
+ return false;
+ }
+
+ uint32 cypher_bytes = 0;
+ bool new_subsample_entry = false;
+ // Alternating clear and cipher sections.
+ if ((i % 2) == 0) {
+ clear_bytes = partition_offset - prev_partition_offset;
+ // Generate a new subsample when finishing reading partition offsets.
+ new_subsample_entry = i == num_partitions;
+ } else {
+ cypher_bytes = partition_offset - prev_partition_offset;
+ // Generate a new subsample after seeing a cipher section.
+ new_subsample_entry = true;
+ }
+
+ if (new_subsample_entry) {
+ if (clear_bytes == 0 && cypher_bytes == 0) {
+ DVLOG(1) << "Not expecting >2 partitions with the same offsets.";
+ return false;
+ }
+ SubsampleEntry entry;
+ entry.clear_bytes = clear_bytes;
+ entry.cypher_bytes = cypher_bytes;
+ subsample_entries->push_back(entry);
+ }
+ }
+ return true;
+}
+
+} // namespace
+
WebMClusterParser::WebMClusterParser(
int64 timecode_scale, int audio_track_num, int video_track_num,
const std::string& audio_encryption_key_id,
@@ -237,6 +311,11 @@
StreamParserBuffer::CopyFrom(data, size, is_keyframe);
#endif // defined(__LB_SHELL__) || defined(COBALT)
+ if (!buffer) {
+ DLOG(WARNING) << "Failed to create StreamParserBuffer";
+ return false;
+ }
+
// Every encrypted Block has a signal byte and IV prepended to it. Current
// encrypted WebM request for comments specification is here
// http://wiki.webmproject.org/encryption/webm-encryption-rfc
@@ -247,13 +326,14 @@
<< "Got a block from an encrypted stream with no data.";
return false;
}
- uint8 signal_byte = data[0];
+ const uint8 signal_byte = data[0];
int data_offset = sizeof(signal_byte);
// Setting the DecryptConfig object of the buffer while leaving the
// initialization vector empty will tell the decryptor that the frame is
// unencrypted.
std::string counter_block;
+ std::vector<SubsampleEntry> subsample_entries;
if (signal_byte & kWebMFlagEncryptedFrame) {
if (size < kWebMSignalByteSize + kWebMIvSize) {
@@ -263,26 +343,57 @@
}
counter_block = GenerateCounterBlock(data + data_offset, kWebMIvSize);
data_offset += kWebMIvSize;
+
+ if (signal_byte & kWebMFlagEncryptedFramePartitioned) {
+ if (size < data_offset + kWebMEncryptedFrameNumPartitionsSize) {
+ DVLOG(1) << "Got a partitioned encrypted block with not enough data "
+ << size;
+ return false;
+ }
+
+ const size_t num_partitions = data[data_offset];
+ if (num_partitions == 0) {
+ DVLOG(1) << "Got a partitioned encrypted block with 0 partitions.";
+ return false;
+ }
+ data_offset += kWebMEncryptedFrameNumPartitionsSize;
+ const uint8* partition_data_start = data + data_offset;
+ data_offset += kWebMEncryptedFramePartitionOffsetSize * num_partitions;
+ if (size <= data_offset) {
+ DVLOG(1) << "Got a partitioned encrypted block with "
+ << num_partitions << " partitions but not enough data "
+ << size;
+ return false;
+ }
+ const size_t frame_data_size = size - data_offset;
+ if (!ExtractSubsamples(partition_data_start, frame_data_size,
+ num_partitions, &subsample_entries)) {
+ return false;
+ }
+ }
}
#if defined(__LB_SHELL__) || defined(COBALT)
// Don't copy prepended meta data as it is not used by the decrytor and
// decoder.
- buffer = StreamParserBuffer::CopyFrom(data + data_offset,
+ buffer = StreamParserBuffer::CopyFrom(data + data_offset,
size - data_offset, is_keyframe);
#endif // defined(__LB_SHELL__) || defined(COBALT)
+ if (!buffer) {
+ DLOG(WARNING) << "Failed to create StreamParserBuffer";
+ return false;
+ }
// TODO(fgalligan): Revisit if DecryptConfig needs to be set on unencrypted
// frames after the CDM API is finalized.
// Unencrypted frames of potentially encrypted streams currently set
// DecryptConfig.
- buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(new DecryptConfig(
- encryption_key_id,
- counter_block,
+ buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(
+ new DecryptConfig(encryption_key_id, counter_block,
#if !defined(__LB_SHELL__) && !defined(COBALT)
- data_offset,
+ data_offset,
#endif // !defined(__LB_SHELL__) && !defined(COBALT)
- std::vector<SubsampleEntry>())));
+ subsample_entries)));
}
buffer->SetTimestamp(timestamp);
diff --git a/src/media/webm/webm_constants.h b/src/media/webm/webm_constants.h
index 150134b..c4150ad 100644
--- a/src/media/webm/webm_constants.h
+++ b/src/media/webm/webm_constants.h
@@ -203,8 +203,11 @@
// Current encrypted WebM request for comments specification is here
// http://wiki.webmproject.org/encryption/webm-encryption-rfc
const uint8 kWebMFlagEncryptedFrame = 0x1;
+const uint8 kWebMFlagEncryptedFramePartitioned = 0x2;
const int kWebMIvSize = 8;
const int kWebMSignalByteSize = 1;
+const int kWebMEncryptedFrameNumPartitionsSize = 1;
+const int kWebMEncryptedFramePartitionOffsetSize = 4;
} // namespace media
diff --git a/src/starboard/client_porting/README.md b/src/starboard/client_porting/README.md
index f07658e..75c8435 100644
--- a/src/starboard/client_porting/README.md
+++ b/src/starboard/client_porting/README.md
@@ -22,6 +22,13 @@
files, not headers, so that the preprocessor replacements don't spread
uncontrollably.
+For each `poem`, we try to name files in a consistent, formulaic manner. With
+this scheme, we can easily determine the correct poem header while porting.
+This can also come handy if one were to write a script to assist in porting
+third party libraries. In theory, the script would just look for includes
+in .cc files, where we have available poems and then wrap unprotected includes
+in #if !defined(STARBOARD), and include the poems if STARBOARD is defined.
+
# "eztime" - Easy Time Functions
@@ -35,3 +42,4 @@
`starboard/client_porting/eztime/eztime.h`, or you can include
`starboard/client_porting/poem/eztime_poem.h` in your implementation file to
automatically simulate POSIXy time functions.
+
diff --git a/src/starboard/client_porting/poem/abs_tests.cc b/src/starboard/client_porting/poem/abs_tests.cc
new file mode 100644
index 0000000..cfcc8c1
--- /dev/null
+++ b/src/starboard/client_porting/poem/abs_tests.cc
@@ -0,0 +1,47 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Test basic functionality of abs()
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#ifndef POEM_FULL_EMULATION
+#define POEM_FULL_EMULATION (1)
+#include "starboard/client_porting/poem/stdlib_poem.h"
+#endif
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+TEST(AbsTest, Positive) {
+ EXPECT_EQ(3, abs(3));
+}
+
+TEST(AbsTest, Zero) {
+ EXPECT_EQ(0, abs(0));
+}
+
+TEST(AbsTest, Negative) {
+ EXPECT_EQ(3, abs(-3));
+}
+
+TEST(AbsTest, FloatPositive) {
+ // this converts/truncates argument 3.41223 to 3, and then passes into abs
+ EXPECT_EQ(3, abs(3.41223));
+}
+
+} // namespace
+} // namespace nplb
+} // namespace starboard
diff --git a/src/starboard/client_porting/poem/eztime_poem.h b/src/starboard/client_porting/poem/eztime_poem.h
index 336f577..280b0c6 100644
--- a/src/starboard/client_porting/poem/eztime_poem.h
+++ b/src/starboard/client_porting/poem/eztime_poem.h
@@ -18,6 +18,8 @@
#ifndef STARBOARD_CLIENT_PORTING_POEM_EZTIME_POEM_H_
#define STARBOARD_CLIENT_PORTING_POEM_EZTIME_POEM_H_
+// #if defined(POEM_FULL_EMULATION) && (POEM_FULL_EMULATION)
+
#include "starboard/client_porting/eztime/eztime.h"
#undef time_t
@@ -37,4 +39,6 @@
#define timegm(x) EzTimeTImplodeUTC(x)
#define timelocal(x) EzTimeTImplodeLocal(x)
+// #endif // POEM_FULL_EMULATION
+
#endif // STARBOARD_CLIENT_PORTING_POEM_EZTIME_POEM_H_
diff --git a/src/starboard/client_porting/poem/include_all.c b/src/starboard/client_porting/poem/include_all.c
new file mode 100644
index 0000000..d5be96e
--- /dev/null
+++ b/src/starboard/client_porting/poem/include_all.c
@@ -0,0 +1,23 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Includes all headers in a C context to make sure they compile as C files.
+
+#include "eztime_poem.h"
+#include "stdio_poem.h"
+#include "stdlib_poem.h"
+#include "string_poem.h"
+#include "strings_poem.h"
+#include "wchar_poem.h"
+
diff --git a/src/starboard/client_porting/poem/main.cc b/src/starboard/client_porting/poem/main.cc
new file mode 100644
index 0000000..de25a95
--- /dev/null
+++ b/src/starboard/client_porting/poem/main.cc
@@ -0,0 +1,26 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/event.h"
+#include "starboard/system.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+void SbEventHandle(const SbEvent* event) {
+ if (event->type == kSbEventTypeStart) {
+ SbEventStartData* data = static_cast<SbEventStartData*>(event->data);
+ ::testing::InitGoogleTest(&data->argument_count, data->argument_values);
+ int result = RUN_ALL_TESTS();
+ SbSystemRequestStop(result);
+ }
+}
diff --git a/src/starboard/client_porting/poem/poem.gyp b/src/starboard/client_porting/poem/poem.gyp
index 52233ef..afde08e 100644
--- a/src/starboard/client_porting/poem/poem.gyp
+++ b/src/starboard/client_porting/poem/poem.gyp
@@ -19,11 +19,29 @@
'type': 'static_library',
'sources': [
'eztime_poem.h',
+ 'stdio_poem.h',
+ 'stdlib_poem.h',
+ 'string_poem.h',
+ 'strings_poem.h',
+ 'wchar_poem.h',
],
'dependencies': [
'<(DEPTH)/starboard/client_porting/eztime/eztime.gyp:eztime',
'<(DEPTH)/starboard/starboard.gyp:starboard',
],
},
+ {
+ 'target_name': 'poem_unittests',
+ 'type': '<(gtest_target_type)',
+ 'sources': [
+ 'abs_tests.cc',
+ 'include_all.c',
+ 'main.cc',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ '<(DEPTH)/starboard/starboard.gyp:starboard',
+ ],
+ },
],
}
diff --git a/src/starboard/client_porting/poem/stdio_poem.h b/src/starboard/client_porting/poem/stdio_poem.h
new file mode 100644
index 0000000..761dff1
--- /dev/null
+++ b/src/starboard/client_porting/poem/stdio_poem.h
@@ -0,0 +1,37 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// A poem (POsix EMulation) for functions in stdio.h
+
+#ifndef STARBOARD_CLIENT_PORTING_POEM_STDIO_POEM_H_
+#define STARBOARD_CLIENT_PORTING_POEM_STDIO_POEM_H_
+
+#if defined(POEM_FULL_EMULATION) && (POEM_FULL_EMULATION)
+
+#include "starboard/string.h"
+
+#define wcsncmp(s1, s2, c) SbStringCompareWide(s1, s2, c)
+
+// the following functions can have variable number of arguments
+// and, out of compatibility concerns, we chose to not use
+// __VA_ARGS__ functionality.
+#define vsnprintf SbStringFormat
+#define snprintf SbStringFormatF
+#define sprintf SbStringFormatUnsafeF
+#define vsscanf SbStringScan
+#define sscanf SbStringScanF
+
+#endif // POEM_FULL_EMULATION
+
+#endif // STARBOARD_CLIENT_PORTING_POEM_STDIO_POEM_H_
diff --git a/src/starboard/client_porting/poem/stdlib_poem.h b/src/starboard/client_porting/poem/stdlib_poem.h
new file mode 100644
index 0000000..54c028b
--- /dev/null
+++ b/src/starboard/client_porting/poem/stdlib_poem.h
@@ -0,0 +1,48 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// A poem (POsix EMulation) for functions in stdlib.h
+
+#ifndef STARBOARD_CLIENT_PORTING_POEM_STDLIB_POEM_H_
+#define STARBOARD_CLIENT_PORTING_POEM_STDLIB_POEM_H_
+
+#include "starboard/configuration.h"
+
+SB_C_INLINE int PoemAbs(int x) {
+ if (x < 0)
+ return -x;
+ return x;
+}
+
+#if defined(POEM_FULL_EMULATION) && (POEM_FULL_EMULATION)
+
+#include "starboard/string.h"
+#include "starboard/system.h"
+
+// number conversion functions
+#define strtol(s, o, b) SbStringParseSignedInteger(s, o, b)
+#define atoi(v) SbStringAToI(v)
+#define atol(v) SbStringAToL(v)
+#define strtol(s, o, b) SbStringParseSignedInteger(s, o, b)
+#define strtoul(s, o, b) SbStringParseUnsignedInteger(s, o, b)
+#define strtoull(s, o, b) SbStringParseUInt64(s, o, b)
+#define strtod(s, o) SbStringParseDouble(s, o)
+
+#define qsort(b, ec, ew, c) SbSystemSort(b, ec, ew, c);
+
+#define abs(x) PoemAbs(x)
+
+#endif // POEM_FULL_EMULATION
+
+#endif // STARBOARD_CLIENT_PORTING_POEM_STDLIB_POEM_H_
diff --git a/src/starboard/client_porting/poem/string_poem.h b/src/starboard/client_porting/poem/string_poem.h
new file mode 100644
index 0000000..93cbcd2
--- /dev/null
+++ b/src/starboard/client_porting/poem/string_poem.h
@@ -0,0 +1,119 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// A poem (POsix EMulation) for functions in string.h
+
+#ifndef STARBOARD_CLIENT_PORTING_POEM_STRING_POEM_H_
+#define STARBOARD_CLIENT_PORTING_POEM_STRING_POEM_H_
+
+#include "starboard/string.h"
+
+#ifdef __cplusplus
+// Finds the last occurrence of |character| in |str|, returning a pointer to
+// the found character in the given string, or NULL if not found.
+// Meant to be a drop-in replacement for strchr, C++ signature
+inline char* PoemFindLastCharacter(char* str, int character) {
+ const char* const_str = static_cast<const char*>(str);
+ const char c = static_cast<char>(character);
+ return const_cast<char*>(SbStringFindLastCharacter(const_str, c));
+}
+
+// Finds the last occurrence of |character| in |str|, returning a pointer to
+// the found character in the given string, or NULL if not found.
+// Meant to be a drop-in replacement for strchr, C++ signature
+inline const char* PoemFindLastCharacter(const char* str, int character) {
+ const char c = static_cast<char>(character);
+ return SbStringFindLastCharacter(str, c);
+}
+
+// Finds the first occurrence of |character| in |str|, returning a pointer to
+// the found character in the given string, or NULL if not found.
+// Meant to be a drop-in replacement for strchr
+inline char* PoemFindCharacter(char* str, int character) {
+ const char* const_str = static_cast<const char*>(str);
+ const char c = static_cast<char>(character);
+ return const_cast<char*>(SbStringFindCharacter(const_str, c));
+}
+
+// Finds the first occurrence of |character| in |str|, returning a pointer to
+// the found character in the given string, or NULL if not found.
+// Meant to be a drop-in replacement for strchr
+inline const char* PoemFindCharacter(const char* str, int character) {
+ const char c = static_cast<char>(character);
+ return SbStringFindCharacter(str, c);
+}
+
+#else
+
+// Finds the first occurrence of |character| in |str|, returning a pointer to
+// the found character in the given string, or NULL if not found.
+// Meant to be a drop-in replacement for strchr
+SB_C_INLINE char* PoemFindCharacter(const char* str, int character) {
+ // C-style cast used for C code
+ return (char*)(SbStringFindCharacter(str, character));
+}
+
+// Finds the last occurrence of |character| in |str|, returning a pointer to
+// the found character in the given string, or NULL if not found.
+// Meant to be a drop-in replacement for strchr
+SB_C_INLINE char* PoemFindLastCharacter(const char* str, int character) {
+ // C-style cast used for C code
+ return (char*)(SbStringFindLastCharacter(str, character));
+}
+#endif
+
+// Concatenates |source| onto the end of |out_destination|, presuming it has
+// |destination_size| total characters of storage available. Returns
+// |out_destination|. This method is a drop-in replacement for strncat
+SB_C_INLINE char* PoemConcat(char* out_destination,
+ const char* source,
+ int destination_size) {
+ SbStringConcat(out_destination, source, destination_size);
+ return out_destination;
+}
+
+// Inline wrapper for an unsafe PoemConcat that assumes |out_destination| is
+// big enough. Returns |out_destination|. Meant to be a drop-in replacement for
+// strcat.
+static SB_C_INLINE char* PoemConcatUnsafe(char* out_destination,
+ const char* source) {
+ return PoemConcat(out_destination, source, INT_MAX);
+}
+
+#if defined(POEM_FULL_EMULATION) && (POEM_FULL_EMULATION)
+
+#define strlen(s) SbStringGetLength(s)
+#define strcpy(o, s) SbStringCopyUnsafe(dst, src)
+#define strncpy(o, s, ds) SbStringCopy(o, s, ds)
+#define strcat(o, s) PoemConcatUnsafe(o, s)
+#define strncat(o, s, ds) PoemConcat(o, s, ds)
+#define strdup(s) SbStringDuplicate(s)
+#define strchr(s, c) PoemFindCharacter(s, c)
+#define strrchr(s, c) PoemFindLastCharacter(s, c)
+#define strstr(s, c) SbStringFindString(s, c)
+#define strncmp(s1, s2, c) SbStringCompare(s1, s2, c)
+#define strcmp(s1, s2) SbStringCompareAll(s1, s2)
+
+// number conversion functions
+#define strtol(s, o, b) SbStringParseSignedInteger(s, o, b)
+#define atoi(v) SbStringAToI(v)
+#define atol(v) SbStringAToL(v)
+#define strtol(s, o, b) SbStringParseSignedInteger(s, o, b)
+#define strtoul(s, o, b) SbStringParseUnsignedInteger(s, o, b)
+#define strtoull(s, o, b) SbStringParseUInt64(s, o, b)
+#define strtod(s, o) SbStringParseDouble(s, o)
+
+#endif // POEM_FULL_EMULATION
+
+#endif // STARBOARD_CLIENT_PORTING_POEM_STRING_POEM_H_
diff --git a/src/starboard/client_porting/poem/strings_poem.h b/src/starboard/client_porting/poem/strings_poem.h
new file mode 100644
index 0000000..9c77d36
--- /dev/null
+++ b/src/starboard/client_porting/poem/strings_poem.h
@@ -0,0 +1,29 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// A poem (POsix EMulation) for functions in strings.h
+
+#ifndef STARBOARD_CLIENT_PORTING_POEM_STRINGS_POEM_H_
+#define STARBOARD_CLIENT_PORTING_POEM_STRINGS_POEM_H_
+
+#if defined(POEM_FULL_EMULATION) && (POEM_FULL_EMULATION)
+
+#include "starboard/string.h"
+
+#define strcasecmp(s1, s2) SbStringCompareNoCase(s1, s2)
+#define strncasecmp(s1, s2) SbStringCompareNoCaseN(s1, s2)
+
+#endif // POEM_FULL_EMULATION
+
+#endif // STARBOARD_CLIENT_PORTING_POEM_STRINGS_POEM_H_
diff --git a/src/starboard/client_porting/poem/wchar_poem.h b/src/starboard/client_porting/poem/wchar_poem.h
new file mode 100644
index 0000000..c72ec8d
--- /dev/null
+++ b/src/starboard/client_porting/poem/wchar_poem.h
@@ -0,0 +1,29 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// A poem (POsix EMulation) for functions in wchar.h
+
+#ifndef STARBOARD_CLIENT_PORTING_POEM_WCHAR_POEM_H_
+#define STARBOARD_CLIENT_PORTING_POEM_WCHAR_POEM_H_
+
+#if defined(POEM_FULL_EMULATION) && (POEM_FULL_EMULATION)
+
+#include "starboard/string.h"
+
+#define vswprintf SbStringFormatWide
+#define wcsncmp(s1, s2, c) SbStringCompareWide(s1, s2, c)
+
+#endif // POEM_FULL_EMULATION
+
+#endif // STARBOARD_CLIENT_PORTING_POEM_WCHAR_POEM_H_
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gyp b/src/starboard/linux/x64directfb/starboard_platform.gyp
index e692647..bea20b6 100644
--- a/src/starboard/linux/x64directfb/starboard_platform.gyp
+++ b/src/starboard/linux/x64directfb/starboard_platform.gyp
@@ -119,6 +119,7 @@
'<(DEPTH)/starboard/shared/iso/string_find_string.cc',
'<(DEPTH)/starboard/shared/iso/string_get_length.cc',
'<(DEPTH)/starboard/shared/iso/string_get_length_wide.cc',
+ '<(DEPTH)/starboard/shared/iso/string_parse_double.cc',
'<(DEPTH)/starboard/shared/iso/string_parse_signed_integer.cc',
'<(DEPTH)/starboard/shared/iso/string_parse_uint64.cc',
'<(DEPTH)/starboard/shared/iso/string_parse_unsigned_integer.cc',
@@ -232,7 +233,7 @@
'<(DEPTH)/starboard/shared/pthread/thread_join.cc',
'<(DEPTH)/starboard/shared/pthread/thread_set_local_value.cc',
'<(DEPTH)/starboard/shared/pthread/thread_yield.cc',
- '<(DEPTH)/starboard/shared/signal/crash_signals.cc',
+ '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc',
'<(DEPTH)/starboard/shared/signal/crash_signals.h',
'<(DEPTH)/starboard/shared/starboard/application.cc',
'<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
@@ -257,8 +258,11 @@
'<(DEPTH)/starboard/shared/starboard/log_message.cc',
'<(DEPTH)/starboard/shared/starboard/log_raw_dump_stack.cc',
'<(DEPTH)/starboard/shared/starboard/log_raw_format.cc',
+ '<(DEPTH)/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc',
'<(DEPTH)/starboard/shared/starboard/media/media_is_output_protected.cc',
'<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc',
+ '<(DEPTH)/starboard/shared/starboard/media/mime_parser.cc',
+ '<(DEPTH)/starboard/shared/starboard/media/mime_parser.h',
'<(DEPTH)/starboard/shared/starboard/new.cc',
'<(DEPTH)/starboard/shared/starboard/player/audio_decoder_internal.h',
'<(DEPTH)/starboard/shared/starboard/player/audio_renderer_internal.cc',
diff --git a/src/starboard/linux/x64x11/starboard_platform.gyp b/src/starboard/linux/x64x11/starboard_platform.gyp
index 1609af2..3200d13 100644
--- a/src/starboard/linux/x64x11/starboard_platform.gyp
+++ b/src/starboard/linux/x64x11/starboard_platform.gyp
@@ -82,6 +82,7 @@
'<(DEPTH)/starboard/shared/iso/string_find_string.cc',
'<(DEPTH)/starboard/shared/iso/string_get_length.cc',
'<(DEPTH)/starboard/shared/iso/string_get_length_wide.cc',
+ '<(DEPTH)/starboard/shared/iso/string_parse_double.cc',
'<(DEPTH)/starboard/shared/iso/string_parse_signed_integer.cc',
'<(DEPTH)/starboard/shared/iso/string_parse_uint64.cc',
'<(DEPTH)/starboard/shared/iso/string_parse_unsigned_integer.cc',
@@ -195,7 +196,7 @@
'<(DEPTH)/starboard/shared/pthread/thread_join.cc',
'<(DEPTH)/starboard/shared/pthread/thread_set_local_value.cc',
'<(DEPTH)/starboard/shared/pthread/thread_yield.cc',
- '<(DEPTH)/starboard/shared/signal/crash_signals.cc',
+ '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc',
'<(DEPTH)/starboard/shared/signal/crash_signals.h',
'<(DEPTH)/starboard/shared/starboard/application.cc',
'<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
@@ -218,8 +219,11 @@
'<(DEPTH)/starboard/shared/starboard/log_message.cc',
'<(DEPTH)/starboard/shared/starboard/log_raw_dump_stack.cc',
'<(DEPTH)/starboard/shared/starboard/log_raw_format.cc',
+ '<(DEPTH)/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc',
'<(DEPTH)/starboard/shared/starboard/media/media_is_output_protected.cc',
'<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc',
+ '<(DEPTH)/starboard/shared/starboard/media/mime_parser.cc',
+ '<(DEPTH)/starboard/shared/starboard/media/mime_parser.h',
'<(DEPTH)/starboard/shared/starboard/new.cc',
'<(DEPTH)/starboard/shared/starboard/player/audio_decoder_internal.h',
'<(DEPTH)/starboard/shared/starboard/player/audio_renderer_internal.cc',
diff --git a/src/starboard/media.h b/src/starboard/media.h
index e3dc6d6..89f2608 100644
--- a/src/starboard/media.h
+++ b/src/starboard/media.h
@@ -63,6 +63,20 @@
kSbMediaAudioCodecVorbis,
} SbMediaAudioCodec;
+// Types of media support which is a direct map as the result of canPlayType()
+// specified in the following link:
+// https://www.w3.org/TR/2011/WD-html5-20110113/video.html#dom-navigator-canplaytype
+typedef enum SbMediaSupportType {
+ // The media type cannot be played.
+ kSbMediaSupportTypeNotSupported,
+
+ // Cannot determinate if the media type is playable without playing it.
+ kSbMediaSupportTypeMaybe,
+
+ // The media type seems to be playable.
+ kSbMediaSupportTypeProbably,
+} SbMediaSupportType;
+
// Possible audio connector types.
typedef enum SbMediaAudioConnector {
kSbMediaAudioConnectorNone,
@@ -223,6 +237,22 @@
SB_EXPORT bool SbMediaIsAudioSupported(SbMediaVideoCodec audio_codec,
int64_t bitrate);
+// Returns information on whether the playback of the specific media described
+// by |mime| and encrypted using |key_system| can be played.
+// |mime| contains the mime information of the media in the form of 'video/webm'
+// or 'video/mp4; codecs="avc1.42001E"'. It may include arbitrary parameters
+// like "codecs", "channels", etc..
+// |key_system| should be a lower case in fhe form of
+// "com.example.somesystem" as suggested by
+// https://w3c.github.io/encrypted-media/#key-system
+// that can be matched exactly with known DRM key systems of the platform.
+// When |key_system| is an empty string, the return value is an indication for
+// non-encrypted media.
+// Note that both |mime| and |key_system| cannot be NULL. This function returns
+// kSbMediaSupportNotSupported if any of them is NULL.
+SB_EXPORT SbMediaSupportType
+SbMediaCanPlayMimeAndKeySystem(const char* mime, const char* key_system);
+
// Returns the number of audio outputs currently available on this device. It
// is expected that, even if the number of outputs or their audio configurations
// can't be determined, the platform will at least return a single output that
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index 3761520..ff62b59 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -173,6 +173,7 @@
'string_find_string_test.cc',
'string_format_test.cc',
'string_format_wide_test.cc',
+ 'string_parse_double_test.cc',
'string_parse_signed_integer_test.cc',
'string_parse_uint64_test.cc',
'string_parse_unsigned_integer_test.cc',
diff --git a/src/starboard/nplb/string_parse_double_test.cc b/src/starboard/nplb/string_parse_double_test.cc
new file mode 100644
index 0000000..1197167
--- /dev/null
+++ b/src/starboard/nplb/string_parse_double_test.cc
@@ -0,0 +1,250 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Here we are not trying to do anything comprehensive, just to sanity check
+// that this is hooked up to something.
+
+#include <float.h> // for DBL_MIN
+#include <math.h> // for HUGE_VAL
+#include "starboard/double.h"
+#include "starboard/string.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+// positive number
+TEST(SbStringParseDoubleTest, Positive) {
+ const char kDouble[] = " 123.4";
+ const double kExpected = 123.4;
+ char* end = NULL;
+ EXPECT_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 7, end);
+}
+
+// positive number without decimal
+TEST(SbStringParseDoubleTest, PositiveNoDecimal) {
+ const char kDouble[] = " 123";
+ const double kExpected = 123;
+ char* end = NULL;
+ EXPECT_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 5, end);
+}
+
+// negative number
+TEST(SbStringParseDoubleTest, Negative) {
+ const char kDouble[] = " -123.4";
+ const double kExpected = -123.4;
+ char* end = NULL;
+ EXPECT_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 8, end);
+}
+
+// zero (in case it gets confused with null)
+TEST(SbStringParseDoubleTest, Zero) {
+ const char kDouble[] = "0";
+ const double kExpected = 0;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 1, end);
+}
+
+TEST(SbStringParseDoubleTest, TabSpacesNewLinePrefix) {
+ const char kDouble[] = "\t \n123.5";
+ const double kExpected = 123.5;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 8, end);
+}
+
+TEST(SbStringParseDoubleTest, TabSpacesNewLineSuffix) {
+ const char kDouble[] = "123.5\t \n";
+ const double kExpected = 123.5;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 5, end);
+}
+
+TEST(SbStringParseDoubleTest, ScientificLowerCasePositiveExp) {
+ const char kDouble[] = "123.5e2";
+ const double kExpected = 12350;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 7, end);
+}
+
+TEST(SbStringParseDoubleTest, ScientificLowerCasePositiveExp2) {
+ const char kDouble[] = "123.5e+2";
+ const double kExpected = 12350;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 8, end);
+}
+
+TEST(SbStringParseDoubleTest, ScientificLowerCaseNegativeExp) {
+ const char kDouble[] = "123.5e-2";
+ const double kExpected = 1.235;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 8, end);
+}
+
+TEST(SbStringParseDoubleTest, ScientificUpperCasePositiveExp) {
+ const char kDouble[] = "123.5E2";
+ const double kExpected = 12350;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 7, end);
+}
+
+TEST(SbStringParseDoubleTest, ScientificUpperCasePositiveExp2) {
+ const char kDouble[] = "123.5E+2";
+ const double kExpected = 12350;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 8, end);
+}
+
+TEST(SbStringParseDoubleTest, ScientificUpperCaseNegativeExp) {
+ const char kDouble[] = "123.5E-2";
+ const double kExpected = 1.235;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 8, end);
+}
+
+TEST(SbStringParseDoubleTest, Empty) {
+ const char kDouble[] = "";
+ const double kExpected = 0.0;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 0, end);
+}
+
+TEST(SbStringParseDoubleTest, Space) {
+ const char kDouble[] = " ";
+ const double kExpected = 0.0;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 0, end);
+}
+
+TEST(SbStringParseDoubleTest, AlphaNumerics) {
+ const char kDouble[] = "alskjdfkldd2";
+ const double kExpected = 0.0;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 0, end);
+}
+
+// out of bounds
+TEST(SbStringParseDoubleTest, Huge) {
+ const char kDouble[] = "9e9999";
+ const double kExpected = HUGE_VAL;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 6, end);
+}
+
+TEST(SbStringParseDoubleTest, HugeNeg) {
+ const char kDouble[] = "-9e9999";
+ const double kExpected = -HUGE_VAL;
+ char* end = NULL;
+ EXPECT_DOUBLE_EQ(kExpected, SbStringParseDouble(kDouble, &end));
+ EXPECT_EQ(kDouble + 7, end);
+}
+
+TEST(SbStringParseDoubleTest, Small) {
+ const char kDouble[] = "1e-310";
+ const double kExpected = DBL_MIN;
+ char* end = NULL;
+ double answer(SbStringParseDouble(kDouble, &end));
+ EXPECT_GE(kExpected, answer);
+ EXPECT_GT(answer, 0.0);
+ EXPECT_EQ(kDouble + 6, end);
+}
+
+TEST(SbStringParseDoubleTest, SmallNeg) {
+ const char kDouble[] = "-1e-310";
+ const double kExpected = -DBL_MIN;
+ char* end = NULL;
+ double answer(SbStringParseDouble(kDouble, &end));
+ EXPECT_LE(kExpected, answer);
+ EXPECT_LT(answer, 0.0);
+ EXPECT_EQ(kDouble + 7, end);
+}
+
+// The following tests are disabled until we decide we want to mimic
+// C11 behavior in Starboard. NAN and INF supported was added in C11
+// test NAN, and INFINITY
+TEST(SbStringParseDoubleTest, NaN) {
+ const char kNanDoubles[][4] = {"nan", "naN", "nAn", "nAN",
+ "Nan", "NaN", "NAn", "NAN"};
+ const double kExpected = NAN;
+ char* end = NULL;
+ for (size_t i(0); i != sizeof(kNanDoubles) / sizeof(kNanDoubles[0]); ++i) {
+ EXPECT_TRUE(SbDoubleIsNan(SbStringParseDouble(kNanDoubles[i], &end)));
+ EXPECT_EQ(kNanDoubles[i] + 3, end);
+ }
+}
+
+TEST(SbStringParseDoubleTest, PosInf) {
+ const char kInfDoubles[][4] = {"inf", "inF", "iNf", "iNF",
+ "Inf", "InF", "INf", "INF"};
+ char* end = NULL;
+ for (size_t i(0); i != sizeof(kInfDoubles) / sizeof(kInfDoubles[0]); ++i) {
+ EXPECT_FALSE(SbDoubleIsFinite(SbStringParseDouble(kInfDoubles[i], &end)));
+ EXPECT_EQ(kInfDoubles[i] + 3, end);
+ }
+
+ const char kInfinity[] = "InFinIty";
+ end = NULL;
+ EXPECT_FALSE(SbDoubleIsFinite(SbStringParseDouble(kInfinity, &end)));
+ EXPECT_EQ(kInfinity + 8, end);
+}
+
+TEST(SbStringParseDoubleTest, PosInf2) {
+ const char kInfDoubles[][5] = {"+inf", "+inF", "+iNf", "+iNF",
+ "+Inf", "+InF", "+INf", "+INF"};
+ char* end = NULL;
+ for (size_t i(0); i != sizeof(kInfDoubles) / sizeof(kInfDoubles[0]); ++i) {
+ EXPECT_FALSE(SbDoubleIsFinite(SbStringParseDouble(kInfDoubles[i], &end)));
+ EXPECT_EQ(kInfDoubles[i] + 4, end);
+ }
+
+ const char kInfinity[] = "+InFinIty";
+ end = NULL;
+ EXPECT_FALSE(SbDoubleIsFinite(SbStringParseDouble(kInfinity, &end)));
+ EXPECT_EQ(kInfinity + 9, end);
+}
+
+TEST(SbStringParseDoubleTest, NegInf) {
+ const char kInfDoubles[][5] = {"-inf", "-inF", "-iNf", "-iNF",
+ "-Inf", "-InF", "-INf", "-INF"};
+ char* end = NULL;
+ for (size_t i(0); i != sizeof(kInfDoubles) / sizeof(kInfDoubles[0]); ++i) {
+ EXPECT_FALSE(SbDoubleIsFinite(SbStringParseDouble(kInfDoubles[i], &end)));
+ EXPECT_EQ(kInfDoubles[i] + 4, end);
+ }
+
+ const char kInfinity[] = "-InFinIty";
+ end = NULL;
+ EXPECT_FALSE(SbDoubleIsFinite(SbStringParseDouble(kInfinity, &end)));
+ EXPECT_EQ(kInfinity + 9, end);
+}
+
+} // namespace
+} // namespace nplb
+} // namespace starboard
diff --git a/src/starboard/nplb/system_hide_splash_screen_test.cc b/src/starboard/nplb/system_hide_splash_screen_test.cc
index a97392e..acf3657 100644
--- a/src/starboard/nplb/system_hide_splash_screen_test.cc
+++ b/src/starboard/nplb/system_hide_splash_screen_test.cc
@@ -16,12 +16,18 @@
// this is hooked up to something.
#include "starboard/system.h"
+#include "starboard/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace starboard {
namespace nplb {
namespace {
+void* ThreadFunc(void* context) {
+ SbSystemHideSplashScreen();
+ return NULL;
+}
+
TEST(SbSystemHideSplashScreenTest, SunnyDay) {
// Function returns no result, and correct execution cannot be determined
// programatically, but we should at least be able to call it twice without
@@ -30,6 +36,16 @@
SbSystemHideSplashScreen();
}
+TEST(SbSystemHideSplashScreenTest, SunnyDayNewThread) {
+ // We should be able to call the function from any thread.
+ const char kThreadName[] = "HideSplashTest";
+ SbThread thread = SbThreadCreate(0 /*stack_size*/, kSbThreadPriorityNormal,
+ kSbThreadNoAffinity, true /*joinable*/,
+ kThreadName, ThreadFunc, NULL /*context*/);
+ EXPECT_TRUE(SbThreadIsValid(thread));
+ SbThreadJoin(thread, NULL /*out_return*/);
+}
+
} // namespace
} // namespace nplb
} // namespace starboard
diff --git a/src/starboard/raspi/1/gyp_configuration.gypi b/src/starboard/raspi/1/gyp_configuration.gypi
index 13f0753..67a0ee9 100644
--- a/src/starboard/raspi/1/gyp_configuration.gypi
+++ b/src/starboard/raspi/1/gyp_configuration.gypi
@@ -21,6 +21,7 @@
'in_app_dial%': 0,
'sysroot%': '/',
'gl_type': 'system_gles2',
+ 'image_cache_size_in_bytes': 32 * 1024 * 1024,
# This should have a default value in cobalt/base.gypi. See the comment
# there for acceptable values for this variable.
diff --git a/src/starboard/raspi/1/starboard_platform.gyp b/src/starboard/raspi/1/starboard_platform.gyp
index 7206d0c..e66dd31 100644
--- a/src/starboard/raspi/1/starboard_platform.gyp
+++ b/src/starboard/raspi/1/starboard_platform.gyp
@@ -88,6 +88,7 @@
'<(DEPTH)/starboard/shared/iso/string_find_string.cc',
'<(DEPTH)/starboard/shared/iso/string_get_length.cc',
'<(DEPTH)/starboard/shared/iso/string_get_length_wide.cc',
+ '<(DEPTH)/starboard/shared/iso/string_parse_double.cc',
'<(DEPTH)/starboard/shared/iso/string_parse_signed_integer.cc',
'<(DEPTH)/starboard/shared/iso/string_parse_uint64.cc',
'<(DEPTH)/starboard/shared/iso/string_parse_unsigned_integer.cc',
@@ -225,8 +226,11 @@
'<(DEPTH)/starboard/shared/starboard/log_message.cc',
'<(DEPTH)/starboard/shared/starboard/log_raw_dump_stack.cc',
'<(DEPTH)/starboard/shared/starboard/log_raw_format.cc',
+ '<(DEPTH)/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc',
'<(DEPTH)/starboard/shared/starboard/media/media_is_output_protected.cc',
'<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc',
+ '<(DEPTH)/starboard/shared/starboard/media/mime_parser.cc',
+ '<(DEPTH)/starboard/shared/starboard/media/mime_parser.h',
'<(DEPTH)/starboard/shared/starboard/new.cc',
'<(DEPTH)/starboard/shared/starboard/player/audio_decoder_internal.h',
'<(DEPTH)/starboard/shared/starboard/player/audio_renderer_internal.cc',
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
index 784947a..be5a4ba 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
@@ -90,9 +90,14 @@
int frame_decoded = 0;
int result =
avcodec_decode_audio4(codec_context_, av_frame_, &frame_decoded, &packet);
- SB_DCHECK(result == input_buffer.size())
- << result << " " << input_buffer.size() << " " << frame_decoded;
- SB_DCHECK(frame_decoded == 1);
+ if (result != input_buffer.size() || frame_decoded != 1) {
+ // TODO: Consider fill it with silence.
+ SB_DLOG(WARNING) << "avcodec_decode_audio4() failed with result: " << result
+ << " with input buffer size: " << input_buffer.size()
+ << " and frame decoded: " << frame_decoded;
+ output->clear();
+ return;
+ }
int decoded_audio_size = av_samples_get_buffer_size(
NULL, codec_context_->channels, av_frame_->nb_samples,
@@ -106,6 +111,7 @@
audio_header_.samples_per_second, av_frame_->nb_samples,
av_frame_->extended_data, reinterpret_cast<uint8_t*>(&(*output)[0]));
} else {
+ // TODO: Consider fill it with silence.
SB_LOG(ERROR) << "Decoded audio frame is empty.";
output->clear();
}
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
index d087ab9..5174f70 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
@@ -38,11 +38,9 @@
}
int AllocateBuffer(AVCodecContext* codec_context, AVFrame* frame) {
- SB_DCHECK(codec_context->pix_fmt == PIX_FMT_YUV420P ||
- codec_context->pix_fmt == PIX_FMT_YUVJ420P)
- << "Invalid pix_fmt " << codec_context->pix_fmt;
if (codec_context->pix_fmt != PIX_FMT_YUV420P &&
codec_context->pix_fmt != PIX_FMT_YUVJ420P) {
+ SB_DLOG(WARNING) << "Unsupported pix_fmt " << codec_context->pix_fmt;
return AVERROR(EINVAL);
}
diff --git a/src/starboard/shared/iso/string_parse_double.cc b/src/starboard/shared/iso/string_parse_double.cc
new file mode 100644
index 0000000..6a51e52
--- /dev/null
+++ b/src/starboard/shared/iso/string_parse_double.cc
@@ -0,0 +1,23 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/string.h"
+
+#include <stdlib.h>
+#include "starboard/log.h"
+
+double SbStringParseDouble(const char* start, char** out_end) {
+ SB_DCHECK(start != NULL) << "start must be a valid pointer";
+ return strtod(start, out_end);
+}
diff --git a/src/starboard/shared/signal/crash_signals_sigaction.cc b/src/starboard/shared/signal/crash_signals_sigaction.cc
new file mode 100644
index 0000000..735e506
--- /dev/null
+++ b/src/starboard/shared/signal/crash_signals_sigaction.cc
@@ -0,0 +1,89 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/signal/crash_signals.h"
+
+#include <signal.h>
+
+#include "starboard/configuration.h"
+#include "starboard/log.h"
+#include "starboard/memory.h"
+#include "starboard/system.h"
+
+namespace starboard {
+namespace shared {
+namespace signal {
+
+namespace {
+
+const int kSignalsToTrap[] = {
+ SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV,
+};
+
+const char* GetSignalName(int signal_id) {
+ switch (signal_id) {
+ case SIGABRT:
+ return "SIGABRT";
+ case SIGFPE:
+ return "SIGFPE";
+ case SIGILL:
+ return "SIGILL";
+ case SIGINT:
+ return "SIGINT";
+ case SIGSEGV:
+ return "SIGSEGV";
+ default:
+ return "UNKNOWN SIGNAL";
+ }
+}
+
+typedef void (*SignalHandlerFunction)(int);
+
+void SetSignalHandler(int signal_id, SignalHandlerFunction handler) {
+ struct sigaction action = {0};
+
+ action.sa_handler = handler;
+ action.sa_flags = 0;
+ ::sigemptyset(&action.sa_mask);
+
+ ::sigaction(signal_id, &action, NULL);
+}
+
+void DumpStackSignalSafe(int signal_id) {
+ const char* signal_name = GetSignalName(signal_id);
+ SbLogRawFormatF("\nCaught signal: %s (%d)\n", signal_name, signal_id);
+ SbLogFlush();
+ SbLogRawDumpStack(1);
+
+ UninstallCrashSignalHandlers();
+ SbSystemBreakIntoDebugger();
+}
+
+} // namespace
+
+void InstallCrashSignalHandlers() {
+ for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) {
+ SetSignalHandler(kSignalsToTrap[i], &DumpStackSignalSafe);
+ }
+}
+
+void UninstallCrashSignalHandlers() {
+ for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) {
+ SetSignalHandler(kSignalsToTrap[i], SIG_DFL);
+ }
+}
+
+} // namespace signal
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc b/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc
new file mode 100644
index 0000000..9bfd9a7
--- /dev/null
+++ b/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc
@@ -0,0 +1,67 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/media.h"
+
+#include "starboard/character.h"
+#include "starboard/log.h"
+#include "starboard/shared/starboard/media/mime_parser.h"
+#include "starboard/string.h"
+
+using starboard::shared::starboard::media::MimeParser;
+
+SbMediaSupportType SbMediaCanPlayMimeAndKeySystem(const char* mime,
+ const char* key_system) {
+ if (mime == NULL) {
+ SB_DLOG(WARNING) << "mime cannot be NULL";
+ return kSbMediaSupportTypeNotSupported;
+ }
+ if (key_system == NULL) {
+ SB_DLOG(WARNING) << "key_system cannot be NULL";
+ return kSbMediaSupportTypeNotSupported;
+ }
+ if (SbStringGetLength(key_system) != 0) {
+ if (!SbMediaIsSupported(kSbMediaVideoCodecNone, kSbMediaAudioCodecNone,
+ key_system)) {
+ return kSbMediaSupportTypeNotSupported;
+ }
+ }
+ MimeParser parser(mime);
+ if (!parser.is_valid()) {
+ SB_DLOG(WARNING) << mime << " is not a valid mime type";
+ return kSbMediaSupportTypeNotSupported;
+ }
+ if (parser.mime() == "application/octet-stream") {
+ return kSbMediaSupportTypeProbably;
+ }
+ if (parser.mime() == "audio/mp4") {
+ return kSbMediaSupportTypeProbably;
+ }
+ if (parser.mime() == "video/mp4") {
+ return kSbMediaSupportTypeProbably;
+ }
+#if SB_HAS(MEDIA_WEBM_VP9_SUPPORT)
+ if (parser.mime() == "video/webm") {
+ if (!parser.HasParam("codecs")) {
+ return kSbMediaSupportTypeMaybe;
+ }
+ std::string codecs = parser.GetParam("codecs");
+ if (codecs == "vp9") {
+ return kSbMediaSupportTypeProbably;
+ }
+ return kSbMediaSupportTypeNotSupported;
+ }
+#endif // SB_HAS(MEDIA_WEBM_VP9_SUPPORT)
+ return kSbMediaSupportTypeNotSupported;
+}
diff --git a/src/starboard/shared/starboard/media/mime_parser.cc b/src/starboard/shared/starboard/media/mime_parser.cc
new file mode 100644
index 0000000..7db734a
--- /dev/null
+++ b/src/starboard/shared/starboard/media/mime_parser.cc
@@ -0,0 +1,141 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/media/mime_parser.h"
+
+#include <vector>
+
+#include "starboard/character.h"
+#include "starboard/log.h"
+#include "starboard/string.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+
+namespace {
+
+void ToLower(std::string* string) {
+ SB_DCHECK(string);
+ for (size_t i = 0; i < string->size(); ++i) {
+ (*string)[i] = SbCharacterToLower((*string)[i]);
+ }
+}
+
+void Trim(std::string* string) {
+ SB_DCHECK(string);
+ while (!string->empty() && SbCharacterIsSpace(*string->rbegin())) {
+ string->resize(string->size() - 1);
+ }
+ while (!string->empty() && SbCharacterIsSpace(*string->begin())) {
+ string->erase(string->begin());
+ }
+}
+
+bool IsSeparator(char ch, std::string separator) {
+ if (separator.empty()) {
+ return SbCharacterIsSpace(ch);
+ }
+ return separator.find(ch) != separator.npos;
+}
+
+// For any given string, split it into substrings separated by any character in
+// the |separator| string. If |separator| is empty string, treat any white
+// space as separators.
+std::vector<std::string> SplitString(std::string string,
+ std::string separator = "") {
+ std::vector<std::string> result;
+ while (!string.empty()) {
+ Trim(&string);
+ if (string.empty()) {
+ break;
+ }
+ bool added = false;
+ for (size_t i = 0; i < string.size(); ++i) {
+ if (IsSeparator(string[i], separator)) {
+ result.push_back(string.substr(0, i));
+ Trim(&result.back());
+ string = string.substr(i + 1);
+ added = true;
+ break;
+ }
+ }
+ if (!added) {
+ Trim(&string);
+ result.push_back(string);
+ break;
+ }
+ }
+ return result;
+}
+
+} // namespace
+
+MimeParser::MimeParser(std::string mime_with_params) {
+ Trim(&mime_with_params);
+ ToLower(&mime_with_params);
+
+ std::vector<std::string> splits = SplitString(mime_with_params, ";");
+ if (splits.empty()) {
+ return; // It is invalid, leave |mime_| as empty.
+ }
+ mime_ = splits[0];
+ // Mime is in the form of "video/mp4".
+ if (SplitString(mime_, "/").size() != 2) {
+ mime_.clear();
+ return;
+ }
+ splits.erase(splits.begin());
+
+ while (!splits.empty()) {
+ std::string params = *splits.begin();
+ splits.erase(splits.begin());
+
+ // Param is in the form of 'name=value' or 'name="value"'.
+ std::vector<std::string> name_and_value = SplitString(params, "=");
+ if (name_and_value.size() != 2) {
+ mime_.clear();
+ return;
+ }
+ std::string name = name_and_value[0];
+ std::string value = name_and_value[1];
+
+ if (value.size() >= 2 && value[0] == '\"' &&
+ value[value.size() - 1] == '\"') {
+ value.erase(value.begin());
+ value.resize(value.size() - 1);
+ Trim(&value);
+ }
+
+ params_[name] = value;
+ }
+}
+
+bool MimeParser::HasParam(const std::string& name) const {
+ return params_.find(name) != params_.end();
+}
+
+std::string MimeParser::GetParam(const std::string& name) const {
+ std::map<std::string, std::string>::const_iterator iter = params_.find(name);
+ if (iter == params_.end()) {
+ return "";
+ }
+ return iter->second;
+}
+
+} // namespace media
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/starboard/media/mime_parser.h b/src/starboard/shared/starboard/media/mime_parser.h
new file mode 100644
index 0000000..b896b2d
--- /dev/null
+++ b/src/starboard/shared/starboard/media/mime_parser.h
@@ -0,0 +1,54 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_STARBOARD_MEDIA_MIME_PARSER_H_
+#define STARBOARD_SHARED_STARBOARD_MEDIA_MIME_PARSER_H_
+
+#include <map>
+#include <string>
+
+#include "starboard/shared/internal_only.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+
+// This class can be used to parse media mime types with params. For example,
+// the following mime type 'video/mp4; codecs="avc1.4d401e"; width=640' will be
+// parsed into:
+// mime => video/mp4
+// param: codecs => avc1.4d401e
+// param: width => 640
+class MimeParser {
+ public:
+ explicit MimeParser(std::string mime_with_params);
+
+ bool is_valid() const { return !mime_.empty(); }
+ const std::string& mime() const { return mime_; }
+
+ bool HasParam(const std::string& name) const;
+ std::string GetParam(const std::string& name) const;
+
+ private:
+ std::string mime_;
+ std::map<std::string, std::string> params_;
+};
+
+} // namespace media
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_STARBOARD_MEDIA_MIME_PARSER_H_
diff --git a/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc b/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc
new file mode 100644
index 0000000..34a9b16
--- /dev/null
+++ b/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc
@@ -0,0 +1,20 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/media.h"
+
+SbMediaSupportType SbMediaCanPlayMimeAndKeySystem(const char* mime,
+ const char* key_system) {
+ return kSbMediaSupportTypeNotSupported;
+}
diff --git a/src/starboard/shared/stub/string_parse_double.cc b/src/starboard/shared/stub/string_parse_double.cc
new file mode 100644
index 0000000..7ac141b
--- /dev/null
+++ b/src/starboard/shared/stub/string_parse_double.cc
@@ -0,0 +1,21 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/string.h"
+
+double SbStringParseDouble(const char* start, char** out_end) {
+ if (out_end != NULL)
+ *out_end = NULL;
+ return 0.0;
+}
diff --git a/src/starboard/shared/stub/system_raise_platform_error.cc b/src/starboard/shared/stub/system_raise_platform_error.cc
index 4a80cb1..13303cb 100644
--- a/src/starboard/shared/stub/system_raise_platform_error.cc
+++ b/src/starboard/shared/stub/system_raise_platform_error.cc
@@ -38,5 +38,5 @@
break;
}
SB_DLOG(INFO) << "SbSystemRaisePlatformError: " << message;
- return false;
+ return kSbSystemPlatformErrorInvalid;
}
diff --git a/src/starboard/string.h b/src/starboard/string.h
index e8193c0..9b72dfa 100644
--- a/src/starboard/string.h
+++ b/src/starboard/string.h
@@ -36,16 +36,18 @@
// Copies as much |source| as possible into |out_destination| and
// null-terminates it, given that it has |destination_size| characters of
-// storage available. Returns the length of |source|.
+// storage available. Returns the length of |source|. Meant to be a drop-in
+// replacement for strlcpy
SB_EXPORT int SbStringCopy(char* out_destination,
const char* source,
int destination_size);
// Inline wrapper for an unsafe SbStringCopy that assumes |out_destination| is
// big enough. Meant to be a drop-in replacement for strcpy.
-static SB_C_INLINE int SbStringCopyUnsafe(char* out_destination,
- const char* source) {
- return SbStringCopy(out_destination, source, INT_MAX);
+static SB_C_INLINE char* SbStringCopyUnsafe(char* out_destination,
+ const char* source) {
+ SbStringCopy(out_destination, source, INT_MAX);
+ return out_destination;
}
// Same as SbStringCopy but for wide characters.
@@ -54,14 +56,16 @@
int destination_size);
// Concatenates |source| onto the end of |out_destination|, presuming it has
-// |destination_size| total characters of storage available. Returns the length
-// of |source|.
+// |destination_size| total characters of storage available. Returns
+// length of |source|. Meant to be a drop-in replacement for strlcpy
+// Note: This function's signature is NOT compatible with strncat
SB_EXPORT int SbStringConcat(char* out_destination,
const char* source,
int destination_size);
// Inline wrapper for an unsafe SbStringConcat that assumes |out_destination| is
-// big enough. Meant to be a drop-in replacement for strcat.
+// big enough.
+// Note: This function's signature is NOT compatible with strcat.
static SB_C_INLINE int SbStringConcatUnsafe(char* out_destination,
const char* source) {
return SbStringConcat(out_destination, source, INT_MAX);
@@ -77,13 +81,15 @@
SB_EXPORT char* SbStringDuplicate(const char* source);
// Finds the first occurrence of |character| in |str|, returning a pointer to
-// the found character in the given string, or NULL if not found. Meant to be a
-// drop-in replacement for strchr.
+// the found character in the given string, or NULL if not found.
+// NOTE: The function signature of this function does NOT match the function
+// strchr.
SB_EXPORT const char* SbStringFindCharacter(const char* str, char character);
// Finds the last occurrence of |character| in |str|, returning a pointer to the
-// found character in the given string, or NULL if not found. Meant to be a
-// drop-in replacement for strrchr.
+// found character in the given string, or NULL if not found.
+// NOTE: The function signature of this function does NOT match the function
+// strrchr.
SB_EXPORT const char* SbStringFindLastCharacter(const char* str,
char character);
@@ -233,7 +239,7 @@
// Parses a string at the beginning of |start| into a unsigned integer in the
// given |base|. It will place the pointer to the end of the consumed portion
// of the string in |out_end|, if it is provided. Meant to be a drop-in
-// replacement for strtol.
+// replacement for strtoul.
// NOLINTNEXTLINE(runtime/int)
SB_EXPORT unsigned long SbStringParseUnsignedInteger(const char* start,
char** out_end,
@@ -247,6 +253,12 @@
char** out_end,
int base);
+// Parses a string at the beginning of |start| into a double.
+// It will place the pointer to the end of the consumed
+// portion of the string in |out_end|, if it is provided. Meant to be a drop-in
+// replacement for strtod, but explicity declared to return double.
+SB_EXPORT double SbStringParseDouble(const char* start, char** out_end);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp
index e871191..21054dc 100644
--- a/src/starboard/stub/starboard_platform.gyp
+++ b/src/starboard/stub/starboard_platform.gyp
@@ -80,6 +80,7 @@
'<(DEPTH)/starboard/shared/stub/log_raw.cc',
'<(DEPTH)/starboard/shared/stub/log_raw_dump_stack.cc',
'<(DEPTH)/starboard/shared/stub/log_raw_format.cc',
+ '<(DEPTH)/starboard/shared/stub/media_can_play_mime_and_key_system.cc',
'<(DEPTH)/starboard/shared/stub/media_is_output_protected.cc',
'<(DEPTH)/starboard/shared/stub/media_is_supported.cc',
'<(DEPTH)/starboard/shared/stub/media_set_output_protection.cc',
@@ -163,6 +164,7 @@
'<(DEPTH)/starboard/shared/stub/string_format_wide.cc',
'<(DEPTH)/starboard/shared/stub/string_get_length.cc',
'<(DEPTH)/starboard/shared/stub/string_get_length_wide.cc',
+ '<(DEPTH)/starboard/shared/stub/string_parse_double.cc',
'<(DEPTH)/starboard/shared/stub/string_parse_signed_integer.cc',
'<(DEPTH)/starboard/shared/stub/string_parse_uint64.cc',
'<(DEPTH)/starboard/shared/stub/string_parse_unsigned_integer.cc',
diff --git a/src/third_party/mozjs/cobalt_config/include/js-confdefs.h b/src/third_party/mozjs/cobalt_config/include/js-confdefs.h
index d5c09af..28f22d6 100644
--- a/src/third_party/mozjs/cobalt_config/include/js-confdefs.h
+++ b/src/third_party/mozjs/cobalt_config/include/js-confdefs.h
@@ -20,6 +20,11 @@
#define RELEASE_BUILD 1
#endif
+#if defined(COBALT_BUILD_TYPE_DEBUG)
+#define DEBUG 1
+#define JS_DEBUG 1
+#endif
+
// Disabling this will fall back to getenv for locale-specific number
// formatting.
// This can be removed when ENABLE_INTL_API is enabled, which requires a newer
diff --git a/src/third_party/mozjs/js/public/Value.h b/src/third_party/mozjs/js/public/Value.h
index 72b3f38..f2345f4 100644
--- a/src/third_party/mozjs/js/public/Value.h
+++ b/src/third_party/mozjs/js/public/Value.h
@@ -819,6 +819,10 @@
return mozilla::SpecificNaN(0, 0x8000000000000ULL);
}
+/* MSVC with PGO miscompiles this function. */
+#if defined(_MSC_VER)
+# pragma optimize("g", off)
+#endif
static inline double
CanonicalizeNaN(double d)
{
@@ -826,6 +830,9 @@
return GenericNaN();
return d;
}
+#if defined(_MSC_VER)
+# pragma optimize("", on)
+#endif
/*
* JS::Value is the interface for a single JavaScript Engine value. A few
diff --git a/src/third_party/mozjs/js/src/builtin/TestingFunctions.cpp b/src/third_party/mozjs/js/src/builtin/TestingFunctions.cpp
index 24cb2d7..239938f 100644
--- a/src/third_party/mozjs/js/src/builtin/TestingFunctions.cpp
+++ b/src/third_party/mozjs/js/src/builtin/TestingFunctions.cpp
@@ -744,7 +744,7 @@
return true;
}
-#ifdef DEBUG
+#if defined(DEBUG) && !defined(JS_USE_CUSTOM_ALLOCATOR)
static JSBool
OOMAfterAllocations(JSContext *cx, unsigned argc, jsval *vp)
{
@@ -1028,7 +1028,7 @@
" count all things or one of 'object', 'double', 'string', 'function'\n"
" to count only things of that kind."),
-#ifdef DEBUG
+#if defined(DEBUG) && !defined(JS_USE_CUSTOM_ALLOCATOR)
JS_FN_HELP("oomAfterAllocations", OOMAfterAllocations, 1, 0,
"oomAfterAllocations(count)",
" After 'count' js_malloc memory allocations, fail every following allocation\n"
diff --git a/src/third_party/mozjs/js/src/ds/LifoAlloc.h b/src/third_party/mozjs/js/src/ds/LifoAlloc.h
index f2fbb5a..25ea2d3 100644
--- a/src/third_party/mozjs/js/src/ds/LifoAlloc.h
+++ b/src/third_party/mozjs/js/src/ds/LifoAlloc.h
@@ -288,18 +288,17 @@
template <typename T>
T *newArray(size_t count) {
- void *mem = alloc(sizeof(T) * count);
- if (!mem)
- return NULL;
JS_STATIC_ASSERT(mozilla::IsPod<T>::value);
- return (T *) mem;
+ return newArrayUninitialized<T>(count);
}
// Create an array with uninitialized elements of type |T|.
// The caller is responsible for initialization.
template <typename T>
T *newArrayUninitialized(size_t count) {
- return static_cast<T *>(alloc(sizeof(T) * count));
+ if (count & tl::MulOverflowMask<sizeof(T)>::result)
+ return NULL;
+ return static_cast<T *>(alloc(sizeof(T) * count));
}
class Mark {
diff --git a/src/third_party/mozjs/js/src/jit/FixedList.h b/src/third_party/mozjs/js/src/jit/FixedList.h
index d21ae87..54a582f 100644
--- a/src/third_party/mozjs/js/src/jit/FixedList.h
+++ b/src/third_party/mozjs/js/src/jit/FixedList.h
@@ -23,7 +23,7 @@
public:
FixedList()
- : length_(0)
+ : length_(0), list_(NULL)
{ }
// Dynamic memory allocation requires the ability to report failure.
@@ -32,6 +32,8 @@
if (length == 0)
return true;
+ if (length & tl::MulOverflowMask<sizeof(T)>::result)
+ return false;
list_ = (T *)GetIonContext()->temp->allocate(length * sizeof(T));
return list_ != NULL;
}
@@ -46,6 +48,11 @@
}
bool growBy(size_t num) {
+ size_t newlength = length_ + num;
+ if (newlength < length_)
+ return false;
+ if (newlength & tl::MulOverflowMask<sizeof(T)>::result)
+ return false;
T *list = (T *)GetIonContext()->temp->allocate((length_ + num) * sizeof(T));
if (!list)
return false;
diff --git a/src/third_party/mozjs/js/src/jit/IonBuilder.cpp b/src/third_party/mozjs/js/src/jit/IonBuilder.cpp
index a0c70f5..00fd7a0 100644
--- a/src/third_party/mozjs/js/src/jit/IonBuilder.cpp
+++ b/src/third_party/mozjs/js/src/jit/IonBuilder.cpp
@@ -5005,6 +5005,7 @@
// MCall accordingly.
types::StackTypeSet *thisTypes = thisArg->resultTypeSet();
if (thisTypes &&
+ thisTypes->getKnownTypeTag() == JSVAL_TYPE_OBJECT &&
TestAreKnownDOMTypes(cx, thisTypes) &&
TestShouldDOMCall(cx, thisTypes, target, JSJitInfo::Method))
{
diff --git a/src/third_party/mozjs/js/src/jit/IonCaches.cpp b/src/third_party/mozjs/js/src/jit/IonCaches.cpp
index f833d0f..a7ce25d 100644
--- a/src/third_party/mozjs/js/src/jit/IonCaches.cpp
+++ b/src/third_party/mozjs/js/src/jit/IonCaches.cpp
@@ -594,8 +594,19 @@
if (!shape->hasGetterValue() || !shape->getterValue().isObject())
return false;
- return shape->getterValue().toObject().is<JSFunction>() &&
- shape->getterValue().toObject().as<JSFunction>().isNative();
+ if (!shape->getterValue().toObject().is<JSFunction>())
+ return false;
+
+ JSFunction& getter = shape->getterValue().toObject().as<JSFunction>();
+ if (!getter.isNative())
+ return false;
+
+ // Check for a DOM method; those are OK with both inner and outer objects.
+ if (getter.jitInfo())
+ return true;
+
+ // For non-DOM methods, don't cache if obj has an outerObject hook.
+ return !obj->getClass()->ext.outerObject;
}
static bool
diff --git a/src/third_party/mozjs/js/src/jit/MIR.h b/src/third_party/mozjs/js/src/jit/MIR.h
index 17d8f7e..ef1df1b 100644
--- a/src/third_party/mozjs/js/src/jit/MIR.h
+++ b/src/third_party/mozjs/js/src/jit/MIR.h
@@ -77,8 +77,6 @@
class MIRGraph;
class MResumePoint;
-static inline bool isOSRLikeValue (MDefinition *def);
-
// Represents a use of a node.
class MUse : public TempObject, public InlineListNode<MUse>
{
@@ -213,14 +211,16 @@
FixedSlot = 1 << 3, // A member of obj->fixedSlots().
TypedArrayElement = 1 << 4, // A typed array element.
DOMProperty = 1 << 5, // A DOM property
- Last = DOMProperty,
+ TypedArrayLength = 1 << 6,// A typed array's length
+ Last = TypedArrayLength,
Any = Last | (Last - 1),
- NumCategories = 6,
+ NumCategories = 7,
// Indicates load or store.
Store_ = 1 << 31
};
+
AliasSet(uint32_t flags)
: flags_(flags)
{
@@ -4339,9 +4339,7 @@
return congruentIfOperandsEqual(ins);
}
AliasSet getAliasSet() const {
- // The typed array |length| property is immutable, so there is no
- // implicit dependency.
- return AliasSet::None();
+ return AliasSet::Load(AliasSet::TypedArrayLength);
}
};
@@ -8264,17 +8262,6 @@
return (MInstruction *)this;
}
-static inline bool isOSRLikeValue (MDefinition *def) {
- if (def->isOsrValue())
- return true;
-
- if (def->isUnbox())
- if (def->getOperand(0)->isOsrValue())
- return true;
-
- return false;
-}
-
typedef Vector<MDefinition *, 8, IonAllocPolicy> MDefinitionVector;
// Helper functions used to decide how to build MIR.
diff --git a/src/third_party/mozjs/js/src/jit/MIRGenerator.h b/src/third_party/mozjs/js/src/jit/MIRGenerator.h
index ee28baa..1e3316f 100644
--- a/src/third_party/mozjs/js/src/jit/MIRGenerator.h
+++ b/src/third_party/mozjs/js/src/jit/MIRGenerator.h
@@ -60,6 +60,8 @@
template <typename T>
T * allocate(size_t count = 1) {
+ if (count & tl::MulOverflowMask<sizeof(T)>::result)
+ return NULL;
return reinterpret_cast<T *>(temp().allocate(sizeof(T) * count));
}
diff --git a/src/third_party/mozjs/js/src/jit/MIRGraph.h b/src/third_party/mozjs/js/src/jit/MIRGraph.h
index 7ee362c..60c2ef4 100644
--- a/src/third_party/mozjs/js/src/jit/MIRGraph.h
+++ b/src/third_party/mozjs/js/src/jit/MIRGraph.h
@@ -542,11 +542,6 @@
numBlocks_(0)
{ }
- template <typename T>
- T * allocate(size_t count = 1) {
- return reinterpret_cast<T *>(alloc_->allocate(sizeof(T) * count));
- }
-
void addBlock(MBasicBlock *block);
void insertBlockAfter(MBasicBlock *at, MBasicBlock *block);
diff --git a/src/third_party/mozjs/js/src/jit/RangeAnalysis.cpp b/src/third_party/mozjs/js/src/jit/RangeAnalysis.cpp
index c8cbc20..4381d84 100644
--- a/src/third_party/mozjs/js/src/jit/RangeAnalysis.cpp
+++ b/src/third_party/mozjs/js/src/jit/RangeAnalysis.cpp
@@ -536,16 +536,12 @@
return;
Range *range = NULL;
- JS_ASSERT(getOperand(0)->op() != MDefinition::Op_OsrValue);
for (size_t i = 0; i < numOperands(); i++) {
if (getOperand(i)->block()->earlyAbort()) {
IonSpew(IonSpew_Range, "Ignoring unreachable input %d", getOperand(i)->id());
continue;
}
- if (isOSRLikeValue(getOperand(i)))
- continue;
-
Range *input = getOperand(i)->range();
if (!input) {
diff --git a/src/third_party/mozjs/js/src/jsdbgapi.cpp b/src/third_party/mozjs/js/src/jsdbgapi.cpp
index 7021e16..08fc0bb 100644
--- a/src/third_party/mozjs/js/src/jsdbgapi.cpp
+++ b/src/third_party/mozjs/js/src/jsdbgapi.cpp
@@ -966,8 +966,11 @@
for (NonBuiltinScriptFrameIter i(cx); !i.done(); ++i) {
FrameDescription desc;
desc.script = i.script();
- desc.lineno = PCToLineNumber(i.script(), i.pc());
+ unsigned column = 0;
+ desc.lineno = PCToLineNumber(i.script(), i.pc(), &column);
desc.fun = i.maybeCallee();
+ // Don't zero index.
+ desc.columnno = column + 1;
if (!frames.append(desc))
return NULL;
if (frames.length() == maxFrames)
diff --git a/src/third_party/mozjs/js/src/jsdbgapi.h b/src/third_party/mozjs/js/src/jsdbgapi.h
index 9aadf53..cd19bd2 100644
--- a/src/third_party/mozjs/js/src/jsdbgapi.h
+++ b/src/third_party/mozjs/js/src/jsdbgapi.h
@@ -18,6 +18,7 @@
JSScript *script;
unsigned lineno;
JSFunction *fun;
+ unsigned columnno;
};
struct StackDescription
diff --git a/src/third_party/mozjs/js/src/jsexn.cpp b/src/third_party/mozjs/js/src/jsexn.cpp
index fae9798..cdc2f51 100644
--- a/src/third_party/mozjs/js/src/jsexn.cpp
+++ b/src/third_party/mozjs/js/src/jsexn.cpp
@@ -76,6 +76,7 @@
T funName;
const char *filename;
unsigned ulineno;
+ unsigned ucolumnno;
};
typedef JSStackTraceElemImpl<HeapPtrString> JSStackTraceElem;
@@ -282,7 +283,10 @@
if (!cfilename)
cfilename = "";
frame.filename = cfilename;
- frame.ulineno = PCToLineNumber(script, i.pc());
+ uint32_t column = 0;
+ frame.ulineno = PCToLineNumber(script, i.pc(), &column);
+ // Don't zero index.
+ frame.ucolumnno = column + 1;
}
}
@@ -327,6 +331,7 @@
if (!priv->stackElems[i].filename)
return false;
priv->stackElems[i].ulineno = frames[i].ulineno;
+ priv->stackElems[i].ucolumnno = frames[i].ucolumnno;
}
SetExnPrivate(exnObject, priv);
@@ -510,7 +515,8 @@
if (!sb.appendInflated(element->filename, strlen(element->filename)))
return NULL;
}
- if (!sb.append(':') || !NumberValueToStringBuffer(cx, NumberValue(element->ulineno), sb) ||
+ if (!sb.append(':') || !NumberValueToStringBuffer(cx, NumberValue(element->ulineno), sb) ||
+ !sb.append(':') || !NumberValueToStringBuffer(cx, NumberValue(element->ucolumnno), sb) ||
!sb.append('\n'))
{
return NULL;
diff --git a/src/third_party/mozjs/js/src/jsinfer.cpp b/src/third_party/mozjs/js/src/jsinfer.cpp
index 93c93bf..3a26388 100644
--- a/src/third_party/mozjs/js/src/jsinfer.cpp
+++ b/src/third_party/mozjs/js/src/jsinfer.cpp
@@ -127,6 +127,9 @@
static bool InferSpewColorable()
{
+#if defined(STARBOARD)
+ return false;
+#else
/* Only spew colors on xterm-color to not screw up emacs. */
static bool colorable = false;
static bool checked = false;
@@ -139,6 +142,7 @@
colorable = true;
}
return colorable;
+#endif
}
const char *
@@ -6176,6 +6180,15 @@
// Tracing
/////////////////////////////////////////////////////////////////////
+static void
+CrashAtUnhandlableOOM(const char *reason)
+{
+ char msgbuf[1024];
+ JS_snprintf(msgbuf, sizeof(msgbuf), "[unhandlable oom] %s", reason);
+ MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
+ MOZ_CRASH();
+}
+
void
TypeSet::sweep(Zone *zone)
{
@@ -6200,10 +6213,9 @@
TypeObjectKey **pentry =
HashSetInsert<TypeObjectKey *,TypeObjectKey,TypeObjectKey>
(zone->types.typeLifoAlloc, objectSet, objectCount, object);
- if (pentry)
- *pentry = object;
- else
- zone->types.setPendingNukeTypes();
+ if (!pentry)
+ CrashAtUnhandlableOOM("OOM in ConstraintTypeSet::sweep");
+ *pentry = object;
}
}
setBaseObjectCount(objectCount);
@@ -6283,19 +6295,17 @@
Property *prop = oldArray[i];
if (prop && prop->types.ownProperty(false)) {
Property *newProp = typeLifoAlloc.new_<Property>(*prop);
- if (newProp) {
- Property **pentry =
- HashSetInsert<jsid,Property,Property>
- (typeLifoAlloc, propertySet, propertyCount, prop->id);
- if (pentry) {
- *pentry = newProp;
- newProp->types.sweep(zone());
- } else {
- zone()->types.setPendingNukeTypes();
- }
- } else {
- zone()->types.setPendingNukeTypes();
- }
+ if (!newProp)
+ CrashAtUnhandlableOOM("OOM in TypeObject::sweep");
+
+ Property **pentry =
+ HashSetInsert<jsid,Property,Property>
+ (typeLifoAlloc, propertySet, propertyCount, prop->id);
+ if (!pentry)
+ CrashAtUnhandlableOOM("OOM in TypeObject::sweep");
+
+ *pentry = newProp;
+ newProp->types.sweep(zone());
}
}
setBasePropertyCount(propertyCount);
@@ -6303,12 +6313,11 @@
Property *prop = (Property *) propertySet;
if (prop->types.ownProperty(false)) {
Property *newProp = typeLifoAlloc.new_<Property>(*prop);
- if (newProp) {
- propertySet = (Property **) newProp;
- newProp->types.sweep(zone());
- } else {
- zone()->types.setPendingNukeTypes();
- }
+ if (!newProp)
+ CrashAtUnhandlableOOM("OOM in TypeObject::sweep");
+
+ propertySet = (Property **) newProp;
+ newProp->types.sweep(zone());
} else {
propertySet = NULL;
setBasePropertyCount(0);
diff --git a/src/third_party/mozjs/js/src/jsinferinlines.h b/src/third_party/mozjs/js/src/jsinferinlines.h
index 6f86bba..8cebc8d 100644
--- a/src/third_party/mozjs/js/src/jsinferinlines.h
+++ b/src/third_party/mozjs/js/src/jsinferinlines.h
@@ -1131,19 +1131,21 @@
* probing. TODO: replace these with jshashtables.
*/
const unsigned SET_ARRAY_SIZE = 8;
+const unsigned SET_CAPACITY_OVERFLOW = 1u << 30;
/* Get the capacity of a set with the given element count. */
static inline unsigned
HashSetCapacity(unsigned count)
{
JS_ASSERT(count >= 2);
+ JS_ASSERT(count < SET_CAPACITY_OVERFLOW);
if (count <= SET_ARRAY_SIZE)
return SET_ARRAY_SIZE;
unsigned log2;
JS_FLOOR_LOG2(log2, count);
- return 1 << (log2 + 2);
+ return 1u << (log2 + 2);
}
/* Compute the FNV hash for the low 32 bits of v. */
@@ -1181,6 +1183,9 @@
}
}
+ if (count >= SET_CAPACITY_OVERFLOW)
+ return NULL;
+
count++;
unsigned newCapacity = HashSetCapacity(count);
diff --git a/src/third_party/mozjs/js/src/jsobj.cpp b/src/third_party/mozjs/js/src/jsobj.cpp
index c8fc252..517b501 100644
--- a/src/third_party/mozjs/js/src/jsobj.cpp
+++ b/src/third_party/mozjs/js/src/jsobj.cpp
@@ -279,7 +279,6 @@
if (pobj->isNative()) {
desc->attrs = GetShapeAttributes(shape);
if (desc->attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
- MOZ_ASSERT(desc.isShared());
doGet = false;
if (desc->attrs & JSPROP_GETTER)
desc->getter = CastAsPropertyOp(shape->getterObject());
diff --git a/src/third_party/mozjs/js/src/jspropertytree.cpp b/src/third_party/mozjs/js/src/jspropertytree.cpp
index 2fc39c0..170827c 100644
--- a/src/third_party/mozjs/js/src/jspropertytree.cpp
+++ b/src/third_party/mozjs/js/src/jspropertytree.cpp
@@ -344,6 +344,9 @@
void
js::PropertyTree::dumpShapes(JSRuntime *rt)
{
+#if defined(STARBOARD)
+ return;
+#else
static bool init = false;
static FILE *dumpfp = NULL;
if (!init) {
@@ -372,5 +375,6 @@
}
*/
}
+#endif
}
#endif
diff --git a/src/third_party/mozjs/js/src/jsproxy.cpp b/src/third_party/mozjs/js/src/jsproxy.cpp
index eddf34f..2dbad14 100644
--- a/src/third_party/mozjs/js/src/jsproxy.cpp
+++ b/src/third_party/mozjs/js/src/jsproxy.cpp
@@ -2328,9 +2328,7 @@
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
- bool ok = handler->getOwnPropertyDescriptor(cx, proxy, id, desc, flags);
- MOZ_ASSERT_IF(ok && desc.isShared(), desc.hasGetterOrSetterObject());
- return ok;
+ return handler->getOwnPropertyDescriptor(cx, proxy, id, desc, flags);
}
bool
diff --git a/src/third_party/mozjs/js/src/jsscript.cpp b/src/third_party/mozjs/js/src/jsscript.cpp
index f4db686..88d8a3b 100644
--- a/src/third_party/mozjs/js/src/jsscript.cpp
+++ b/src/third_party/mozjs/js/src/jsscript.cpp
@@ -40,6 +40,10 @@
#include "vm/RegExpObject-inl.h"
#include "vm/ScopeObject-inl.h"
+#ifdef USE_ZLIB
+#include "zlib.h"
+#endif
+
using namespace js;
using namespace js::gc;
using namespace js::frontend;
diff --git a/src/third_party/mozjs/js/src/jstypedarray.cpp b/src/third_party/mozjs/js/src/jstypedarray.cpp
index 53afdc1..8019563 100644
--- a/src/third_party/mozjs/js/src/jstypedarray.cpp
+++ b/src/third_party/mozjs/js/src/jstypedarray.cpp
@@ -623,39 +623,56 @@
ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents,
uint8_t **data)
{
+ MOZ_ASSERT(cx);
+
ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
JSObject *views = *GetViewList(&buffer);
- js::ObjectElements *header = js::ObjectElements::fromElements((js::HeapSlot*)buffer.dataPointer());
- if (buffer.hasDynamicElements() && !buffer.isAsmJSArrayBuffer()) {
+
+ uint32_t byteLen = buffer.byteLength();
+
+ js::ObjectElements *oldHeader = buffer.getElementsHeader();
+ js::ObjectElements *newHeader;
+
+ // If the ArrayBuffer's elements are transferrable, transfer ownership
+ // directly. Otherwise we have to copy the data into new elements.
+ bool stolen = buffer.hasStealableContents();
+ if (stolen) {
+ newHeader = AllocateArrayBufferContents(cx, byteLen, NULL);
+ if (!newHeader)
+ return false;
+
*GetViewList(&buffer) = NULL;
- *contents = header;
+ *contents = oldHeader;
*data = buffer.dataPointer();
- buffer.setFixedElements();
- header = js::ObjectElements::fromElements((js::HeapSlot*)buffer.dataPointer());
+ MOZ_ASSERT(!buffer.isAsmJSArrayBuffer(),
+ "buffer won't be neutered by neuterAsmJSArrayBuffer");
+
+ buffer.elements = newHeader->elements();
} else {
- uint32_t length = buffer.byteLength();
- js::ObjectElements *newheader =
- AllocateArrayBufferContents(cx, length, buffer.dataPointer());
- if (!newheader) {
- js_ReportOutOfMemory(cx);
+ js::ObjectElements *headerCopy =
+ AllocateArrayBufferContents(cx, byteLen, buffer.dataPointer());
+ if (!headerCopy)
return false;
- }
- ArrayBufferObject::setElementsHeader(newheader, length);
- *contents = newheader;
- *data = reinterpret_cast<uint8_t *>(newheader + 1);
-
+ *contents = headerCopy;
+ *data = reinterpret_cast<uint8_t *>(headerCopy + 1);
if (buffer.isAsmJSArrayBuffer())
ArrayBufferObject::neuterAsmJSArrayBuffer(buffer);
+
+ // Keep using the current elements.
+ newHeader = oldHeader;
}
// Neuter the donor ArrayBuffer and all views of it
- ArrayBufferObject::setElementsHeader(header, 0);
+ uint32_t flags = newHeader->flags;
+ ArrayBufferObject::setElementsHeader(newHeader, 0);
+ newHeader->flags = flags;
GetViewList(&buffer)->init(views);
for (JSObject *view = views; view; view = NextView(view))
TypedArray::neuter(view);
+ newHeader->setIsNeuteredBuffer();
return true;
}
diff --git a/src/third_party/mozjs/js/src/jstypedarray.h b/src/third_party/mozjs/js/src/jstypedarray.h
index f666e52..4751d53 100644
--- a/src/third_party/mozjs/js/src/jstypedarray.h
+++ b/src/third_party/mozjs/js/src/jstypedarray.h
@@ -137,6 +137,24 @@
static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
static void restoreArrayBufferLists(ArrayBufferVector &vector);
+ bool hasStealableContents() const {
+ // Inline elements strictly adhere to the corresponding buffer.
+ if (!hasDynamicElements())
+ return false;
+
+ // asm.js buffer contents are transferred by copying, just like inline
+ // elements.
+ if (isAsmJSArrayBuffer())
+ return false;
+
+ // Neutered contents aren't transferrable because we want a neutered
+ // array's contents to be backed by zeroed memory equal in length to
+ // the original buffer contents. Transferring these contents would
+ // allocate new ones based on the current byteLength, which is 0 for a
+ // neutered array -- not the original byteLength.
+ return !isNeutered();
+ }
+
static bool stealContents(JSContext *cx, JSObject *obj, void **contents,
uint8_t **data);
@@ -164,10 +182,17 @@
*/
inline bool hasData() const;
- inline bool isAsmJSArrayBuffer() const;
+ bool isAsmJSArrayBuffer() const {
+ return getElementsHeader()->isAsmJSArrayBuffer();
+ }
+
static bool prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buffer);
static void neuterAsmJSArrayBuffer(ArrayBufferObject &buffer);
static void releaseAsmJSArrayBuffer(FreeOp *fop, JSObject *obj);
+
+ bool isNeutered() const {
+ return getElementsHeader()->isNeuteredBuffer();
+ }
};
/*
diff --git a/src/third_party/mozjs/js/src/jstypedarrayinlines.h b/src/third_party/mozjs/js/src/jstypedarrayinlines.h
index 5af70f5..f26e9cc 100644
--- a/src/third_party/mozjs/js/src/jstypedarrayinlines.h
+++ b/src/third_party/mozjs/js/src/jstypedarrayinlines.h
@@ -56,12 +56,6 @@
return getClass() == &class_;
}
-inline bool
-ArrayBufferObject::isAsmJSArrayBuffer() const
-{
- return getElementsHeader()->isAsmJSArrayBuffer();
-}
-
static inline int32_t
ClampIntForUint8Array(int32_t x)
{
diff --git a/src/third_party/mozjs/js/src/jsutil.cpp b/src/third_party/mozjs/js/src/jsutil.cpp
index bcab124..bd3e182 100644
--- a/src/third_party/mozjs/js/src/jsutil.cpp
+++ b/src/third_party/mozjs/js/src/jsutil.cpp
@@ -20,6 +20,10 @@
#include "js/Utility.h"
+#ifdef USE_ZLIB
+#include "zlib.h"
+#endif
+
using namespace js;
using mozilla::PodArrayZero;
@@ -37,6 +41,32 @@
js_free(addr);
}
+class Compressor
+{
+ /* Number of bytes we should hand to zlib each compressMore() call. */
+ static const size_t CHUNKSIZE = 2048;
+ z_stream zs;
+ const unsigned char *inp;
+ size_t inplen;
+ size_t outbytes;
+
+ public:
+ enum Status {
+ MOREOUTPUT,
+ DONE,
+ CONTINUE,
+ OOM
+ };
+
+ Compressor(const unsigned char *inp, size_t inplen);
+ ~Compressor();
+ bool init();
+ void setOutput(unsigned char *out, size_t outlen);
+ size_t outWritten() const { return outbytes; }
+ /* Compress some of the input. Return true if it should be called again. */
+ Status compressMore();
+};
+
Compressor::Compressor(const unsigned char *inp, size_t inplen)
: inp(inp),
inplen(inplen),
diff --git a/src/third_party/mozjs/js/src/jsutil.h b/src/third_party/mozjs/js/src/jsutil.h
index 64ebee5..9306a26 100644
--- a/src/third_party/mozjs/js/src/jsutil.h
+++ b/src/third_party/mozjs/js/src/jsutil.h
@@ -17,10 +17,6 @@
#include "js/Utility.h"
-#ifdef USE_ZLIB
-#include "zlib.h"
-#endif
-
/* Forward declarations. */
struct JSContext;
@@ -265,31 +261,6 @@
}
#ifdef USE_ZLIB
-class Compressor
-{
- /* Number of bytes we should hand to zlib each compressMore() call. */
- static const size_t CHUNKSIZE = 2048;
- z_stream zs;
- const unsigned char *inp;
- size_t inplen;
- size_t outbytes;
-
- public:
- enum Status {
- MOREOUTPUT,
- DONE,
- CONTINUE,
- OOM
- };
-
- Compressor(const unsigned char *inp, size_t inplen);
- ~Compressor();
- bool init();
- void setOutput(unsigned char *out, size_t outlen);
- size_t outWritten() const { return outbytes; }
- /* Compress some of the input. Return true if it should be called again. */
- Status compressMore();
-};
/*
* Decompress a string. The caller must know the length of the output and
diff --git a/src/third_party/mozjs/js/src/vm/Interpreter.cpp b/src/third_party/mozjs/js/src/vm/Interpreter.cpp
index 9d53ec5..234c7b5 100644
--- a/src/third_party/mozjs/js/src/vm/Interpreter.cpp
+++ b/src/third_party/mozjs/js/src/vm/Interpreter.cpp
@@ -519,13 +519,18 @@
/*
* We must call the thisObject hook in case we are not called from the
* interpreter, where a prior bytecode has computed an appropriate
- * |this| already.
+ * |this| already. But don't do that if fval is a DOM function.
*/
- RootedObject thisObj(cx, &args.thisv().toObject());
- JSObject *thisp = JSObject::thisObject(cx, thisObj);
- if (!thisp)
- return false;
- args.setThis(ObjectValue(*thisp));
+ if (!fval.isObject() || !fval.toObject().is<JSFunction>() ||
+ !fval.toObject().as<JSFunction>().isNative() ||
+ !fval.toObject().as<JSFunction>().jitInfo())
+ {
+ RootedObject thisObj(cx, &args.thisv().toObject());
+ JSObject *thisp = JSObject::thisObject(cx, thisObj);
+ if (!thisp)
+ return false;
+ args.setThis(ObjectValue(*thisp));
+ }
}
if (!Invoke(cx, args))
diff --git a/src/third_party/mozjs/js/src/vm/ObjectImpl.cpp b/src/third_party/mozjs/js/src/vm/ObjectImpl.cpp
index b1ce275..98b97b1 100644
--- a/src/third_party/mozjs/js/src/vm/ObjectImpl.cpp
+++ b/src/third_party/mozjs/js/src/vm/ObjectImpl.cpp
@@ -182,8 +182,10 @@
{
static int throttle = -1;
if (throttle < 0) {
+#if !defined(STARBOARD)
if (const char *var = getenv("JS_CHECK_SHAPE_THROTTLE"))
throttle = atoi(var);
+#endif
if (throttle < 0)
throttle = 0;
}
diff --git a/src/third_party/mozjs/js/src/vm/ObjectImpl.h b/src/third_party/mozjs/js/src/vm/ObjectImpl.h
index 980f935..8eba5da 100644
--- a/src/third_party/mozjs/js/src/vm/ObjectImpl.h
+++ b/src/third_party/mozjs/js/src/vm/ObjectImpl.h
@@ -979,10 +979,11 @@
enum Flags {
CONVERT_DOUBLE_ELEMENTS = 0x1,
ASMJS_ARRAY_BUFFER = 0x2,
+ NEUTERED_BUFFER = 0x4,
// Present only if these elements correspond to an array with
// non-writable length; never present for non-arrays.
- NONWRITABLE_ARRAY_LENGTH = 0x4
+ NONWRITABLE_ARRAY_LENGTH = 0x8
};
private:
@@ -1036,6 +1037,12 @@
void setIsAsmJSArrayBuffer() {
flags |= ASMJS_ARRAY_BUFFER;
}
+ bool isNeuteredBuffer() const {
+ return flags & NEUTERED_BUFFER;
+ }
+ void setIsNeuteredBuffer() {
+ flags |= NEUTERED_BUFFER;
+ }
bool hasNonwritableArrayLength() const {
return flags & NONWRITABLE_ARRAY_LENGTH;
}
diff --git a/src/third_party/mozjs/js/src/vm/SelfHosting.cpp b/src/third_party/mozjs/js/src/vm/SelfHosting.cpp
index 87656bf..aecc895 100644
--- a/src/third_party/mozjs/js/src/vm/SelfHosting.cpp
+++ b/src/third_party/mozjs/js/src/vm/SelfHosting.cpp
@@ -26,6 +26,15 @@
#include "selfhosted.out.h"
+#if defined(DEBUG) && defined(STARBOARD)
+// On Starboard platforms, DEBUG will get #undef'd when we #include zlib.h
+#define STARBOARD_DEBUG
+#endif
+
+#ifdef USE_ZLIB
+#include "zlib.h"
+#endif
+
using namespace js;
using namespace js::selfhosted;
@@ -186,7 +195,7 @@
static JSBool
intrinsic_AssertionFailed(JSContext *cx, unsigned argc, Value *vp)
{
-#ifdef DEBUG
+#if defined(DEBUG) || defined(STARBOARD_DEBUG)
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() > 0) {
// try to dump the informative string
@@ -304,7 +313,7 @@
return true;
}
-#ifdef DEBUG
+#if defined(DEBUG) || defined(STARBOARD_DEBUG)
/*
* Dump(val): Dumps a value for debugging, even in parallel mode.
*/
@@ -630,7 +639,7 @@
JS_FN("intl_numberingSystem", intl_numberingSystem, 1,0),
JS_FN("intl_patternForSkeleton", intl_patternForSkeleton, 2,0),
-#ifdef DEBUG
+#if defined(DEBUG) || defined(STARBOARD_DEBUG)
JS_FN("Dump", intrinsic_Dump, 1,0),
#endif
diff --git a/src/third_party/mozjs/js/src/yarr/BumpPointerAllocator.h b/src/third_party/mozjs/js/src/yarr/BumpPointerAllocator.h
index 44fe538..0dcb1f8 100644
--- a/src/third_party/mozjs/js/src/yarr/BumpPointerAllocator.h
+++ b/src/third_party/mozjs/js/src/yarr/BumpPointerAllocator.h
@@ -34,7 +34,9 @@
namespace WTF {
-#if WTF_CPU_SPARC
+#if defined(STARBOARD)
+#define MINIMUM_BUMP_POOL_SIZE SB_MEMORY_PAGE_SIZE
+#elif WTF_CPU_SPARC
#define MINIMUM_BUMP_POOL_SIZE 0x2000
#elif WTF_CPU_IA64
#define MINIMUM_BUMP_POOL_SIZE 0x4000