Import Cobalt 4.11837
diff --git a/src/third_party/mozjs/js/src/jit/Ion.cpp b/src/third_party/mozjs/js/src/jit/Ion.cpp
index 99f8854..c12df1b 100644
--- a/src/third_party/mozjs/js/src/jit/Ion.cpp
+++ b/src/third_party/mozjs/js/src/jit/Ion.cpp
@@ -69,7 +69,11 @@
 
 #ifdef JS_THREADSAFE
 static bool IonTLSInitialized = false;
+#if defined(STARBOARD)
+static PRTLSIndex IonTLSIndex;
+#else   // defined(STARBOARD)
 static unsigned IonTLSIndex;
+#endif  // defined(STARBOARD)
 
 static inline IonContext *
 CurrentIonContext()
diff --git a/src/third_party/mozjs/js/src/jit/IonBuilder.cpp b/src/third_party/mozjs/js/src/jit/IonBuilder.cpp
index 00fd7a0..55b6818 100644
--- a/src/third_party/mozjs/js/src/jit/IonBuilder.cpp
+++ b/src/third_party/mozjs/js/src/jit/IonBuilder.cpp
@@ -25,7 +25,12 @@
 #include "jstypedarrayinlines.h"
 
 #ifdef JS_THREADSAFE
+#if defined(STARBOARD)
+#include "pr_starboard.h"
+#else
 # include "prthread.h"
+#endif  // defined(STARBOARD)
+
 #endif
 
 using namespace js;
diff --git a/src/third_party/mozjs/js/src/jsapi.cpp b/src/third_party/mozjs/js/src/jsapi.cpp
index 33b7991..85b9856 100644
--- a/src/third_party/mozjs/js/src/jsapi.cpp
+++ b/src/third_party/mozjs/js/src/jsapi.cpp
@@ -5134,7 +5134,7 @@
     const int64_t kFileSize = info.size;
     FileContents buffer(cx);
     buffer.resize(kFileSize);
-    if (SbFileRead(file, buffer.begin(), kFileSize) < 0) {
+    if (SbFileReadAll(file, buffer.begin(), kFileSize) < 0) {
         return NULL;
     }
     JSScript *script = Compile(cx, obj, options, buffer.begin(),
@@ -5519,12 +5519,23 @@
 JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options,
              const char *filename, jsval *rval)
 {
+#if defined(STARBOARD)
+    starboard::ScopedFile file(filename, kSbFileOpenOnly | kSbFileRead, NULL,
+                               NULL);
+    const int64_t kFileSize = file.GetSize();
+    FileContents buffer(cx);
+    buffer.resize(kFileSize);
+    if (file.ReadAll(buffer.begin(), kFileSize) < 0) {
+        return false;
+    }
+#else
     FileContents buffer(cx);
     {
         AutoFile file;
         if (!file.open(cx, filename) || !file.readAll(cx, buffer))
             return false;
     }
+#endif
 
     options.setFileAndLine(filename, 1);
     return Evaluate(cx, obj, options, buffer.begin(), buffer.length(), rval);
diff --git a/src/third_party/mozjs/js/src/jsgc.cpp b/src/third_party/mozjs/js/src/jsgc.cpp
index 5c2e730..78d3d57 100644
--- a/src/third_party/mozjs/js/src/jsgc.cpp
+++ b/src/third_party/mozjs/js/src/jsgc.cpp
@@ -81,6 +81,10 @@
 # include <unistd.h>
 #endif
 
+#if defined(STARBOARD)
+#include "starboard/system.h"
+#endif  // defined(STARBOARD)
+
 #if JS_TRACE_LOGGING
 #include "TraceLogging.h"
 #endif
@@ -2170,6 +2174,8 @@
         SYSTEM_INFO sysinfo;
         GetSystemInfo(&sysinfo);
         ncpus = unsigned(sysinfo.dwNumberOfProcessors);
+#elif defined(STARBOARD)
+        ncpus = SbSystemGetNumberOfProcessors();
 # else
         long n = sysconf(_SC_NPROCESSORS_ONLN);
         ncpus = (n > 0) ? unsigned(n) : 1;
diff --git a/src/third_party/mozjs/js/src/jslock.h b/src/third_party/mozjs/js/src/jslock.h
index b91e1f9..f27c300 100644
--- a/src/third_party/mozjs/js/src/jslock.h
+++ b/src/third_party/mozjs/js/src/jslock.h
@@ -11,6 +11,17 @@
 
 #ifdef JS_THREADSAFE
 
+#if defined(STARBOARD)
+#include "starboard/atomic.h"
+
+#define JS_ATOMIC_INCREMENT(p) SbAtomicBarrier_Increment((SbAtomic32*)(p), 1)
+#define JS_ATOMIC_DECREMENT(p) SbAtomicBarrier_Increment((SbAtomic32*)(p), -1)
+#define JS_ATOMIC_ADD(p, v) \
+  SbAtomicBarrier_Increment((SbAtomic32*)(p), (SbAtomic32)(v))
+#define JS_ATOMIC_SET(p, v) \
+  SbAtomicNoBarrier_Exchange((SbAtomic32*)(p), (SbAtomic32)(v))
+
+#else  // defined(STARBOARD)
 # include "pratom.h"
 # include "prlock.h"
 # include "prcvar.h"
@@ -21,6 +32,7 @@
 # define JS_ATOMIC_DECREMENT(p)      PR_ATOMIC_DECREMENT((int32_t *)(p))
 # define JS_ATOMIC_ADD(p,v)          PR_ATOMIC_ADD((int32_t *)(p), (int32_t)(v))
 # define JS_ATOMIC_SET(p,v)          PR_ATOMIC_SET((int32_t *)(p), (int32_t)(v))
+#endif  // defined(STARBOARD)
 
 namespace js {
     // Defined in jsgc.cpp.
diff --git a/src/third_party/mozjs/js/src/jsscript.h b/src/third_party/mozjs/js/src/jsscript.h
index 9b4c5c1..fea2c4e 100644
--- a/src/third_party/mozjs/js/src/jsscript.h
+++ b/src/third_party/mozjs/js/src/jsscript.h
@@ -19,6 +19,10 @@
 #include "js/RootingAPI.h"
 #include "vm/Shape.h"
 
+#if defined(STARBOARD) && defined(JS_THREADSAFE)
+#include "pr_starboard.h"
+#endif  // defined(STARBOARD) && defined(JS_THREADSAFE)
+
 namespace js {
 
 namespace jit {
diff --git a/src/third_party/mozjs/js/src/jsworkers.cpp b/src/third_party/mozjs/js/src/jsworkers.cpp
index 57b16ea..cbe03b2 100644
--- a/src/third_party/mozjs/js/src/jsworkers.cpp
+++ b/src/third_party/mozjs/js/src/jsworkers.cpp
@@ -16,6 +16,10 @@
 # include "jit/ExecutionModeInlines.h"
 #endif
 
+#if defined(JS_THREADSAFE) && defined(STARBOARD)
+#include "pr_starboard.h"
+#endif  // defined(JS_THREADSAFE) && defined(STARBOARD)
+
 using namespace js;
 
 using mozilla::DebugOnly;
diff --git a/src/third_party/mozjs/js/src/pr_starboard.cc b/src/third_party/mozjs/js/src/pr_starboard.cc
new file mode 100644
index 0000000..239153f
--- /dev/null
+++ b/src/third_party/mozjs/js/src/pr_starboard.cc
@@ -0,0 +1,281 @@
+// 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 "pr_starboard.h"
+
+#include "starboard/condition_variable.h"
+#include "starboard/log.h"
+#include "starboard/memory.h"
+#include "starboard/mutex.h"
+#include "starboard/once.h"
+#include "starboard/queue.h"
+#include "starboard/thread.h"
+#include "starboard/time.h"
+#include "starboard/types.h"
+
+namespace {
+
+typedef starboard::Queue<bool> SetupSignalQueue;
+
+// Utility function to convert a PRInterval to signed 64 bit integer
+// microseconds.
+int64_t PR_IntervalToMicrosecondsInt64(PRIntervalTime ticks) {
+  uint32_t microseconds_as_uint32 = PR_IntervalToMicroseconds(ticks);
+  int64_t microseconds_as_int64 = static_cast<int64_t>(microseconds_as_uint32);
+  return microseconds_as_int64;
+}
+
+// Struct to bundle up arguments to be passed into SbThreadCreate.
+struct ThreadEntryPointWrapperContext {
+  ThreadEntryPointWrapperContext(void* pr_context,
+                                 PRThread* pr_thread,
+                                 PRThreadEntryPoint pr_entry_point,
+                                 SetupSignalQueue* setup_signal_queue)
+      : pr_context(pr_context),
+        pr_thread(pr_thread),
+        pr_entry_point(pr_entry_point),
+        setup_signal_queue(setup_signal_queue) {}
+  void* pr_context;
+  PRThread* pr_thread;
+  PRThreadEntryPoint pr_entry_point;
+  SetupSignalQueue* setup_signal_queue;
+};
+
+// The thread local key that corresponds to where local PRThread* data is held.
+SbThreadLocalKey g_pr_thread_local_key = kSbThreadLocalKeyInvalid;
+// The SbOnceControlStructure to to ensure that the local key is only created
+// once.
+SbOnceControl g_pr_thread_key_once_control = SB_ONCE_INITIALIZER;
+
+void PrThreadDtor(void* value) {
+  PRThread* pr_thread = reinterpret_cast<PRThread*>(value);
+  delete pr_thread;
+}
+
+void InitPrThreadKey() {
+  g_pr_thread_local_key = SbThreadCreateLocalKey(PrThreadDtor);
+}
+
+SbThreadLocalKey GetPrThreadKey() {
+  SB_CHECK(SbOnce(&g_pr_thread_key_once_control, InitPrThreadKey));
+  return g_pr_thread_local_key;
+}
+
+void* ThreadEntryPointWrapper(void* context_as_void_pointer) {
+  ThreadEntryPointWrapperContext* context =
+      reinterpret_cast<ThreadEntryPointWrapperContext*>(
+          context_as_void_pointer);
+  void* pr_context = context->pr_context;
+  PRThreadEntryPoint pr_entry_point = context->pr_entry_point;
+  PRThread* pr_thread = context->pr_thread;
+  SetupSignalQueue* setup_signal_queue = context->setup_signal_queue;
+
+  delete context;
+
+  pr_thread->sb_thread = SbThreadGetCurrent();
+  SbThreadLocalKey key = GetPrThreadKey();
+  SB_CHECK(SbThreadIsValidLocalKey(key));
+  SbThreadSetLocalValue(key, pr_thread);
+
+  setup_signal_queue->Put(true);
+  pr_entry_point(pr_context);
+
+  return NULL;
+}
+
+}  // namespace
+
+PRLock* PR_NewLock() {
+  PRLock* lock = new PRLock();
+  if (!SbMutexCreate(lock)) {
+    delete lock;
+    return NULL;
+  }
+  return lock;
+}
+
+void PR_DestroyLock(PRLock* lock) {
+  SB_DCHECK(lock);
+  SbMutexDestroy(lock);
+  delete lock;
+}
+
+PRCondVar* PR_NewCondVar(PRLock* lock) {
+  SB_DCHECK(lock);
+  PRCondVar* cvar = new PRCondVar();
+  if (!SbConditionVariableCreate(&cvar->sb_condition_variable, lock)) {
+    delete cvar;
+    return NULL;
+  }
+  cvar->lock = lock;
+  return cvar;
+}
+
+void PR_DestroyCondVar(PRCondVar* cvar) {
+  SbConditionVariableDestroy(&cvar->sb_condition_variable);
+  delete cvar;
+}
+
+PRStatus PR_WaitCondVar(PRCondVar* cvar, PRIntervalTime timeout) {
+  SbConditionVariableResult result;
+  if (timeout == PR_INTERVAL_NO_WAIT) {
+    result = SbConditionVariableWaitTimed(&cvar->sb_condition_variable,
+                                          cvar->lock, 0);
+  } else if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+    result = SbConditionVariableWait(&cvar->sb_condition_variable, cvar->lock);
+  } else {
+    int64_t microseconds = PR_IntervalToMicrosecondsInt64(timeout);
+    result = SbConditionVariableWaitTimed(&cvar->sb_condition_variable,
+                                          cvar->lock, microseconds);
+  }
+  return pr_starboard::ToPRStatus(result != kSbConditionVariableFailed);
+}
+
+PRThread* PR_GetCurrentThread() {
+  SbThreadLocalKey key = GetPrThreadKey();
+  SB_CHECK(SbThreadIsValidLocalKey(key));
+
+  PRThread* value = static_cast<PRThread*>(SbThreadGetLocalValue(key));
+  // We could potentially be a thread that was not created through
+  // PR_CreateThread.  In this case, we must allocate a PRThread and do the
+  // setup that would normally have been done in PR_CreateThread.
+  if (!value) {
+    PRThread* pr_thread = new PRThread(SbThreadGetCurrent());
+    SbThreadSetLocalValue(key, pr_thread);
+    value = pr_thread;
+  }
+
+  return value;
+}
+
+uint32_t PR_snprintf(char* out, uint32_t outlen, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  uint32_t ret = PR_vsnprintf(out, outlen, fmt, args);
+  va_end(args);
+  return ret;
+}
+
+PRThread* PR_CreateThread(PRThreadType type,
+                          PRThreadEntryPoint start,
+                          void* arg,
+                          PRThreadPriority priority,
+                          PRThreadScope scope,
+                          PRThreadState state,
+                          PRUint32 stackSize) {
+  int64_t sb_stack_size = static_cast<int64_t>(stackSize);
+
+  SbThreadPriority sb_priority;
+  switch (priority) {
+    case PR_PRIORITY_LOW:
+      sb_priority = kSbThreadPriorityLow;
+      break;
+    case PR_PRIORITY_NORMAL:
+      sb_priority = kSbThreadPriorityNormal;
+      break;
+    case PR_PRIORITY_HIGH:
+      sb_priority = kSbThreadPriorityHigh;
+      break;
+    case PR_PRIORITY_LAST:
+      sb_priority = kSbThreadPriorityHighest;
+      break;
+    default:
+      sb_priority = kSbThreadNoPriority;
+  }
+
+  SbThreadAffinity sb_affinity = kSbThreadNoAffinity;
+
+  SB_DCHECK(state == PR_JOINABLE_THREAD || state == PR_UNJOINABLE_THREAD);
+  bool sb_joinable = (state == PR_JOINABLE_THREAD);
+
+  // This heap allocated PRThread object will have a pointer to it stored in
+  // the newly created child thread's thread local storage.  Once the newly
+  // created child thread finishes, it will be freed in the destructor
+  // associated with it through thread local storage.
+  PRThread* pr_thread = new PRThread(kSbThreadInvalid);
+
+  // Utility queue for the ThreadEntryWrapper to signal us once it's done
+  // running its initial setup and we can safely exit.
+  SetupSignalQueue setup_signal_queue;
+
+  // This heap allocated context object is freed after
+  // ThreadEntryPointWrapper's initial setup is complete, right before the
+  // nspr level entry point is run.
+  ThreadEntryPointWrapperContext* context = new ThreadEntryPointWrapperContext(
+      arg, pr_thread, start, &setup_signal_queue);
+
+  // Note that pr_thread->sb_thread will be set to the correct value in the
+  // setup section of ThreadEntryPointWrapper.  It is done there rather than
+  // here to account for the unlikely but possible case in which we enter the
+  // newly created child thread, and then the child thread passes references
+  // to itself off into its potential children or co-threads that interact
+  // with it before we can copy what SbThreadCreate returns into
+  // pr_thread->sb_thread from this current thread.
+  SbThreadCreate(sb_stack_size, sb_priority, sb_affinity, sb_joinable, NULL,
+                 ThreadEntryPointWrapper, context);
+
+  // Now we must wait for the setup section of ThreadEntryPointWrapper to run
+  // and initialize pr_thread (both the struct itself and the corresponding
+  // new thread's private data) before we can safely return.  We expect to
+  // receive true rather than false by convention.
+  bool setup_signal = setup_signal_queue.Get();
+  SB_DCHECK(setup_signal);
+
+  return pr_thread;
+}
+
+PRStatus PR_CallOnceWithArg(PRCallOnceType* once,
+                            PRCallOnceWithArgFN func,
+                            void* arg) {
+  SB_NOTREACHED() << "Not implemented";
+  return PR_FAILURE;
+}
+
+PRStatus PR_NewThreadPrivateIndex(PRTLSIndex* newIndex,
+                                  PRThreadPrivateDTOR destructor) {
+  SbThreadLocalKey key = SbThreadCreateLocalKey(destructor);
+  if (!SbThreadIsValidLocalKey(key)) {
+    return pr_starboard::ToPRStatus(false);
+  }
+  *newIndex = key;
+  return pr_starboard::ToPRStatus(true);
+}
+
+PRIntervalTime PR_MillisecondsToInterval(PRUint32 milli) {
+  PRUint64 tock = static_cast<PRUint64>(milli);
+  PRUint64 msecPerSec = static_cast<PRInt64>(PR_MSEC_PER_SEC);
+  PRUint64 rounding = static_cast<PRInt64>(PR_MSEC_PER_SEC >> 1);
+  PRUint64 tps = static_cast<PRInt64>(PR_TicksPerSecond());
+
+  tock *= tps;
+  tock += rounding;
+  tock /= msecPerSec;
+
+  PRUint64 ticks = static_cast<PRUint64>(tock);
+  return ticks;
+}
+
+PRUint32 PR_IntervalToMicroseconds(PRIntervalTime ticks) {
+  PRUint64 tock = static_cast<PRInt64>(ticks);
+  PRUint64 usecPerSec = static_cast<PRInt64>(PR_USEC_PER_SEC);
+  PRUint64 tps = static_cast<PRInt64>(PR_TicksPerSecond());
+  PRUint64 rounding = static_cast<PRUint64>(tps) >> 1;
+
+  tock *= usecPerSec;
+  tock += rounding;
+  tock /= tps;
+
+  PRUint32 micro = static_cast<PRUint32>(tock);
+  return micro;
+}
diff --git a/src/third_party/mozjs/js/src/pr_starboard.h b/src/third_party/mozjs/js/src/pr_starboard.h
new file mode 100644
index 0000000..72ff257
--- /dev/null
+++ b/src/third_party/mozjs/js/src/pr_starboard.h
@@ -0,0 +1,185 @@
+// 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.
+
+// This header defines the interface for the starboard based implementation of
+// the subset of nspr that spider monkey 24 depends on.  It should directly
+// match the nspr api, with the exception that accessing thread local data
+// should use PRTLSIndex, rather than PRUintn.
+
+#ifndef PR_STARBOARD_H_
+#define PR_STARBOARD_H_
+
+#include "starboard/condition_variable.h"
+#include "starboard/log.h"
+#include "starboard/memory.h"
+#include "starboard/mutex.h"
+#include "starboard/string.h"
+#include "starboard/thread.h"
+#include "starboard/types.h"
+
+#define PR_CALLBACK
+
+#define PR_MSEC_PER_SEC 1000L
+#define PR_USEC_PER_SEC 1000000L
+#define PR_NSEC_PER_SEC 1000000000L
+#define PR_USEC_PER_MSEC 1000L
+#define PR_NSEC_PER_MSEC 1000000L
+
+typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus;
+
+namespace pr_starboard {
+
+// Utility function to map true to PR_SUCCESS and false to PR_FAILURE.
+static inline PRStatus ToPRStatus(bool result) {
+  return result ? PR_SUCCESS : PR_FAILURE;
+}
+
+}  // namespace pr_starboard
+
+typedef enum PRThreadPriority {
+  PR_PRIORITY_FIRST = 0,
+  PR_PRIORITY_LOW = 0,
+  PR_PRIORITY_NORMAL = 1,
+  PR_PRIORITY_HIGH = 2,
+  PR_PRIORITY_URGENT = 3,
+  PR_PRIORITY_LAST = 3
+} PRThreadPriority;
+
+typedef enum PRThreadScope {
+  PR_LOCAL_THREAD,
+  PR_GLOBAL_THREAD,
+  PR_GLOBAL_BOUND_THREAD
+} PRThreadScope;
+
+typedef enum PRThreadState {
+  PR_JOINABLE_THREAD,
+  PR_UNJOINABLE_THREAD
+} PRThreadState;
+
+typedef enum PRThreadType { PR_USER_THREAD, PR_SYSTEM_THREAD } PRThreadType;
+
+typedef SbThreadLocalKey PRTLSIndex;
+typedef uint32_t PRIntervalTime;
+
+typedef int32_t PRInt32;
+typedef uint32_t PRUint32;
+
+typedef int64_t PRInt64;
+typedef uint64_t PRUint64;
+
+typedef void(PR_CALLBACK* PRThreadPrivateDTOR)(void* priv);
+
+struct PRThread {
+  PRThread(SbThread sb_thread) : sb_thread(sb_thread) {}
+  SbThread sb_thread;
+};
+
+typedef SbMutex PRLock;
+
+#define PR_INTERVAL_NO_WAIT 0UL
+#define PR_INTERVAL_NO_TIMEOUT 0xffffffffUL
+
+struct PRCondVar {
+  SbConditionVariable sb_condition_variable;
+  SbMutex* lock;
+};
+
+PRLock* PR_NewLock();
+
+static inline void PR_Lock(PRLock* lock) {
+  SbMutexAcquire(lock);
+}
+
+static inline void PR_Unlock(PRLock* lock) {
+  SbMutexRelease(lock);
+}
+
+void PR_DestroyLock(PRLock* lock);
+
+PRCondVar* PR_NewCondVar(PRLock* lock);
+
+void PR_DestroyCondVar(PRCondVar* cvar);
+
+PRStatus PR_WaitCondVar(PRCondVar* cvar, PRIntervalTime timeout);
+
+static inline PRStatus PR_NotifyCondVar(PRCondVar* cvar) {
+  return pr_starboard::ToPRStatus(
+      SbConditionVariableSignal(&cvar->sb_condition_variable));
+}
+
+static inline PRStatus PR_NotifyAllCondVar(PRCondVar* cvar) {
+  return pr_starboard::ToPRStatus(
+      SbConditionVariableBroadcast(&cvar->sb_condition_variable));
+}
+
+typedef void (*PRThreadEntryPoint)(void*);
+
+PRThread* PR_CreateThread(PRThreadType type,
+                          PRThreadEntryPoint start,
+                          void* arg,
+                          PRThreadPriority priority,
+                          PRThreadScope scope,
+                          PRThreadState state,
+                          PRUint32 stackSize);
+
+static inline PRStatus PR_JoinThread(PRThread* pr_thread) {
+  SB_DCHECK(pr_thread);
+  SB_DCHECK(SbThreadIsValid(pr_thread->sb_thread));
+  return pr_starboard::ToPRStatus(SbThreadJoin(pr_thread->sb_thread, NULL));
+}
+
+PRThread* PR_GetCurrentThread();
+
+void PR_DetachThread();
+
+PRStatus PR_NewThreadPrivateIndex(PRTLSIndex* newIndex,
+                                  PRThreadPrivateDTOR destructor);
+
+static inline PRStatus PR_SetThreadPrivate(PRTLSIndex index, void* priv) {
+  return pr_starboard::ToPRStatus(SbThreadSetLocalValue(index, priv));
+}
+
+static inline void* PR_GetThreadPrivate(PRTLSIndex index) {
+  return SbThreadGetLocalValue(index);
+}
+
+static inline void PR_SetCurrentThreadName(const char* name) {
+  SbThreadSetName(name);
+}
+
+static inline PRUint32 PR_vsnprintf(char* out,
+                                    PRUint32 outlen,
+                                    const char* fmt,
+                                    va_list ap) {
+  return static_cast<PRUint32>(SbStringFormat(out, outlen, fmt, ap));
+}
+
+PRUint32 PR_snprintf(char* out, PRUint32 outlen, const char* fmt, ...);
+
+PRIntervalTime PR_MillisecondsToInterval(PRUint32 milli);
+
+PRUint32 PR_IntervalToMicroseconds(PRIntervalTime ticks);
+
+struct PRCallOnceType {};
+typedef PRStatus(PR_CALLBACK* PRCallOnceWithArgFN)(void* arg);
+
+PRStatus PR_CallOnceWithArg(PRCallOnceType* once,
+                            PRCallOnceWithArgFN func,
+                            void* arg);
+
+static inline PRUint32 PR_TicksPerSecond() {
+  return 1000;
+}
+
+#endif  // #ifndef PR_STARBOARD_H_
diff --git a/src/third_party/mozjs/js/src/shell/js.cpp b/src/third_party/mozjs/js/src/shell/js.cpp
index 4af5e8d..03d0010 100644
--- a/src/third_party/mozjs/js/src/shell/js.cpp
+++ b/src/third_party/mozjs/js/src/shell/js.cpp
@@ -92,6 +92,7 @@
 #endif
 
 #include "starboard/client_porting/wrap_main/wrap_main.h"
+#include "starboard/memory.h"
 
 using namespace js;
 using namespace js::cli;
@@ -108,6 +109,14 @@
 
 size_t gStackChunkSize = 8192;
 
+#if defined(STARBOARD)
+size_t CalculateStackQuota() {
+    void* stack_high;
+    void* stack_low;
+    SbMemoryGetStackBounds(&stack_high, &stack_low);
+    return 3 * (reinterpret_cast<intptr_t>(stack_high) - reinterpret_cast<intptr_t>(stack_low)) / 4;
+}
+#else
 /*
  * Note: This limit should match the stack limit set by the browser in
  *       js/xpconnect/src/XPCJSRuntime.cpp
@@ -117,9 +126,14 @@
 #else
 size_t gMaxStackSize = 128 * sizeof(size_t) * 1024;
 #endif
+#endif
 
 #ifdef JS_THREADSAFE
+#if defined(STARBOARD)
+static PRTLSIndex gStackBaseThreadIndex;
+#else
 static unsigned gStackBaseThreadIndex;
+#endif  // defined(STARBOARD)
 #else
 static uintptr_t gStackBase;
 #endif
@@ -5422,7 +5436,12 @@
     JS_SetTrustedPrincipals(rt, &shellTrustedPrincipals);
     JS_SetSecurityCallbacks(rt, &securityCallbacks);
 
+#if defined(STARBOARD)
+    // This sets the quota to 3/4 the stack size.
+    JS_SetNativeStackQuota(rt, CalculateStackQuota());
+#else
     JS_SetNativeStackQuota(rt, gMaxStackSize);
+#endif
 
     if (!InitWatchdog(rt))
         return 1;
diff --git a/src/third_party/mozjs/js/src/vm/ForkJoin.cpp b/src/third_party/mozjs/js/src/vm/ForkJoin.cpp
index d0216e6..1f21799 100644
--- a/src/third_party/mozjs/js/src/vm/ForkJoin.cpp
+++ b/src/third_party/mozjs/js/src/vm/ForkJoin.cpp
@@ -7,8 +7,13 @@
 #include "jscntxt.h"
 
 #ifdef JS_THREADSAFE
+#if defined(STARBOARD)
+#include "pr_starboard.h"
+#else  // defined(STARBOARD)
 #  include "prthread.h"
 #  include "prprf.h"
+#endif  // defined(STARBOARD)
+
 #endif
 
 #include "vm/ForkJoin.h"
@@ -208,7 +213,11 @@
     NumForkJoinModes
 };
 
+#if defined(STARBOARD)
+PRTLSIndex ForkJoinSlice::ThreadPrivateIndex;
+#else   // defined(STARBOARD)
 unsigned ForkJoinSlice::ThreadPrivateIndex;
+#endif  // defined(STARBOARD)
 bool ForkJoinSlice::TLSInitialized;
 
 class ParallelDo
diff --git a/src/third_party/mozjs/js/src/vm/ForkJoin.h b/src/third_party/mozjs/js/src/vm/ForkJoin.h
index b961548..aa86021 100644
--- a/src/third_party/mozjs/js/src/vm/ForkJoin.h
+++ b/src/third_party/mozjs/js/src/vm/ForkJoin.h
@@ -360,7 +360,11 @@
 
 #if defined(JS_THREADSAFE) && defined(JS_ION)
     // Initialized by InitializeTLS()
+#if defined(STARBOARD)
+  static PRTLSIndex ThreadPrivateIndex;
+#else   // defined(STARBOARD)
     static unsigned ThreadPrivateIndex;
+#endif  // defined(STARBOARD)
     static bool TLSInitialized;
 #endif
 
diff --git a/src/third_party/mozjs/js/src/vm/Monitor.h b/src/third_party/mozjs/js/src/vm/Monitor.h
index 9aaa504..0da5116 100644
--- a/src/third_party/mozjs/js/src/vm/Monitor.h
+++ b/src/third_party/mozjs/js/src/vm/Monitor.h
@@ -9,6 +9,10 @@
 
 #include "jslock.h"
 
+#if defined(STARBOARD) && defined(JS_THREADSAFE)
+#include "pr_starboard.h"
+#endif  // defined(STARBOARD) && defined(JS_THREADSAFE)
+
 namespace js {
 
 // A base class used for types intended to be used in a parallel
diff --git a/src/third_party/mozjs/js/src/vm/ThreadPool.cpp b/src/third_party/mozjs/js/src/vm/ThreadPool.cpp
index 754ad50..af88bbc 100644
--- a/src/third_party/mozjs/js/src/vm/ThreadPool.cpp
+++ b/src/third_party/mozjs/js/src/vm/ThreadPool.cpp
@@ -11,7 +11,9 @@
 #include "vm/ThreadPool.h"
 
 #ifdef JS_THREADSAFE
+#if !defined(STARBOARD)
 #  include "prthread.h"
+#endif  // !defined(STARBOARD)
 #endif
 
 using namespace js;
@@ -207,8 +209,10 @@
         numWorkers_ = 0;
 
 # ifdef DEBUG
+#if !defined(STARBOARD)
     if (char *jsthreads = getenv("JS_THREADPOOL_SIZE"))
         numWorkers_ = strtol(jsthreads, NULL, 10);
+#endif  // !defined(STARBOARD)
 # endif
 #endif
 
diff --git a/src/third_party/mozjs/js/src/vm/ThreadPool.h b/src/third_party/mozjs/js/src/vm/ThreadPool.h
index 5999341..1b40ae6 100644
--- a/src/third_party/mozjs/js/src/vm/ThreadPool.h
+++ b/src/third_party/mozjs/js/src/vm/ThreadPool.h
@@ -13,9 +13,13 @@
 #include "jsalloc.h"
 
 #ifdef JS_THREADSAFE
+#if defined(STARBOARD)
+#include "pr_starboard.h"
+#else  // defined(STARBOARD)
 #  include "prtypes.h"
 #  include "prlock.h"
 #  include "prcvar.h"
+#endif  // defined(STARBOARD)
 #endif
 
 struct JSContext;
diff --git a/src/third_party/mozjs/mozjs.gyp b/src/third_party/mozjs/mozjs.gyp
index b0c4497..bede0e6 100644
--- a/src/third_party/mozjs/mozjs.gyp
+++ b/src/third_party/mozjs/mozjs.gyp
@@ -34,6 +34,10 @@
       'JS_USE_CUSTOM_ALLOCATOR',
       # Do not export symbols that are declare with JS_PUBLIC_[API|DATA].
       'STATIC_JS_API',
+      # Option that enables support for running multiple threads of JavaScript
+      # code concurrently as long as no objects or strings are shared between
+      # them.
+      'JS_THREADSAFE',
     ],
     'include_dirs': [
       'cobalt_config/include',
@@ -368,7 +372,7 @@
       # Host tool used to generate a header file that defines a huge switch
       # statement for JavaScript keywords.
       'target_name': 'mozjs_keyword_header_gen',
-      'type': '<(final_executable_type)',
+      'type': 'executable',
       'toolsets': ['host'],
       'sources': [
         'js/src/jskwgen.cpp',
@@ -378,7 +382,7 @@
     {
       # Host tool used to generate a header file that defines opcode lengths.
       'target_name': 'mozjs_opcode_length_header_gen',
-      'type': '<(final_executable_type)',
+      'type': 'executable',
       'toolsets': ['host'],
       'sources': [
         'js/src/jsoplengen.cpp',
diff --git a/src/third_party/mozjs/mozjs.gypi b/src/third_party/mozjs/mozjs.gypi
index 6b85ee0..6e45b6f 100644
--- a/src/third_party/mozjs/mozjs.gypi
+++ b/src/third_party/mozjs/mozjs.gypi
@@ -85,6 +85,7 @@
       'js/src/memory_allocator_reporter.cpp',
       'js/src/perf/jsperf.cpp',
       'js/src/perf/pm_stub.cpp',
+      'js/src/pr_starboard.cc',
       'js/src/prmjtime.cpp',
       'js/src/vm/ArgumentsObject.cpp',
       'js/src/vm/CharacterEncoding.cpp',